summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS12
-rw-r--r--COPYING339
-rw-r--r--ChangeLog1089
-rw-r--r--INSTALL58
-rw-r--r--Makefile.am14
-rw-r--r--Makefile.in1060
-rw-r--r--NEWS1
-rw-r--r--README5
-rw-r--r--aclocal.m4896
-rw-r--r--action.c192
-rw-r--r--action.h82
-rw-r--r--cfsysline.c661
-rw-r--r--cfsysline.h68
-rwxr-xr-xcompile142
-rwxr-xr-xconfig.guess1516
-rw-r--r--config.h.in304
-rwxr-xr-xconfig.sub1622
-rwxr-xr-xconfigure9385
-rw-r--r--configure.ac280
-rw-r--r--contrib/README12
-rw-r--r--contrib/delete_mysql52
-rw-r--r--createDB.sql37
-rwxr-xr-xdepcomp584
-rw-r--r--doc/bugs.html46
-rw-r--r--doc/contributors.html60
-rw-r--r--doc/features.html80
-rw-r--r--doc/generic_design.html149
-rw-r--r--doc/history.html94
-rw-r--r--doc/how2help.html59
-rw-r--r--doc/install.html156
-rw-r--r--doc/ipv6.html48
-rw-r--r--doc/manual.html54
-rw-r--r--doc/property_replacer.html148
-rw-r--r--doc/rsconf1_actionexeconlyifpreviousissuspended.html29
-rw-r--r--doc/rsconf1_actionresumeinterval.html30
-rw-r--r--doc/rsconf1_allowedsender.html28
-rw-r--r--doc/rsconf1_controlcharacterescapeprefix.html23
-rw-r--r--doc/rsconf1_debugprintcfsyslinehandlerlist.html22
-rw-r--r--doc/rsconf1_debugprintmodulelist.html22
-rw-r--r--doc/rsconf1_debugprinttemplatelist.html22
-rw-r--r--doc/rsconf1_dircreatemode.html22
-rw-r--r--doc/rsconf1_dirgroup.html22
-rw-r--r--doc/rsconf1_dirowner.html22
-rw-r--r--doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html22
-rw-r--r--doc/rsconf1_droptrailinglfonreception.html22
-rw-r--r--doc/rsconf1_dynafilecachesize.html23
-rw-r--r--doc/rsconf1_escapecontrolcharactersonreceive.html29
-rw-r--r--doc/rsconf1_failonchownfailure.html22
-rw-r--r--doc/rsconf1_filecreatemode.html35
-rw-r--r--doc/rsconf1_filegroup.html22
-rw-r--r--doc/rsconf1_fileowner.html22
-rw-r--r--doc/rsconf1_includeconfig.html44
-rw-r--r--doc/rsconf1_mainmsgqueuesize.html22
-rw-r--r--doc/rsconf1_modload.html22
-rw-r--r--doc/rsconf1_repeatedmsgreduction.html23
-rw-r--r--doc/rsconf1_resetconfigvariables.html22
-rw-r--r--doc/rsconf1_umask.html24
-rw-r--r--doc/rsyslog_conf.html811
-rw-r--r--doc/rsyslog_mysql.html240
-rw-r--r--doc/rsyslog_packages.html40
-rw-r--r--doc/rsyslog_php_syslog_ng.html151
-rw-r--r--doc/rsyslog_recording_pri.html134
-rw-r--r--doc/rsyslog_stunnel.html248
-rw-r--r--doc/status.html43
-rw-r--r--doc/syslog-protocol.html196
-rw-r--r--doc/version_naming.html30
-rwxr-xr-xfreebsd/rsyslogd83
-rw-r--r--iminternal.c189
-rw-r--r--iminternal.h48
-rwxr-xr-xinstall-sh507
-rw-r--r--klogd.c1200
-rw-r--r--klogd.h44
-rw-r--r--ksym.c985
-rw-r--r--ksym_mod.c703
-rw-r--r--ksyms.h35
-rwxr-xr-xliblogging-stub.h7
-rw-r--r--linkedlist.c304
-rw-r--r--linkedlist.h70
-rwxr-xr-xmissing367
-rw-r--r--module-template.h344
-rw-r--r--module.h61
-rw-r--r--modules.c334
-rw-r--r--modules.h100
-rw-r--r--msg.c1642
-rw-r--r--msg.h156
-rw-r--r--net.c242
-rw-r--r--net.h75
-rw-r--r--objomsr.c144
-rw-r--r--objomsr.h44
-rw-r--r--omdiscard.c127
-rw-r--r--omdiscard.h33
-rw-r--r--omfile.c803
-rw-r--r--omfile.h34
-rw-r--r--omfwd.c925
-rw-r--r--omfwd.h33
-rw-r--r--ommysql.c310
-rw-r--r--ommysql.h38
-rw-r--r--omshell.c151
-rw-r--r--omshell.h33
-rw-r--r--omusrmsg.c334
-rw-r--r--omusrmsg.h33
-rw-r--r--outchannel.c279
-rw-r--r--outchannel.h23
-rw-r--r--parse.c555
-rw-r--r--parse.h105
-rw-r--r--pidfile.c147
-rw-r--r--pidfile.h50
-rw-r--r--redhat/rsyslog.conf26
-rw-r--r--redhat/rsyslog.init89
-rw-r--r--redhat/rsyslog.log6
-rw-r--r--redhat/rsyslog.sysconfig12
-rw-r--r--rfc3195d.885
-rw-r--r--rfc3195d.c275
-rw-r--r--rklogd.8441
-rw-r--r--rsyslog.conf.562
-rw-r--r--rsyslog.h147
-rw-r--r--rsyslogd.8586
-rwxr-xr-xslackware/rc.rsyslogd68
-rwxr-xr-xsrUtils.c235
-rwxr-xr-xsrUtils.h66
-rwxr-xr-xstringbuf.c743
-rwxr-xr-xstringbuf.h135
-rw-r--r--syslog.c140
-rw-r--r--syslogd-types.h117
-rw-r--r--syslogd.c6208
-rw-r--r--syslogd.h88
-rw-r--r--tcpsyslog.c692
-rw-r--r--tcpsyslog.h56
-rw-r--r--template.c987
-rw-r--r--template.h92
130 files changed, 44847 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..cd21117
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,12 @@
+Rainer Gerhards <rgerhards@adiscon.com>, Adiscon GmbH
+Michael Meckelein <mmeckelein@hq.adiscon.com>, Adiscon GmbH
+
+Contributors
+Andres Riancho (andres-dot-riancho-at-gmail-dot-com)
+ (alias APR in code files)
+ - supplied regexp functionality for the property replacer - a great feature.
+ thanks!
+Bjoern Kalkbrenner
+ - provided code for the "execute shell script" action
+Peter Vrabec
+ - provided IPv6-enabling code
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..0974d61
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1089 @@
+---------------------------------------------------------------------------
+Version 1.18.2 (rgerhards), 2007-08-13
+- fixed a bug in outchannel code that caused templates to be incorrectly
+ parsed
+- fixed a bug in ommysql that caused a wrong ";template" missing message
+- added some code for unloading modules; not yet fully complete (and we do
+ not yet have loadable modules, so this is no problem)
+- removed debian subdirectory by request of a debian packager (this is a special
+ subdir for debian and there is also no point in maintaining it when there
+ is a debian package available - so I gladly did this) in some cases
+- improved overall doc quality (some pages were quite old) and linked to
+ more of the online resources.
+- improved /contrib/delete_mysql script by adding a host option and some
+ other minor modifications
+---------------------------------------------------------------------------
+Version 1.18.1 (rgerhards), 2007-08-08
+- applied a patch from varmojfekoj which solved a potential segfault
+ of rsyslogd on HUP
+- applied patch from Michel Samia to fix compilation when the pthreads
+ feature is disabled
+- some code cleanup (moved action object to its own file set)
+- add config directive $MainMsgQueueSize, which now allows to configure the
+ queue size dynamically
+- all compile-time settings are now shown in rsyslogd -v, not just the
+ active ones
+- enhanced performance a little bit more
+- added config file directive $ActionResumeInterval
+- fixed a bug that prevented compilation under debian sid
+- added a contrib directory for user-contributed useful things
+---------------------------------------------------------------------------
+Version 1.18.0 (rgerhards), 2007-08-03
+- rsyslog now supports fallback actions when an action did not work. This
+ is a great feature e.g. for backup database servers or backup syslog
+ servers
+- modified rklogd to only change the console log level if -c is specified
+- added feature to use multiple actions inside a single selector
+- implemented $ActionExecOnlyWhenPreviousIsSuspended config directive
+- error messages during startup are now spit out to the configured log
+ destinations
+---------------------------------------------------------------------------
+Version 1.17.6 (rgerhards), 2007-08-01
+- continued to work on output module modularization - basic stage of
+ this work is now FINISHED
+- fixed bug in OMSRcreate() - always returned SR_RET_OK
+- fixed a bug that caused ommysql to always complain about missing
+ templates
+- fixed a mem leak in OMSRdestruct - freeing the object itself was
+ forgotten - thanks to varmojfekoj for the patch
+- fixed a memory leak in syslogd/init() that happend when the config
+ file could not be read - thanks to varmojfekoj for the patch
+- fixed insufficient memory allocation in addAction() and its helpers.
+ The initial fix and idea was developed by mildew, I fine-tuned
+ it a bit. Thanks a lot for the fix, I'd probably had pulled out my
+ hair to find the bug...
+- added output of config file line number when a parsing error occured
+- fixed bug in objomsr.c that caused program to abort in debug mode with
+ an invalid assertion (in some cases)
+- fixed a typo that caused the default template for MySQL to be wrong.
+ thanks to mildew for catching this.
+- added configuration file command $DebugPrintModuleList and
+ $DebugPrintCfSysLineHandlerList
+- fixed an invalid value for the MARK timer - unfortunately, there was
+ a testing aid left in place. This resulted in quite frequent MARK messages
+- added $IncludeConfig config directive
+- applied a patch from mildew to prevent rsyslogd from freezing under heavy
+ load. This could happen when the queue was full. Now, we drop messages
+ but rsyslogd remains active.
+---------------------------------------------------------------------------
+Version 1.17.5 (rgerhards), 2007-07-30
+- continued to work on output module modularization
+- fixed a missing file bug - thanks to Andrea Montanari for reporting
+ this problem
+- fixed a problem with shutting down the worker thread and freeing the
+ selector_t list - this caused messages to be lost, because the
+ message queue was not properly drained before the selectors got
+ destroyed.
+---------------------------------------------------------------------------
+Version 1.17.4 (rgerhards), 2007-07-27
+- continued to work on output module modularization
+- fixed a situation where rsyslogd could create zombie processes
+ thanks to mildew for the patch
+- applied patch from Michel Samia to fix compilation when NOT
+ compiled for pthreads
+---------------------------------------------------------------------------
+Version 1.17.3 (rgerhards), 2007-07-25
+- continued working on output module modularization
+- fixed a bug that caused rsyslogd to segfault on exit (and
+ probably also on HUP), when there was an unsent message in a selector
+ that required forwarding and the dns lookup failed for that selector
+ (yes, it was pretty unlikely to happen;))
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed a memory leak in config file parsing and die()
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- rsyslogd now checks on startup if it is capable to performa any work
+ at all. If it cant, it complains and terminates
+ thanks to Michel Samia for providing the patch!
+- fixed a small memory leak when HUPing syslogd. The allowed sender
+ list now gets freed. thanks to mildew for the patch.
+- changed the way error messages in early startup are logged. They
+ now do no longer use the syslogd code directly but are rather
+ send to stderr.
+---------------------------------------------------------------------------
+Version 1.17.2 (rgerhards), 2007-07-23
+- made the port part of the -r option optional. Needed for backward
+ compatibility with sysklogd
+- replaced system() calls with something more reasonable. Please note that
+ this might break compatibility with some existing configuration files.
+ We accept this in favour of the gained security.
+- removed a memory leak that could occur if timegenerated was used in
+ RFC 3164 format in templates
+- did some preparation in msg.c for advanced multithreading - placed the
+ hooks, but not yet any active code
+- worked further on modularization
+- added $ModLoad MySQL (dummy) config directive
+- added DropTrailingLFOnReception config directive
+---------------------------------------------------------------------------
+Version 1.17.1 (rgerhards), 2007-07-20
+- fixed a bug that caused make install to install rsyslogd and rklogd under
+ the wrong names
+- fixed bug that caused $AllowedSenders to handle IPv6 scopes incorrectly;
+ also fixed but that could grabble $AllowedSender wildcards. Thanks to
+ mildew@gmail.com for the patch
+- minor code cleanup - thanks to Peter Vrabec for the patch
+- fixed minimal memory leak on HUP (caused by templates)
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- fixed another memory leak on HUPing and on exiting rsyslogd
+ again thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- code cleanup (removed compiler warnings)
+- fixed portability bug in configure.ac - thanks to Bartosz Kuźma for patch
+- moved msg object into its own file set
+- added the capability to continue trying to write log files when the
+ file system is full. Functionality based on patch by Martin Schulze
+ to sysklogd package.
+---------------------------------------------------------------------------
+Version 1.17.0 (RGer), 2007-07-17
+- added $RepeatedLineReduction config parameter
+- added $EscapeControlCharactersOnReceive config parameter
+- added $ControlCharacterEscapePrefix config parameter
+- added $DirCreateMode config parameter
+- added $CreateDirs config parameter
+- added $DebugPrintTemplateList config parameter
+- added $ResetConfigVariables config parameter
+- added $FileOwner config parameter
+- added $FileGroup config parameter
+- added $DirOwner config parameter
+- added $DirGroup config parameter
+- added $FailOnChownFailure config parameter
+- added regular expression support to the filter engine
+ thanks to Michel Samia for providing the patch!
+- enhanced $AllowedSender functionality. Credits to mildew@gmail.com for
+ the patch doing that
+ - added IPv6 support
+ - allowed DNS hostnames
+ - allowed DNS wildcard names
+- added new option $DropMsgsWithMaliciousDnsPTRRecords
+- added autoconf so that rfc3195d, rsyslogd and klogd are stored to /sbin
+- added capability to auto-create directories with dynaFiles
+---------------------------------------------------------------------------
+Version 1.16.0 (RGer/Peter Vrabec), 2007-07-13 - The Friday, 13th Release ;)
+- build system switched to autotools
+- removed SYSV preprocessor macro use, replaced with autotools equivalents
+- fixed a bug that caused rsyslogd to segfault when TCP listening was
+ disabled and it terminated
+- added new properties "syslogfacility-text" and "syslogseverity-text"
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- added the -x option to disable hostname dns reslution
+ thanks to varmojfekoj <varmojfekoj@gmail.com> for the patch
+- begun to better modularize syslogd.c - this is an ongoing project; moved
+ type definitions to a separate file
+- removed some now-unused fields from struct filed
+- move file size limit fields in struct field to the "right spot" (the file
+ writing part of the union - f_un.f_file)
+- subdirectories linux and solaris are no longer part of the distribution
+ package. This is not because we cease support for them, but there are no
+ longer any files in them after the move to autotools
+---------------------------------------------------------------------------
+Version 1.15.1 (RGer), 2007-07-10
+- fixed a bug that caused a dynaFile selector to stall when there was
+ an open error with one file
+- improved template processing for dynaFiles; templates are now only
+ looked up during initialization - speeds up processing
+- optimized memory layout in struct filed when compiled with MySQL
+ support
+- fixed a bug that caused compilation without SYSLOG_INET to fail
+- re-enabled the "last message repeated n times" feature. This
+ feature was not taken care of while rsyslogd evolved from sysklogd
+ and it was more or less defunct. Now it is fully functional again.
+- added system properties: $NOW, $YEAR, $MONTH, $DAY, $HOUR, $MINUTE
+- fixed a bug in iovAsString() that caused a memory leak under stress
+ conditions (most probably memory shortage). This was unlikely to
+ ever happen, but it doesn't hurt doing it right
+- cosmetic: defined type "uchar", change all unsigned chars to uchar
+---------------------------------------------------------------------------
+Version 1.15.0 (RGer), 2007-07-05
+- added ability to dynamically generate file names based on templates
+ and thus properties. This was a much-requested feature. It makes
+ life easy when it e.g. comes to splitting files based on the sender
+ address.
+- added $umask and $FileCreateMode config file directives
+- applied a patch from Bartosz Kuzma to compile cleanly under NetBSD
+- checks for extra (unexpected) characters in system config file lines
+ have been added
+- added IPv6 documentation - was accidently missing from CVS
+- begun to change char to unsigned char
+---------------------------------------------------------------------------
+Version 1.14.2 (RGer), 2007-07-03
+** this release fixes all known nits with IPv6 **
+- restored capability to do /etc/service lookup for "syslog"
+ service when -r 0 was given
+- documented IPv6 handling of syslog messages
+- integrate patch from Bartosz Kuźma to make rsyslog compile under
+ Solaris again (the patch replaced a strndup() call, which is not
+ available under Solaris
+- improved debug logging when waiting on select
+- updated rsyslogd man page with new options (-46A)
+---------------------------------------------------------------------------
+Version 1.14.1 (RGer/Peter Vrabec), 2007-06-29
+- added Peter Vrabec's patch for IPv6 TCP
+- prefixed all messages send to stderr in rsyslogd with "rsyslogd: "
+---------------------------------------------------------------------------
+Version 1.14.0 (RGer/Peter Vrabec), 2007-06-28
+- Peter Vrabec provided IPv6 for rsyslog, so we are now IPv6 enabled
+ IPv6 Support is currently for UDP only, TCP is to come soon.
+ AllowedSender configuration does not yet work for IPv6.
+- fixed code in iovCreate() that broke C's strict aliasing rules
+- fixed some char/unsigned char differences that forced the compiler
+ to spit out warning messages
+- updated the Red Hat init script to fix a known issue (thanks to
+ Peter Vrabec)
+---------------------------------------------------------------------------
+Version 1.13.5 (RGer), 2007-06-22
+- made the TCP session limit configurable via command line switch
+ now -t <port>,<max sessions>
+- added man page for rklogd(8) (basically a copy from klogd, but now
+ there is one...)
+- fixed a bug that caused internal messages (e.g. rsyslogd startup) to
+ appear without a tag.
+- removed a minor memory leak that occurred when TAG processing requalified
+ a HOSTNAME to be a TAG (and a TAG already was set).
+- removed potential small memory leaks in MsgSet***() functions. There
+ would be a leak if a property was re-set, something that happened
+ extremely seldom.
+---------------------------------------------------------------------------
+Version 1.13.4 (RGer), 2007-06-18
+- added a new property "PRI-text", which holds the PRI field in
+ textual form (e.g. "syslog.info")
+- added alias "syslogseverity" for "syslogpriority", which is a
+ misleading property name that needs to stay for historical
+ reasons (and backward-compatility)
+- added doc on how to record PRI value in log file
+- enhanced signal handling in klogd, including removal of an unsafe
+ call to the logging system during signal handling
+---------------------------------------------------------------------------
+Version 1.13.3 (RGer), 2007-06-15
+- create a version of syslog.c from scratch. This is now
+ - highly optimized for rsyslog
+ - removes an incompatible license problem as the original
+ version had a BSD license with advertising clause
+ - fixed in the regard that rklogd will continue to work when
+ rsysogd has been restarted (the original version, as well
+ as sysklogd, will remain silent then)
+ - solved an issue with an extra NUL char at message end that the
+ original version had
+- applied some changes to klogd to care for the new interface
+- fixed a bug in syslogd.c which prevented compiling under debian
+---------------------------------------------------------------------------
+Version 1.13.2 (RGer), 2007-06-13
+- lib order in makefile patched to facilitate static linking - thanks
+ to Bennett Todd for providing the patch
+- Integrated a patch from Peter Vrabec (pvrabec@redheat.com):
+ - added klogd under the name of rklogd (remove dependency on
+ original sysklogd package
+ - createDB.sql now in UTF
+ - added additional config files for use on Red Hat
+---------------------------------------------------------------------------
+Version 1.13.1 (RGer), 2007-02-05
+- changed the listen backlog limit to a more reasonable value based on
+ the maximum number of TCP connections configurd (10% + 5) - thanks to Guy
+ Standen for the hint (actually, the limit was 5 and that was a
+ left-over from early testing).
+- fixed a bug in makefile which caused DB-support to be disabled when
+ NETZIP support was enabled
+- added the -e option to allow transmission of every message to remote
+ hosts (effectively turns off duplicate message suppression)
+- (somewhat) improved memory consumption when compiled with MySQL support
+- looks like we fixed an incompatibility with MySQL 5.x and above software
+ At least in one case, the remote server name was destroyed, leading to
+ a connection failure. The new, improved code does not have this issue and
+ so we see this as solved (the new code is generally somewhat better, so
+ there is a good chance we fixed this incompatibility).
+---------------------------------------------------------------------------
+Version 1.13.0 (RGer), 2006-12-19
+- added '$' as ToPos proptery replacer specifier - means "up to the
+ end of the string"
+- property replacer option "escape-cc", "drop-cc" and "space-cc" added
+- changed the handling of \0 characters inside syslog messages. We now
+ consistently escape them to "#000". This is somewhat recommended in
+ the draft-ietf-syslog-protocol-19 draft. While the real recomendation
+ is to not escape any characters at all, we can not do this without
+ considerable modification of the code. So we escape it to "#000", which
+ is consistent with a sample found in the Internet-draft.
+- removed message glue logic (see printchopped() comment for details)
+ Also caused removal of parts table and thus some improvements in
+ memory usage.
+- changed the default MAXLINE to 2048 to take care of recent syslog
+ standardization efforts (can easily be changed in syslogd.c)
+- added support for byte-counted TCP syslog messages (much like
+ syslog-transport-tls-05 Internet Draft). This was necessary to
+ support compression over TCP.
+- added support for receiving compressed syslog messages
+- added support for sending compressed syslog messages
+- fixed a bug where the last message in a syslog/tcp stream was
+ lost if it was not properly terminated by a LF character
+---------------------------------------------------------------------------
+Version 1.12.3 (RGer), 2006-10-04
+- implemented some changes to support Solaris (but support is not
+ yet complete)
+- commented out (via #if 0) some methods that are currently not being use
+ but should be kept for further us
+- added (interim) -u 1 option to turn off hostname and tag parsing
+- done some modifications to better support Fedora
+- made the field delimiter inside property replace configurable via
+ template
+- fixed a bug in property replacer: if fields were used, the delimitor
+ became part of the field. Up until now, this was barely noticable as
+ the delimiter as TAB only and thus invisible to a human. With other
+ delimiters available now, it quickly showed up. This bug fix might cause
+ some grief to existing installations if they used the extra TAB for
+ whatever reasons - sorry folks... Anyhow, a solution is easy: just add
+ a TAB character contstant into your template. Thus, there has no attempt
+ been made to do this in a backwards-compatible way.
+---------------------------------------------------------------------------
+Version 1.12.2 (RGer), 2006-02-15
+- fixed a bug in the RFC 3339 date formatter. An extra space was added
+ after the actual timestamp
+- added support for providing high-precision RFC3339 timestamps for
+ (rsyslogd-)internally-generated messages
+- very (!) experimental support for syslog-protocol internet draft
+ added (the draft is experimental, the code is solid ;))
+- added support for field-extracting in the property replacer
+- enhanced the legacy-syslog parser so that it can interpret messages
+ that do not contain a TIMESTAMP
+- fixed a bug that caused the default socket (usually /dev/log) to be
+ opened even when -o command line option was given
+- fixed a bug in the Debian sample startup script - it caused rsyslogd
+ to listen to remote requests, which it shouldn't by default
+---------------------------------------------------------------------------
+Version 1.12.1 (RGer), 2005-11-23
+- made multithreading work with BSD. Some signal-handling needed to be
+ restructured. Also, there might be a slight delay of up to 10 seconds
+ when huping and terminating rsyslogd under BSD
+- fixed a bug where a NULL-pointer was passed to printf() in logmsg().
+- fixed a bug during "make install" where rc3195d was not installed
+ Thanks to Bennett Todd for spotting this.
+- fixed a bug where rsyslogd dumped core when no TAG was found in the
+ received message
+- enhanced message parser so that it can deal with missing hostnames
+ in many cases (may not be totally fail-safe)
+- fixed a bug where internally-generated messages did not have the correct
+ TAG
+---------------------------------------------------------------------------
+Version 1.12.0 (RGer), 2005-10-26
+- moved to a multi-threaded design. single-threading is still optionally
+ available. Multi-threading is experimental!
+- fixed a potential race condition. In the original code, marking was done
+ by an alarm handler, which could lead to all sorts of bad things. This
+ has been changed now. See comments in syslogd.c/domark() for details.
+- improved debug output for property-based filters
+- not a code change, but: I have checked all exit()s to make sure that
+ none occurs once rsyslogd has started up. Even in unusual conditions
+ (like low-memory conditions) rsyslogd somehow remains active. Of course,
+ it might loose a message or two, but at least it does not abort and it
+ can also recover when the condition no longer persists.
+- fixed a bug that could cause loss of the last message received
+ immediately before rsyslogd was terminated.
+- added comments on thread-safety of global variables in syslogd.c
+- fixed a small bug: spurios printf() when TCP syslog was used
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug with regular expression support (thanks to Andres Riancho)
+- a little bit of code restructuring (especially main(), which was
+ horribly large)
+---------------------------------------------------------------------------
+Version 1.11.1 (RGer), 2005-10-19
+- support for BSD-style program name and host blocks
+- added a new property "programname" that can be used in templates
+- added ability to specify listen port for rfc3195d
+- fixed a bug that rendered the "startswith" comparison operation
+ unusable.
+- changed more functions to "static" storage class to help compiler
+ optimize (should have been static in the first place...)
+- fixed a potential memory leak in the string buffer class destructor.
+ As the destructur was previously never called, the leak did not actually
+ appear.
+- some internal restructuring in anticipation/preparation of minimal
+ multi-threading support
+- rsyslogd still shares some code with the sysklogd project. Some patches
+ for this shared code have been brought over from the sysklogd CVS.
+---------------------------------------------------------------------------
+Version 1.11.0 (RGer), 2005-10-12
+- support for receiving messages via RFC 3195; added rfc3195d for that
+ purpose
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+---------------------------------------------------------------------------
+Version 1.10.2 (RGer), 2005-09-27
+- added comparison operations in property-based filters:
+ * isequal
+ * startswith
+- added ability to negate all property-based filter comparison operations
+ by adding a !-sign right in front of the operation name
+- added the ability to specify remote senders for UDP and TCP
+ received messages. Allows to block all but well-known hosts
+- changed the $-config line directives to be case-INsensitive
+- new command line option -w added: "do not display warnings if messages
+ from disallowed senders are received"
+- fixed a bug that caused rsyslogd to dump core when the compare value
+ was not quoted in property-based filters
+- fixed a bug in the new CStr compare function which lead to invalid
+ results (fortunately, this function was not yet used widely)
+- added better support for "debugging" rsyslog.conf property filters
+ (only if -d switch is given)
+- changed some function definitions to static, which eventually enables
+ some compiler optimizations
+- fixed a bug in MySQL code; when a SQL error occured, rsyslogd could
+ run in a tight loop. This was due to invalid sequence of error reporting
+ and is now fixed.
+---------------------------------------------------------------------------
+Version 1.10.1 (RGer), 2005-09-23
+- added the ability to execute a shell script as an action.
+ Thanks to Bjoern Kalkbrenner for providing the code!
+- fixed a bug in the MySQL code; due to the bug the automatic one-time
+ retry after an error did not happen - this lead to error message in
+ cases where none should be seen (e.g. after a MySQL restart)
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.10.0 (RGer), 2005-09-20
+ REMINDER: 1.10 is the first unstable version if the 1.x series!
+- added the capability to filter on any property in selector lines
+ (not just facility and priority)
+- changed stringbuf into a new counted string class
+- added support for a "discard" action. If a selector line with
+ discard (~ character) is found, no selector lines *after* that
+ line will be processed.
+- thanks to Andres Riancho, regular expression support has been
+ added to the template engine
+- added the FROMHOST property in the template processor, which could
+ previously not be obtained. Thanks to Cristian Testa for pointing
+ this out and even providing a fix.
+- added display of compile-time options to -v output
+- performance improvement for production build - made some checks
+ to happen only during debug mode
+- fixed a problem with compiling on SUSE and - while doing so - removed
+ the socket call to set SO_BSDCOMPAT in cases where it is obsolete.
+---------------------------------------------------------------------------
+Version 1.0.4 (RGer), 2006-02-01
+- a small but important fix: the tcp receiver had two forgotten printf's
+ in it that caused a lot of unnecessary output to stdout. This was
+ important enough to justify a new release
+---------------------------------------------------------------------------
+Version 1.0.3 (RGer), 2005-11-14
+- added an additional guard to prevent rsyslogd from aborting when the
+ 2gb file size limit is hit. While a user can configure rsyslogd to
+ handle such situations, it would abort if that was not done AND large
+ file support was not enabled (ok, this is hopefully an unlikely scenario)
+- fixed a bug that caused additional Unix domain sockets to be incorrectly
+ processed - could lead to message loss in extreme cases
+- applied some patches available from the sysklogd project to code
+ shared from there
+- fixed a bug that causes rsyslogd to dump core on termination when one
+ of the selector lines did not receive a message during the run (very
+ unlikely)
+- fixed an one-too-low memory allocation in the TCP sender. Could result
+ in rsyslogd dumping core.
+- fixed a bug in the TCP sender that caused the retry logic to fail
+ after an error or receiver overrun
+- fixed a bug in init() that could lead to dumping core
+- fixed a bug that could lead to dumping core when no HOSTNAME or no TAG
+ was present in the syslog message
+---------------------------------------------------------------------------
+Version 1.0.2 (RGer), 2005-10-05
+- fixed an issue with MySQL error reporting. When an error occured,
+ the MySQL driver went into an endless loop (at least in most cases).
+---------------------------------------------------------------------------
+Version 1.0.1 (RGer), 2005-09-23
+- fixed a security issue with SQL-escaping in conjunction with
+ non-(SQL-)standard MySQL features.
+---------------------------------------------------------------------------
+Version 1.0.0 (RGer), 2005-09-12
+- changed install doc to cover daily cron scripts - a trouble source
+- added rc script for slackware (provided by Chris Elvidge - thanks!)
+- fixed a really minor bug in usage() - the -r option was still
+ reported as without the port parameter
+---------------------------------------------------------------------------
+Version 0.9.8 (RGer), 2005-09-05
+- made startup and shutdown message more consistent and included the
+ pid, so that they can be easier correlated. Used syslog-protocol
+ structured data format for this purpose.
+- improved config info in startup message, now tells not only
+ if it is listening remote on udp, but also for tcp. Also includes
+ the port numbers. The previous startup message was misleading, because
+ it did not say "remote reception" if rsyslogd was only listening via
+ tcp (but not via udp).
+- added a "how can you help" document to the doc set
+---------------------------------------------------------------------------
+Version 0.9.7 (RGer), 2005-08-15
+- some of the previous doc files (like INSTALL) did not properly
+ reflect the changes to the build process and the new doc. Fixed
+ that.
+- changed syslogd.c so that when compiled without database support,
+ an error message is displayed when a database action is detected
+ in the config file (previously this was used as an user rule ;))
+- fixed a bug in the os-specific Makefiles which caused MySQL
+ support to not be compiled, even if selected
+---------------------------------------------------------------------------
+Version 0.9.6 (RGer), 2005-08-09
+- greatly enhanced documentation. Now available in html format in
+ the "doc" folder and FreeBSD. Finally includes an install howto.
+- improved MySQL error messages a little - they now show up as log
+ messages, too (formerly only in debug mode)
+- added the ability to specify the listen port for udp syslog.
+ WARNING: This introduces an incompatibility. Formerly, udp
+ syslog was enabled by the -r command line option. Now, it is
+ "-r [port]", which is consistent with the tcp listener. However,
+ just -r will now return an error message.
+- added sample startup scripts for Debian and FreeBSD
+- added support for easy feature selection in the makefile. Un-
+ fortunately, this also means I needed to spilt the make file
+ for different OS and distros. There are some really bad syntax
+ differences between FreeBSD and Linux make.
+---------------------------------------------------------------------------
+Version 0.9.5 (RGer), 2005-08-01
+- the "semicolon bug" was actually not (fully) solved in 0.9.4. One
+ part of the bug was solved, but another still existed. This one
+ is fixed now, too.
+- the "semicolon bug" actually turned out to be a more generic bug.
+ It appeared whenever an invalid template name was given. With some
+ selector actions, rsyslogd dumped core, with other it "just" had
+ a small ressource leak with others all worked well. These anomalies
+ are now fixed. Note that they only appeared during system initaliziation
+ once the system was running, nothing bad happened.
+- improved error reporting for template errors on startup. They are now
+ shown on the console and the start-up tty. Formerly, they were only
+ visible in debug mode.
+- support for multiple instances of rsyslogd on a single machine added
+- added new option "-o" --> omit local unix domain socket. This option
+ enables rsyslogd NOT to listen to the local socket. This is most
+ helpful when multiple instances of rsyslogd (or rsyslogd and another
+ syslogd) shall run on a single system.
+- added new option "-i <pidfile>" which allows to specify the pidfile.
+ This is needed when multiple instances of rsyslogd are to be run.
+- the new project home page is now online at www.rsyslog.com
+---------------------------------------------------------------------------
+Version 0.9.4 (RGer), 2005-07-25
+- finally added the TCP sender. It now supports non-blocking mode, no
+ longer disabling message reception during connect. As it is now, it
+ is usable in production. The code could be more sophisticated, but
+ I've kept it short in anticipation of the move to liblogging, which
+ will lead to the removal of the code just written ;)
+- the "exiting on signal..." message still had the "syslogd" name in
+ it. Changed this to "rsyslogd", as we do not have a large user base
+ yet, this should pose no problem.
+- fixed "the semiconlon" bug. rsyslogd dumped core if a write-db action
+ was specified but no semicolon was given after the password (an empty
+ template was ok, but the semicolon needed to be present).
+- changed a default for traditional output format. During testing, it
+ was seen that the timestamp written to file in default format was
+ the time of message reception, not the time specified in the TIMESTAMP
+ field of the message itself. Traditionally, the message TIMESTAMP is
+ used and this has been changed now.
+---------------------------------------------------------------------------
+Version 0.9.3 (RGer), 2005-07-19
+- fixed a bug in the message parser. In June, the RFC 3164 timestamp
+ was not correctly parsed (yes, only in June and some other months,
+ see the code comment to learn why...)
+- added the ability to specify the destination port when forwarding
+ syslog messages (both for TCP and UDP)
+- added an very experimental TCP sender (activated by
+ @@machine:port in config). This is not yet for production use. If
+ the receiver is not alive, rsyslogd will wait quite some time until
+ the connection request times out, which most probably leads to
+ loss of incoming messages.
+
+---------------------------------------------------------------------------
+Version 0.9.2 (RGer), around 2005-07-06
+- I intended to change the maxsupported message size to 32k to
+ support IHE - but given the memory inefficiency in the usual use
+ cases, I have not done this. I have, however, included very
+ specific instructions on how to do this in the source code. I have
+ also done some testing with 32k messages, so you can change the
+ max size without taking too much risk.
+- added a syslog/tcp receiver; we now can receive messages via
+ plain tcp, but we can still send only via UDP. The syslog/tcp
+ receiver is the primary enhancement of this release.
+- slightly changed some error messages that contained a spurios \n at
+ the end of the line (which gives empty lines in your log...)
+
+---------------------------------------------------------------------------
+Version 0.9.1 (RGer)
+- fixed code so that it compiles without errors under FreeBSD
+- removed now unused function "allocate_log()" from syslogd.c
+- changed the make file so that it contains more defines for
+ different environments (in the long term, we need a better
+ system for disabling/enabling features...)
+- changed some printf's printing off_t types to %lld and
+ explicit (long long) casts. I tried to figure out the exact type,
+ but did not succeed in this. In the worst case, ultra-large peta-
+ byte files will now display funny informational messages on rollover,
+ something I think we can live with for the next 10 years or so...
+
+---------------------------------------------------------------------------
+Version 0.9.0 (RGer)
+- changed the filed structure to be a linked list. Previously, it
+ was a table - well, for non-SYSV it was defined as linked list,
+ but from what I see that code did no longer work after my
+ modifications. I am now using a linked list in general because
+ that is needed for other upcoming modifications.
+- fixed a bug that caused rsyslogd not to listen to anything if
+ the configuration file could not be read
+- pervious versions disabled network logging (send/receive) if
+ syslog/udp port was not in /etc/services. Now defaulting to
+ port 514 in this case.
+- internal error messages are now supported up to 256 bytes
+- error message seen during config file read are now also displayed
+ to the attached tty and not only the console
+- changed some error messages during init to be sent to the console
+ and/or emergency log. Previously, they were only seen if the
+ -d (debug) option was present on the command line.
+- fixed the "2gb file issue on 32bit systems". If a file grew to
+ more than 2gb, the syslogd was aborted with "file size exceeded".
+ Now, defines have been added according to
+ http://www.daimi.au.dk/~kasperd/comp.os.linux.development.faq.html#LARGEFILE
+ Testing revealed that they work ;)
+ HOWEVER, if your file system, glibc, kernel, whatever does not
+ support files larger 2gb, you need to set a file size limit with
+ the new output channel mechanism.
+- updated man pages to reflect the changes
+
+---------------------------------------------------------------------------
+Version 0.8.4
+
+- improved -d debug output (removed developer-only content)
+- now compiles under FreeBSD and NetBSD (only quick testing done on NetBSD)
+---------------------------------------------------------------------------
+Version 0.8.3
+
+- security model in "make install" changed
+- minor doc updates
+---------------------------------------------------------------------------
+Version 0.8.2
+
+- added man page for rsyslog.conf and rsyslogd
+- gave up on the concept of rsyslog being a "drop in" replacement
+ for syslogd. Now, the user installs rsyslogd and also needs to
+ adjust his system settings to this specifically. This also lead
+ to these changes:
+ * changed Makefile so that install now installs rsyslogd instead
+ of dealing with syslogd
+ * changed the default config file name to rsyslog.conf
+---------------------------------------------------------------------------
+Version 0.8.1
+
+- fixed a nasty memory leak (probably not the last one with this release)
+- some enhancements to Makefile as suggested by Bennett Todd
+- syslogd-internal messages (like restart) were missing the hostname
+ this has been corrected
+---------------------------------------------------------------------------
+Version 0.8.0
+
+Initial testing release. Based on the sysklogd package. Thanks to the
+sysklogd maintainers for all their good work!
+---------------------------------------------------------------------------
+
+----------------------------------------------------------------------
+The following comments are from the stock syslogd.c source. They provide
+some insight into what happened to the source before we forked
+rsyslogd. However, much of the code already has been replaced and more
+is to be replaced. So over time, these comments become less valuable.
+I have moved them out of the syslogd.c file to shrink it, especially
+as a lot of them do no longer apply. For historical reasons and
+understanding of how the daemon evolved, they are probably still
+helpful.
+ * Author: Eric Allman
+ * extensive changes by Ralph Campbell
+ * more extensive changes by Eric Allman (again)
+ *
+ * Steve Lord: Fix UNIX domain socket code, added linux kernel logging
+ * change defines to
+ * SYSLOG_INET - listen on a UDP socket
+ * SYSLOG_UNIXAF - listen on unix domain socket
+ * SYSLOG_KERNEL - listen to linux kernel
+ *
+ * Mon Feb 22 09:55:42 CST 1993: Dr. Wettstein
+ * Additional modifications to the source. Changed priority scheme
+ * to increase the level of configurability. In its stock configuration
+ * syslogd no longer logs all messages of a certain priority and above
+ * to a log file. The * wildcard is supported to specify all priorities.
+ * Note that this is a departure from the BSD standard.
+ *
+ * Syslogd will now listen to both the inetd and the unixd socket. The
+ * strategy is to allow all local programs to direct their output to
+ * syslogd through the unixd socket while the program listens to the
+ * inetd socket to get messages forwarded from other hosts.
+ *
+ * Fri Mar 12 16:55:33 CST 1993: Dr. Wettstein
+ * Thanks to Stephen Tweedie (dcs.ed.ac.uk!sct) for helpful bug-fixes
+ * and an enlightened commentary on the prioritization problem.
+ *
+ * Changed the priority scheme so that the default behavior mimics the
+ * standard BSD. In this scenario all messages of a specified priority
+ * and above are logged.
+ *
+ * Add the ability to specify a wildcard (=) as the first character
+ * of the priority name. Doing this specifies that ONLY messages with
+ * this level of priority are to be logged. For example:
+ *
+ * *.=debug /usr/adm/debug
+ *
+ * Would log only messages with a priority of debug to the /usr/adm/debug
+ * file.
+ *
+ * Providing an * as the priority specifies that all messages are to be
+ * logged. Note that this case is degenerate with specifying a priority
+ * level of debug. The wildcard * was retained because I believe that
+ * this is more intuitive.
+ *
+ * Thu Jun 24 11:34:13 CDT 1993: Dr. Wettstein
+ * Modified sources to incorporate changes in libc4.4. Messages from
+ * syslog are now null-terminated, syslogd code now parses messages
+ * based on this termination scheme. Linux as of libc4.4 supports the
+ * fsync system call. Modified code to fsync after all writes to
+ * log files.
+ *
+ * Sat Dec 11 11:59:43 CST 1993: Dr. Wettstein
+ * Extensive changes to the source code to allow compilation with no
+ * complaints with -Wall.
+ *
+ * Reorganized the facility and priority name arrays so that they
+ * compatible with the syslog.h source found in /usr/include/syslog.h.
+ * NOTE that this should really be changed. The reason I do not
+ * allow the use of the values defined in syslog.h is on account of
+ * the extensions made to allow the wildcard character in the
+ * priority field. To fix this properly one should malloc an array,
+ * copy the contents of the array defined by syslog.h and then
+ * make whatever modifications that are desired. Next round.
+ *
+ * Thu Jan 6 12:07:36 CST 1994: Dr. Wettstein
+ * Added support for proper decomposition and re-assembly of
+ * fragment messages on UNIX domain sockets. Lack of this capability
+ * was causing 'partial' messages to be output. Since facility and
+ * priority information is encoded as a leader on the messages this
+ * was causing lines to be placed in erroneous files.
+ *
+ * Also added a patch from Shane Alderton (shane@ion.apana.org.au) to
+ * correct a problem with syslogd dumping core when an attempt was made
+ * to write log messages to a logged-on user. Thank you.
+ *
+ * Many thanks to Juha Virtanen (jiivee@hut.fi) for a series of
+ * interchanges which lead to the fixing of problems with messages set
+ * to priorities of none and emerg. Also thanks to Juha for a patch
+ * to exclude users with a class of LOGIN from receiving messages.
+ *
+ * Shane Alderton provided an additional patch to fix zombies which
+ * were conceived when messages were written to multiple users.
+ *
+ * Mon Feb 6 09:57:10 CST 1995: Dr. Wettstein
+ * Patch to properly reset the single priority message flag. Thanks
+ * to Christopher Gori for spotting this bug and forwarding a patch.
+ *
+ * Wed Feb 22 15:38:31 CST 1995: Dr. Wettstein
+ * Added version information to startup messages.
+ *
+ * Added defines so that paths to important files are taken from
+ * the definitions in paths.h. Hopefully this will insure that
+ * everything follows the FSSTND standards. Thanks to Chris Metcalf
+ * for a set of patches to provide this functionality. Also thanks
+ * Elias Levy for prompting me to get these into the sources.
+ *
+ * Wed Jul 26 18:57:23 MET DST 1995: Martin Schulze
+ * Linux' gethostname only returns the hostname and not the fqdn as
+ * expected in the code. But if you call hostname with an fqdn then
+ * gethostname will return an fqdn, so we have to mention that. This
+ * has been changed.
+ *
+ * The 'LocalDomain' and the hostname of a remote machine is
+ * converted to lower case, because the original caused some
+ * inconsistency, because the (at least my) nameserver did respond an
+ * fqdn containing of upper- _and_ lowercase letters while
+ * 'LocalDomain' consisted only of lowercase letters and that didn't
+ * match.
+ *
+ * Sat Aug 5 18:59:15 MET DST 1995: Martin Schulze
+ * Now no messages that were received from any remote host are sent
+ * out to another. At my domain this missing feature caused ugly
+ * syslog-loops, sometimes.
+ *
+ * Remember that no message is sent out. I can't figure out any
+ * scenario where it might be useful to change this behavior and to
+ * send out messages to other hosts than the one from which we
+ * received the message, but I might be shortsighted. :-/
+ *
+ * Thu Aug 10 19:01:08 MET DST 1995: Martin Schulze
+ * Added my pidfile.[ch] to it to perform a better handling with
+ * pidfiles. Now both, syslogd and klogd, can only be started
+ * once. They check the pidfile.
+ *
+ * Sun Aug 13 19:01:41 MET DST 1995: Martin Schulze
+ * Add an addition to syslog.conf's interpretation. If a priority
+ * begins with an exclamation mark ('!') the normal interpretation
+ * of the priority is inverted: ".!*" is the same as ".none", ".!=info"
+ * don't logs the info priority, ".!crit" won't log any message with
+ * the priority crit or higher. For example:
+ *
+ * mail.*;mail.!=info /usr/adm/mail
+ *
+ * Would log all messages of the facility mail except those with
+ * the priority info to /usr/adm/mail. This makes the syslogd
+ * much more flexible.
+ *
+ * Defined TABLE_ALLPRI=255 and changed some occurrences.
+ *
+ * Sat Aug 19 21:40:13 MET DST 1995: Martin Schulze
+ * Making the table of facilities and priorities while in debug
+ * mode more readable.
+ *
+ * If debugging is turned on, printing the whole table of
+ * facilities and priorities every hexadecimal or 'X' entry is
+ * now 2 characters wide.
+ *
+ * The number of the entry is prepended to each line of
+ * facilities and priorities, and F_UNUSED lines are not shown
+ * anymore.
+ *
+ * Corrected some #ifdef SYSV's.
+ *
+ * Mon Aug 21 22:10:35 MET DST 1995: Martin Schulze
+ * Corrected a strange behavior during parsing of configuration
+ * file. The original BSD syslogd doesn't understand spaces as
+ * separators between specifier and action. This syslogd now
+ * understands them. The old behavior caused some confusion over
+ * the Linux community.
+ *
+ * Thu Oct 19 00:02:07 MET 1995: Martin Schulze
+ * The default behavior has changed for security reasons. The
+ * syslogd will not receive any remote message unless you turn
+ * reception on with the "-r" option.
+ *
+ * Not defining SYSLOG_INET will result in not doing any network
+ * activity, i.e. not sending or receiving messages. I changed
+ * this because the old idea is implemented with the "-r" option
+ * and the old thing didn't work anyway.
+ *
+ * Thu Oct 26 13:14:06 MET 1995: Martin Schulze
+ * Added another logfile type F_FORW_UNKN. The problem I ran into
+ * was a name server that runs on my machine and a forwarder of
+ * kern.crit to another host. The hosts address can only be
+ * fetched using the nameserver. But named is started after
+ * syslogd, so syslogd complained.
+ *
+ * This logfile type will retry to get the address of the
+ * hostname ten times and then complain. This should be enough to
+ * get the named up and running during boot sequence.
+ *
+ * Fri Oct 27 14:08:15 1995: Dr. Wettstein
+ * Changed static array of logfiles to a dynamic array. This
+ * can grow during process.
+ *
+ * Fri Nov 10 23:08:18 1995: Martin Schulze
+ * Inserted a new tabular sys_h_errlist that contains plain text
+ * for error codes that are returned from the net subsystem and
+ * stored in h_errno. I have also changed some wrong lookups to
+ * sys_errlist.
+ *
+ * Wed Nov 22 22:32:55 1995: Martin Schulze
+ * Added the fabulous strip-domain feature that allows us to
+ * strip off (several) domain names from the fqdn and only log
+ * the simple hostname. This is useful if you're in a LAN that
+ * has a central log server and also different domains.
+ *
+ * I have also also added the -l switch do define hosts as
+ * local. These will get logged with their simple hostname, too.
+ *
+ * Thu Nov 23 19:02:56 MET DST 1995: Martin Schulze
+ * Added the possibility to omit fsyncing of logfiles after every
+ * write. This will give some performance back if you have
+ * programs that log in a very verbose manner (like innd or
+ * smartlist). Thanks to Stephen R. van den Berg <srb@cuci.nl>
+ * for the idea.
+ *
+ * Thu Jan 18 11:14:36 CST 1996: Dr. Wettstein
+ * Added patche from beta-testers to stop compile error. Also
+ * added removal of pid file as part of termination cleanup.
+ *
+ * Wed Feb 14 12:42:09 CST 1996: Dr. Wettstein
+ * Allowed forwarding of messages received from remote hosts to
+ * be controlled by a command-line switch. Specifying -h allows
+ * forwarding. The default behavior is to disable forwarding of
+ * messages which were received from a remote host.
+ *
+ * Parent process of syslogd does not exit until child process has
+ * finished initialization process. This allows rc.* startup to
+ * pause until syslogd facility is up and operating.
+ *
+ * Re-arranged the select code to move UNIX domain socket accepts
+ * to be processed later. This was a contributed change which
+ * has been proposed to correct the delays sometimes encountered
+ * when syslogd starts up.
+ *
+ * Minor code cleanups.
+ *
+ * Thu May 2 15:15:33 CDT 1996: Dr. Wettstein
+ * Fixed bug in init function which resulted in file descripters
+ * being orphaned when syslogd process was re-initialized with SIGHUP
+ * signal. Thanks to Edvard Tuinder
+ * (Edvard.Tuinder@praseodymium.cistron.nl) for putting me on the
+ * trail of this bug. I am amazed that we didn't catch this one
+ * before now.
+ *
+ * Tue May 14 00:03:35 MET DST 1996: Martin Schulze
+ * Corrected a mistake that causes the syslogd to stop logging at
+ * some virtual consoles under Linux. This was caused by checking
+ * the wrong error code. Thanks to Michael Nonweiler
+ * <mrn20@hermes.cam.ac.uk> for sending me a patch.
+ *
+ * Mon May 20 13:29:32 MET DST 1996: Miquel van Smoorenburg <miquels@cistron.nl>
+ * Added continuation line supported and fixed a bug in
+ * the init() code.
+ *
+ * Tue May 28 00:58:45 MET DST 1996: Martin Schulze
+ * Corrected behaviour of blocking pipes - i.e. the whole system
+ * hung. Michael Nonweiler <mrn20@hermes.cam.ac.uk> has sent us
+ * a patch to correct this. A new logfile type F_PIPE has been
+ * introduced.
+ *
+ * Mon Feb 3 10:12:15 MET DST 1997: Martin Schulze
+ * Corrected behaviour of logfiles if the file can't be opened.
+ * There was a bug that causes syslogd to try to log into non
+ * existing files which ate cpu power.
+ *
+ * Sun Feb 9 03:22:12 MET DST 1997: Martin Schulze
+ * Modified syslogd.c to not kill itself which confuses bash 2.0.
+ *
+ * Mon Feb 10 00:09:11 MET DST 1997: Martin Schulze
+ * Improved debug code to decode the numeric facility/priority
+ * pair into textual information.
+ *
+ * Tue Jun 10 12:35:10 MET DST 1997: Martin Schulze
+ * Corrected freeing of logfiles. Thanks to Jos Vos <jos@xos.nl>
+ * for reporting the bug and sending an idea to fix the problem.
+ *
+ * Tue Jun 10 12:51:41 MET DST 1997: Martin Schulze
+ * Removed sleep(10) from parent process. This has caused a slow
+ * startup in former times - and I don't see any reason for this.
+ *
+ * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
+ * Some more glibc patches made by <mdorman@debian.org>.
+ *
+ * Thu Jan 1 16:04:52 CET 1998: Martin Schulze <joey@infodrom.north.de
+ * Applied patch from Herbert Thielen <Herbert.Thielen@lpr.e-technik.tu-muenchen.de>.
+ * This included some balance parentheses for emacs and a bug in
+ * the exclamation mark handling.
+ *
+ * Fixed small bug which caused syslogd to write messages to the
+ * wrong logfile under some very rare conditions. Thanks to
+ * Herbert Xu <herbert@gondor.apana.org.au> for fiddling this out.
+ *
+ * Thu Jan 8 22:46:35 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Reworked one line of the above patch as it prevented syslogd
+ * from binding the socket with the result that no messages were
+ * forwarded to other hosts.
+ *
+ * Sat Jan 10 01:33:06 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed small bugs in F_FORW_UNKN meachanism. Thanks to Torsten
+ * Neumann <torsten@londo.rhein-main.de> for pointing me to it.
+ *
+ * Mon Jan 12 19:50:58 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified debug output concerning remote receiption.
+ *
+ * Mon Feb 23 23:32:35 CET 1998: Topi Miettinen <Topi.Miettinen@ml.tele.fi>
+ * Re-worked handling of Unix and UDP sockets to support closing /
+ * opening of them in order to have it open only if it is needed
+ * either for forwarding to a remote host or by receiption from
+ * the network.
+ *
+ * Wed Feb 25 10:54:09 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed little comparison mistake that prevented the MARK
+ * feature to work properly.
+ *
+ * Wed Feb 25 13:21:44 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Corrected Topi's patch as it prevented forwarding during
+ * startup due to an unknown LogPort.
+ *
+ * Sat Oct 10 20:01:48 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added support for TESTING define which will turn syslogd into
+ * stdio-mode used for debugging.
+ *
+ * Sun Oct 11 20:16:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Reworked the initialization/fork code. Now the parent
+ * process activates a signal handler which the daughter process
+ * will raise if it is initialized. Only after that one the
+ * parent process may exit. Otherwise klogd might try to flush
+ * its log cache while syslogd can't receive the messages yet.
+ *
+ * Mon Oct 12 13:30:35 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Redirected some error output with regard to argument parsing to
+ * stderr.
+ *
+ * Mon Oct 12 14:02:51 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Applied patch provided vom Topi Miettinen with regard to the
+ * people from OpenBSD. This provides the additional '-a'
+ * argument used for specifying additional UNIX domain sockets to
+ * listen to. This is been used with chroot()'ed named's for
+ * example. See for http://www.psionic.com/papers/dns.html
+ *
+ * Mon Oct 12 18:29:44 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added `ftp' facility which was introduced in glibc version 2.
+ * It's #ifdef'ed so won't harm with older libraries.
+ *
+ * Mon Oct 12 19:59:21 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Code cleanups with regard to bsd -> posix transition and
+ * stronger security (buffer length checking). Thanks to Topi
+ * Miettinen <tom@medialab.sonera.net>
+ * . index() --> strchr()
+ * . sprintf() --> snprintf()
+ * . bcopy() --> memcpy()
+ * . bzero() --> memset()
+ * . UNAMESZ --> UT_NAMESIZE
+ * . sys_errlist --> strerror()
+ *
+ * Mon Oct 12 20:22:59 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added support for setutent()/getutent()/endutend() instead of
+ * binary reading the UTMP file. This is the the most portable
+ * way. This allows /var/run/utmp format to change, even to a
+ * real database or utmp daemon. Also if utmp file locking is
+ * implemented in libc, syslog will use it immediately. Thanks
+ * to Topi Miettinen <tom@medialab.sonera.net>.
+ *
+ * Mon Oct 12 20:49:18 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Avoid logging of SIGCHLD when syslogd is in the process of
+ * exiting and closing its files. Again thanks to Topi.
+ *
+ * Mon Oct 12 22:18:34 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified printline() to support 8bit characters - such as
+ * russion letters. Thanks to Vladas Lapinskas <lapinskas@mail.iae.lt>.
+ *
+ * Sat Nov 14 02:29:37 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * ``-m 0'' now turns of MARK logging entirely.
+ *
+ * Tue Jan 19 01:04:18 MET 1999: Martin Schulze <joey@infodrom.north.de>
+ * Finally fixed an error with `-a' processing, thanks to Topi
+ * Miettinen <tom@medialab.sonera.net>.
+ *
+ * Sun May 23 10:08:53 CEST 1999: Martin Schulze <joey@infodrom.north.de>
+ * Removed superflous call to utmpname(). The path to the utmp
+ * file is defined in the used libc and should not be hardcoded
+ * into the syslogd binary referring the system it was compiled on.
+ *
+ * Sun Sep 17 20:45:33 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Fixed some bugs in printline() code that did not escape
+ * control characters '\177' through '\237' and contained a
+ * single-byte buffer overflow. Thanks to Solar Designer
+ * <solar@false.com>.
+ *
+ * Sun Sep 17 21:26:16 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Don't close open sockets upon reload. Thanks to Bill
+ * Nottingham.
+ *
+ * Mon Sep 18 09:10:47 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Fixed bug in printchopped() that caused syslogd to emit
+ * kern.emerg messages when splitting long lines. Thanks to
+ * Daniel Jacobowitz <dan@debian.org> for the fix.
+ *
+ * Mon Sep 18 15:33:26 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Removed unixm/unix domain sockets and switch to Datagram Unix
+ * Sockets. This should remove one possibility to play DoS with
+ * syslogd. Thanks to Olaf Kirch <okir@caldera.de> for the patch.
+ *
+ * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de>
+ * Don't return a closed fd if `-a' is called with a wrong path.
+ * Thanks to Bill Nottingham <notting@redhat.com> for providing
+ * a patch.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..494eb74
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,58 @@
+There is an additional install HOWTO available under
+
+ doc/install.html
+
+Probably this HOWTO is easier to follow then the steps here
+below.
+
+
+1.) READ the README.linux file and the accompanying man pages.
+ It will save you some frustration. Be sure to review sample.conf
+ it has a lot of information and samples on templates. If you
+ want to do all the cool things, this is what you need to know.
+
+2.) The actual build process is done from a distro-specific
+ subdirectory. If in doubt, use the "linux" directory. CD
+ into it. We assume you stay in it for the rest of the process.
+
+3.) Edit the Makefile for your installation. NOTE that if you have not
+ carried out step 1 you may make choices which could render your
+ system and/or these utilities unusable. Compile the utilities.
+
+4.) The FSSTND makes suggestions as to appropriate locations for
+ system binaries. Since not everyone agrees with standards it is
+ up to the system administrator installing the utilities to choose
+ the most appropriate locations for the binaries and their
+ configuration files. By default the package will compile and
+ install following the FSSTND recommendations. If a decision is
+ made to change this behavior consult the makefile and the sources.
+ The FSSTND define controls selection of values which may be
+ influenced by the choice of conformance with the FSSTND or site
+ preferences.
+
+5.) For proper functioning the daemon is best run as root.
+ This is probably not much of a problem since it will probably be
+ started either by init or as part of the rc.* startup process. There
+ may be security concerns with running it as root. Please repeat
+ step 1 if you are unsure of why this may be the case.
+
+6.) Contrary to previous releases, this release does NOT replace the
+ standard syslogd in your system. Instead, the tool is installed
+ under the name rsyslogd. Similarily, it does NOT automatically read
+ syslog.conf, but rsyslog.conf instead. This was done based on user
+ feedback (which re-activated the author's common sense ;)) and will
+ probably save you a lot of hassle. On the other hand, if you used
+ previous versions of rsyslog, you need to change some things now!
+
+7.) If you would like to use database logging, you need a database ;)
+ The default configuration requires a MonitorWare schema. To do this, you
+ can follow this advise:
+ How to create the database for rsyslog?
+ It is really easy. Simply run the following command in your shell. Be sure
+ that the mysql user you are using have permission to create a database.
+ mysql -u username -p < /path/to/createDB.sql
+ Enter the password if requested. The database "Syslog" with the necessary
+ tables is created.
+ If you would like to use a different schema, you can do so ;) Just create
+ your schema and database and then create a matching template in rsyslog.conf.
+ See sample.conf for a description on how templates work.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..5b48728
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,14 @@
+
+sbin_PROGRAMS=rklogd rfc3195d rsyslogd
+
+rklogd_SOURCES=klogd.c syslog.c pidfile.c ksym.c ksym_mod.c klogd.h ksyms.h pidfile.h module.h
+
+rfc3195d_SOURCES=rfc3195d.c rsyslog.h
+
+man_MANS = rfc3195d.8 rklogd.8 rsyslogd.8 rsyslog.conf.5
+
+rsyslogd_SOURCES=syslogd.c pidfile.c template.c outchannel.c stringbuf.c srUtils.c parse.c syslogd-types.h template.h outchannel.h syslogd.h stringbuf.h parse.h srUtils.h liblogging-stub.h net.c net.h msg.c msg.h omshell.c omshell.h omusrmsg.c omusrmsg.h ommysql.c ommysql.h omfwd.c omfwd.h tcpsyslog.c tcpsyslog.h omfile.h omfile.c omdiscard.c omdiscard.h modules.c modules.h module-template.h objomsr.c objomsr.h cfsysline.c cfsysline.h linkedlist.c linkedlist.h iminternal.c iminternal.h action.c action.h
+rsyslogd_CPPFLAGS=$(mysql_includes)
+rsyslogd_LDADD=$(mysql_libs) $(zlib_libs) $(pthreads_libs)
+
+EXTRA_DIST = doc/bugs.html doc/features.html doc/generic_design.html doc/history.html doc/how2help.html doc/install.html doc/ipv6.html doc/manual.html doc/property_replacer.html doc/rsyslog_conf.html doc/rsyslog_mysql.html doc/rsyslog_packages.html doc/rsyslog_php_syslog_ng.html doc/rsyslog_recording_pri.html doc/rsyslog_stunnel.html doc/status.html doc/syslog-protocol.html doc/version_naming.html doc/contributors.html redhat/rsyslog.conf redhat/rsyslog.init redhat/rsyslog.log redhat/rsyslog.sysconfig freebsd/rsyslogd slackware/rc.rsyslogd rfc3195d.8 rklogd.8 rsyslogd.8 rsyslog.conf.5 createDB.sql contrib/README contrib/delete_mysql doc/rsconf1_actionexeconlyifpreviousissuspended.html doc/rsconf1_actionresumeinterval.html doc/rsconf1_allowedsender.html doc/rsconf1_controlcharacterescapeprefix.html doc/rsconf1_debugprintcfsyslinehandlerlist.html doc/rsconf1_debugprintmodulelist.html doc/rsconf1_debugprinttemplatelist.html doc/rsconf1_dircreatemode.html doc/rsconf1_dirgroup.html doc/rsconf1_dirowner.html doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html doc/rsconf1_droptrailinglfonreception.html doc/rsconf1_dynafilecachesize.html doc/rsconf1_escapecontrolcharactersonreceive.html doc/rsconf1_failonchownfailure.html doc/rsconf1_filecreatemode.html doc/rsconf1_filegroup.html doc/rsconf1_fileowner.html doc/rsconf1_includeconfig.html doc/rsconf1_mainmsgqueuesize.html doc/rsconf1_modload.html doc/rsconf1_repeatedmsgreduction.html doc/rsconf1_resetconfigvariables.html doc/rsconf1_umask.html
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..cfaa967
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,1060 @@
+# Makefile.in generated by automake 1.10 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = rklogd$(EXEEXT) rfc3195d$(EXEEXT) rsyslogd$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+ compile config.guess config.sub depcomp install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)"
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(sbin_PROGRAMS)
+am_rfc3195d_OBJECTS = rfc3195d.$(OBJEXT)
+rfc3195d_OBJECTS = $(am_rfc3195d_OBJECTS)
+rfc3195d_LDADD = $(LDADD)
+am_rklogd_OBJECTS = klogd.$(OBJEXT) syslog.$(OBJEXT) pidfile.$(OBJEXT) \
+ ksym.$(OBJEXT) ksym_mod.$(OBJEXT)
+rklogd_OBJECTS = $(am_rklogd_OBJECTS)
+rklogd_LDADD = $(LDADD)
+am_rsyslogd_OBJECTS = rsyslogd-syslogd.$(OBJEXT) \
+ rsyslogd-pidfile.$(OBJEXT) rsyslogd-template.$(OBJEXT) \
+ rsyslogd-outchannel.$(OBJEXT) rsyslogd-stringbuf.$(OBJEXT) \
+ rsyslogd-srUtils.$(OBJEXT) rsyslogd-parse.$(OBJEXT) \
+ rsyslogd-net.$(OBJEXT) rsyslogd-msg.$(OBJEXT) \
+ rsyslogd-omshell.$(OBJEXT) rsyslogd-omusrmsg.$(OBJEXT) \
+ rsyslogd-ommysql.$(OBJEXT) rsyslogd-omfwd.$(OBJEXT) \
+ rsyslogd-tcpsyslog.$(OBJEXT) rsyslogd-omfile.$(OBJEXT) \
+ rsyslogd-omdiscard.$(OBJEXT) rsyslogd-modules.$(OBJEXT) \
+ rsyslogd-objomsr.$(OBJEXT) rsyslogd-cfsysline.$(OBJEXT) \
+ rsyslogd-linkedlist.$(OBJEXT) rsyslogd-iminternal.$(OBJEXT) \
+ rsyslogd-action.$(OBJEXT)
+rsyslogd_OBJECTS = $(am_rsyslogd_OBJECTS)
+am__DEPENDENCIES_1 =
+rsyslogd_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(rfc3195d_SOURCES) $(rklogd_SOURCES) $(rsyslogd_SOURCES)
+DIST_SOURCES = $(rfc3195d_SOURCES) $(rklogd_SOURCES) \
+ $(rsyslogd_SOURCES)
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(man_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+mysql_includes = @mysql_includes@
+mysql_libs = @mysql_libs@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pthreads_libs = @pthreads_libs@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+zlib_libs = @zlib_libs@
+rklogd_SOURCES = klogd.c syslog.c pidfile.c ksym.c ksym_mod.c klogd.h ksyms.h pidfile.h module.h
+rfc3195d_SOURCES = rfc3195d.c rsyslog.h
+man_MANS = rfc3195d.8 rklogd.8 rsyslogd.8 rsyslog.conf.5
+rsyslogd_SOURCES = syslogd.c pidfile.c template.c outchannel.c stringbuf.c srUtils.c parse.c syslogd-types.h template.h outchannel.h syslogd.h stringbuf.h parse.h srUtils.h liblogging-stub.h net.c net.h msg.c msg.h omshell.c omshell.h omusrmsg.c omusrmsg.h ommysql.c ommysql.h omfwd.c omfwd.h tcpsyslog.c tcpsyslog.h omfile.h omfile.c omdiscard.c omdiscard.h modules.c modules.h module-template.h objomsr.c objomsr.h cfsysline.c cfsysline.h linkedlist.c linkedlist.h iminternal.c iminternal.h action.c action.h
+rsyslogd_CPPFLAGS = $(mysql_includes)
+rsyslogd_LDADD = $(mysql_libs) $(zlib_libs) $(pthreads_libs)
+EXTRA_DIST = doc/bugs.html doc/features.html doc/generic_design.html \
+ doc/history.html doc/how2help.html doc/install.html \
+ doc/ipv6.html doc/manual.html doc/property_replacer.html \
+ doc/rsyslog_conf.html doc/rsyslog_mysql.html \
+ doc/rsyslog_packages.html doc/rsyslog_php_syslog_ng.html \
+ doc/rsyslog_recording_pri.html doc/rsyslog_stunnel.html \
+ doc/status.html doc/syslog-protocol.html \
+ doc/version_naming.html doc/contributors.html \
+ redhat/rsyslog.conf redhat/rsyslog.init redhat/rsyslog.log \
+ redhat/rsyslog.sysconfig freebsd/rsyslogd \
+ slackware/rc.rsyslogd rfc3195d.8 rklogd.8 rsyslogd.8 \
+ rsyslog.conf.5 createDB.sql contrib/README \
+ contrib/delete_mysql \
+ doc/rsconf1_actionexeconlyifpreviousissuspended.html \
+ doc/rsconf1_actionresumeinterval.html \
+ doc/rsconf1_allowedsender.html \
+ doc/rsconf1_controlcharacterescapeprefix.html \
+ doc/rsconf1_debugprintcfsyslinehandlerlist.html \
+ doc/rsconf1_debugprintmodulelist.html \
+ doc/rsconf1_debugprinttemplatelist.html \
+ doc/rsconf1_dircreatemode.html doc/rsconf1_dirgroup.html \
+ doc/rsconf1_dirowner.html \
+ doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html \
+ doc/rsconf1_droptrailinglfonreception.html \
+ doc/rsconf1_dynafilecachesize.html \
+ doc/rsconf1_escapecontrolcharactersonreceive.html \
+ doc/rsconf1_failonchownfailure.html \
+ doc/rsconf1_filecreatemode.html doc/rsconf1_filegroup.html \
+ doc/rsconf1_fileowner.html doc/rsconf1_includeconfig.html \
+ doc/rsconf1_mainmsgqueuesize.html doc/rsconf1_modload.html \
+ doc/rsconf1_repeatedmsgreduction.html \
+ doc/rsconf1_resetconfigvariables.html doc/rsconf1_umask.html
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
+ cd $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+ done
+
+clean-sbinPROGRAMS:
+ -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+rfc3195d$(EXEEXT): $(rfc3195d_OBJECTS) $(rfc3195d_DEPENDENCIES)
+ @rm -f rfc3195d$(EXEEXT)
+ $(LINK) $(rfc3195d_OBJECTS) $(rfc3195d_LDADD) $(LIBS)
+rklogd$(EXEEXT): $(rklogd_OBJECTS) $(rklogd_DEPENDENCIES)
+ @rm -f rklogd$(EXEEXT)
+ $(LINK) $(rklogd_OBJECTS) $(rklogd_LDADD) $(LIBS)
+rsyslogd$(EXEEXT): $(rsyslogd_OBJECTS) $(rsyslogd_DEPENDENCIES)
+ @rm -f rsyslogd$(EXEEXT)
+ $(LINK) $(rsyslogd_OBJECTS) $(rsyslogd_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/klogd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ksym.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ksym_mod.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pidfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc3195d.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-action.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-cfsysline.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-iminternal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-linkedlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-modules.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-msg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-net.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-objomsr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omdiscard.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfwd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-ommysql.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omshell.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omusrmsg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-outchannel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-parse.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-pidfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-srUtils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-stringbuf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-syslogd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-tcpsyslog.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-template.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+rsyslogd-syslogd.o: syslogd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.o -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='syslogd.c' object='rsyslogd-syslogd.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c
+
+rsyslogd-syslogd.obj: syslogd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='syslogd.c' object='rsyslogd-syslogd.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi`
+
+rsyslogd-pidfile.o: pidfile.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pidfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-pidfile.Tpo -c -o rsyslogd-pidfile.o `test -f 'pidfile.c' || echo '$(srcdir)/'`pidfile.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-pidfile.Tpo $(DEPDIR)/rsyslogd-pidfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pidfile.c' object='rsyslogd-pidfile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pidfile.o `test -f 'pidfile.c' || echo '$(srcdir)/'`pidfile.c
+
+rsyslogd-pidfile.obj: pidfile.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pidfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-pidfile.Tpo -c -o rsyslogd-pidfile.obj `if test -f 'pidfile.c'; then $(CYGPATH_W) 'pidfile.c'; else $(CYGPATH_W) '$(srcdir)/pidfile.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-pidfile.Tpo $(DEPDIR)/rsyslogd-pidfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pidfile.c' object='rsyslogd-pidfile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pidfile.obj `if test -f 'pidfile.c'; then $(CYGPATH_W) 'pidfile.c'; else $(CYGPATH_W) '$(srcdir)/pidfile.c'; fi`
+
+rsyslogd-template.o: template.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-template.o -MD -MP -MF $(DEPDIR)/rsyslogd-template.Tpo -c -o rsyslogd-template.o `test -f 'template.c' || echo '$(srcdir)/'`template.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-template.Tpo $(DEPDIR)/rsyslogd-template.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='template.c' object='rsyslogd-template.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-template.o `test -f 'template.c' || echo '$(srcdir)/'`template.c
+
+rsyslogd-template.obj: template.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-template.obj -MD -MP -MF $(DEPDIR)/rsyslogd-template.Tpo -c -o rsyslogd-template.obj `if test -f 'template.c'; then $(CYGPATH_W) 'template.c'; else $(CYGPATH_W) '$(srcdir)/template.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-template.Tpo $(DEPDIR)/rsyslogd-template.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='template.c' object='rsyslogd-template.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-template.obj `if test -f 'template.c'; then $(CYGPATH_W) 'template.c'; else $(CYGPATH_W) '$(srcdir)/template.c'; fi`
+
+rsyslogd-outchannel.o: outchannel.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-outchannel.o -MD -MP -MF $(DEPDIR)/rsyslogd-outchannel.Tpo -c -o rsyslogd-outchannel.o `test -f 'outchannel.c' || echo '$(srcdir)/'`outchannel.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-outchannel.Tpo $(DEPDIR)/rsyslogd-outchannel.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='outchannel.c' object='rsyslogd-outchannel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-outchannel.o `test -f 'outchannel.c' || echo '$(srcdir)/'`outchannel.c
+
+rsyslogd-outchannel.obj: outchannel.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-outchannel.obj -MD -MP -MF $(DEPDIR)/rsyslogd-outchannel.Tpo -c -o rsyslogd-outchannel.obj `if test -f 'outchannel.c'; then $(CYGPATH_W) 'outchannel.c'; else $(CYGPATH_W) '$(srcdir)/outchannel.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-outchannel.Tpo $(DEPDIR)/rsyslogd-outchannel.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='outchannel.c' object='rsyslogd-outchannel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-outchannel.obj `if test -f 'outchannel.c'; then $(CYGPATH_W) 'outchannel.c'; else $(CYGPATH_W) '$(srcdir)/outchannel.c'; fi`
+
+rsyslogd-stringbuf.o: stringbuf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-stringbuf.o -MD -MP -MF $(DEPDIR)/rsyslogd-stringbuf.Tpo -c -o rsyslogd-stringbuf.o `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-stringbuf.Tpo $(DEPDIR)/rsyslogd-stringbuf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='stringbuf.c' object='rsyslogd-stringbuf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-stringbuf.o `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c
+
+rsyslogd-stringbuf.obj: stringbuf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-stringbuf.obj -MD -MP -MF $(DEPDIR)/rsyslogd-stringbuf.Tpo -c -o rsyslogd-stringbuf.obj `if test -f 'stringbuf.c'; then $(CYGPATH_W) 'stringbuf.c'; else $(CYGPATH_W) '$(srcdir)/stringbuf.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-stringbuf.Tpo $(DEPDIR)/rsyslogd-stringbuf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='stringbuf.c' object='rsyslogd-stringbuf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-stringbuf.obj `if test -f 'stringbuf.c'; then $(CYGPATH_W) 'stringbuf.c'; else $(CYGPATH_W) '$(srcdir)/stringbuf.c'; fi`
+
+rsyslogd-srUtils.o: srUtils.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-srUtils.o -MD -MP -MF $(DEPDIR)/rsyslogd-srUtils.Tpo -c -o rsyslogd-srUtils.o `test -f 'srUtils.c' || echo '$(srcdir)/'`srUtils.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-srUtils.Tpo $(DEPDIR)/rsyslogd-srUtils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='srUtils.c' object='rsyslogd-srUtils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-srUtils.o `test -f 'srUtils.c' || echo '$(srcdir)/'`srUtils.c
+
+rsyslogd-srUtils.obj: srUtils.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-srUtils.obj -MD -MP -MF $(DEPDIR)/rsyslogd-srUtils.Tpo -c -o rsyslogd-srUtils.obj `if test -f 'srUtils.c'; then $(CYGPATH_W) 'srUtils.c'; else $(CYGPATH_W) '$(srcdir)/srUtils.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-srUtils.Tpo $(DEPDIR)/rsyslogd-srUtils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='srUtils.c' object='rsyslogd-srUtils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-srUtils.obj `if test -f 'srUtils.c'; then $(CYGPATH_W) 'srUtils.c'; else $(CYGPATH_W) '$(srcdir)/srUtils.c'; fi`
+
+rsyslogd-parse.o: parse.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-parse.o -MD -MP -MF $(DEPDIR)/rsyslogd-parse.Tpo -c -o rsyslogd-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-parse.Tpo $(DEPDIR)/rsyslogd-parse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='parse.c' object='rsyslogd-parse.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-parse.o `test -f 'parse.c' || echo '$(srcdir)/'`parse.c
+
+rsyslogd-parse.obj: parse.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-parse.obj -MD -MP -MF $(DEPDIR)/rsyslogd-parse.Tpo -c -o rsyslogd-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-parse.Tpo $(DEPDIR)/rsyslogd-parse.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='parse.c' object='rsyslogd-parse.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-parse.obj `if test -f 'parse.c'; then $(CYGPATH_W) 'parse.c'; else $(CYGPATH_W) '$(srcdir)/parse.c'; fi`
+
+rsyslogd-net.o: net.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-net.o -MD -MP -MF $(DEPDIR)/rsyslogd-net.Tpo -c -o rsyslogd-net.o `test -f 'net.c' || echo '$(srcdir)/'`net.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-net.Tpo $(DEPDIR)/rsyslogd-net.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net.c' object='rsyslogd-net.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-net.o `test -f 'net.c' || echo '$(srcdir)/'`net.c
+
+rsyslogd-net.obj: net.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-net.obj -MD -MP -MF $(DEPDIR)/rsyslogd-net.Tpo -c -o rsyslogd-net.obj `if test -f 'net.c'; then $(CYGPATH_W) 'net.c'; else $(CYGPATH_W) '$(srcdir)/net.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-net.Tpo $(DEPDIR)/rsyslogd-net.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net.c' object='rsyslogd-net.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-net.obj `if test -f 'net.c'; then $(CYGPATH_W) 'net.c'; else $(CYGPATH_W) '$(srcdir)/net.c'; fi`
+
+rsyslogd-msg.o: msg.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-msg.o -MD -MP -MF $(DEPDIR)/rsyslogd-msg.Tpo -c -o rsyslogd-msg.o `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-msg.Tpo $(DEPDIR)/rsyslogd-msg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='msg.c' object='rsyslogd-msg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-msg.o `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+
+rsyslogd-msg.obj: msg.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-msg.obj -MD -MP -MF $(DEPDIR)/rsyslogd-msg.Tpo -c -o rsyslogd-msg.obj `if test -f 'msg.c'; then $(CYGPATH_W) 'msg.c'; else $(CYGPATH_W) '$(srcdir)/msg.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-msg.Tpo $(DEPDIR)/rsyslogd-msg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='msg.c' object='rsyslogd-msg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-msg.obj `if test -f 'msg.c'; then $(CYGPATH_W) 'msg.c'; else $(CYGPATH_W) '$(srcdir)/msg.c'; fi`
+
+rsyslogd-omshell.o: omshell.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.o -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omshell.c' object='rsyslogd-omshell.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c
+
+rsyslogd-omshell.obj: omshell.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omshell.c' object='rsyslogd-omshell.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi`
+
+rsyslogd-omusrmsg.o: omusrmsg.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.o -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omusrmsg.c' object='rsyslogd-omusrmsg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c
+
+rsyslogd-omusrmsg.obj: omusrmsg.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omusrmsg.c' object='rsyslogd-omusrmsg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi`
+
+rsyslogd-ommysql.o: ommysql.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ommysql.o -MD -MP -MF $(DEPDIR)/rsyslogd-ommysql.Tpo -c -o rsyslogd-ommysql.o `test -f 'ommysql.c' || echo '$(srcdir)/'`ommysql.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-ommysql.Tpo $(DEPDIR)/rsyslogd-ommysql.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ommysql.c' object='rsyslogd-ommysql.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ommysql.o `test -f 'ommysql.c' || echo '$(srcdir)/'`ommysql.c
+
+rsyslogd-ommysql.obj: ommysql.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ommysql.obj -MD -MP -MF $(DEPDIR)/rsyslogd-ommysql.Tpo -c -o rsyslogd-ommysql.obj `if test -f 'ommysql.c'; then $(CYGPATH_W) 'ommysql.c'; else $(CYGPATH_W) '$(srcdir)/ommysql.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-ommysql.Tpo $(DEPDIR)/rsyslogd-ommysql.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ommysql.c' object='rsyslogd-ommysql.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ommysql.obj `if test -f 'ommysql.c'; then $(CYGPATH_W) 'ommysql.c'; else $(CYGPATH_W) '$(srcdir)/ommysql.c'; fi`
+
+rsyslogd-omfwd.o: omfwd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omfwd.c' object='rsyslogd-omfwd.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c
+
+rsyslogd-omfwd.obj: omfwd.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omfwd.c' object='rsyslogd-omfwd.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi`
+
+rsyslogd-tcpsyslog.o: tcpsyslog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-tcpsyslog.o -MD -MP -MF $(DEPDIR)/rsyslogd-tcpsyslog.Tpo -c -o rsyslogd-tcpsyslog.o `test -f 'tcpsyslog.c' || echo '$(srcdir)/'`tcpsyslog.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-tcpsyslog.Tpo $(DEPDIR)/rsyslogd-tcpsyslog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tcpsyslog.c' object='rsyslogd-tcpsyslog.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-tcpsyslog.o `test -f 'tcpsyslog.c' || echo '$(srcdir)/'`tcpsyslog.c
+
+rsyslogd-tcpsyslog.obj: tcpsyslog.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-tcpsyslog.obj -MD -MP -MF $(DEPDIR)/rsyslogd-tcpsyslog.Tpo -c -o rsyslogd-tcpsyslog.obj `if test -f 'tcpsyslog.c'; then $(CYGPATH_W) 'tcpsyslog.c'; else $(CYGPATH_W) '$(srcdir)/tcpsyslog.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-tcpsyslog.Tpo $(DEPDIR)/rsyslogd-tcpsyslog.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tcpsyslog.c' object='rsyslogd-tcpsyslog.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-tcpsyslog.obj `if test -f 'tcpsyslog.c'; then $(CYGPATH_W) 'tcpsyslog.c'; else $(CYGPATH_W) '$(srcdir)/tcpsyslog.c'; fi`
+
+rsyslogd-omfile.o: omfile.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omfile.c' object='rsyslogd-omfile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c
+
+rsyslogd-omfile.obj: omfile.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omfile.c' object='rsyslogd-omfile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi`
+
+rsyslogd-omdiscard.o: omdiscard.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.o -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omdiscard.c' object='rsyslogd-omdiscard.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c
+
+rsyslogd-omdiscard.obj: omdiscard.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='omdiscard.c' object='rsyslogd-omdiscard.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi`
+
+rsyslogd-modules.o: modules.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-modules.o -MD -MP -MF $(DEPDIR)/rsyslogd-modules.Tpo -c -o rsyslogd-modules.o `test -f 'modules.c' || echo '$(srcdir)/'`modules.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-modules.Tpo $(DEPDIR)/rsyslogd-modules.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modules.c' object='rsyslogd-modules.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-modules.o `test -f 'modules.c' || echo '$(srcdir)/'`modules.c
+
+rsyslogd-modules.obj: modules.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-modules.obj -MD -MP -MF $(DEPDIR)/rsyslogd-modules.Tpo -c -o rsyslogd-modules.obj `if test -f 'modules.c'; then $(CYGPATH_W) 'modules.c'; else $(CYGPATH_W) '$(srcdir)/modules.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-modules.Tpo $(DEPDIR)/rsyslogd-modules.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modules.c' object='rsyslogd-modules.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-modules.obj `if test -f 'modules.c'; then $(CYGPATH_W) 'modules.c'; else $(CYGPATH_W) '$(srcdir)/modules.c'; fi`
+
+rsyslogd-objomsr.o: objomsr.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-objomsr.o -MD -MP -MF $(DEPDIR)/rsyslogd-objomsr.Tpo -c -o rsyslogd-objomsr.o `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-objomsr.Tpo $(DEPDIR)/rsyslogd-objomsr.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='objomsr.c' object='rsyslogd-objomsr.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-objomsr.o `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c
+
+rsyslogd-objomsr.obj: objomsr.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-objomsr.obj -MD -MP -MF $(DEPDIR)/rsyslogd-objomsr.Tpo -c -o rsyslogd-objomsr.obj `if test -f 'objomsr.c'; then $(CYGPATH_W) 'objomsr.c'; else $(CYGPATH_W) '$(srcdir)/objomsr.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-objomsr.Tpo $(DEPDIR)/rsyslogd-objomsr.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='objomsr.c' object='rsyslogd-objomsr.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-objomsr.obj `if test -f 'objomsr.c'; then $(CYGPATH_W) 'objomsr.c'; else $(CYGPATH_W) '$(srcdir)/objomsr.c'; fi`
+
+rsyslogd-cfsysline.o: cfsysline.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-cfsysline.o -MD -MP -MF $(DEPDIR)/rsyslogd-cfsysline.Tpo -c -o rsyslogd-cfsysline.o `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-cfsysline.Tpo $(DEPDIR)/rsyslogd-cfsysline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cfsysline.c' object='rsyslogd-cfsysline.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-cfsysline.o `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c
+
+rsyslogd-cfsysline.obj: cfsysline.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-cfsysline.obj -MD -MP -MF $(DEPDIR)/rsyslogd-cfsysline.Tpo -c -o rsyslogd-cfsysline.obj `if test -f 'cfsysline.c'; then $(CYGPATH_W) 'cfsysline.c'; else $(CYGPATH_W) '$(srcdir)/cfsysline.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-cfsysline.Tpo $(DEPDIR)/rsyslogd-cfsysline.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cfsysline.c' object='rsyslogd-cfsysline.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-cfsysline.obj `if test -f 'cfsysline.c'; then $(CYGPATH_W) 'cfsysline.c'; else $(CYGPATH_W) '$(srcdir)/cfsysline.c'; fi`
+
+rsyslogd-linkedlist.o: linkedlist.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-linkedlist.o -MD -MP -MF $(DEPDIR)/rsyslogd-linkedlist.Tpo -c -o rsyslogd-linkedlist.o `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-linkedlist.Tpo $(DEPDIR)/rsyslogd-linkedlist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linkedlist.c' object='rsyslogd-linkedlist.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-linkedlist.o `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c
+
+rsyslogd-linkedlist.obj: linkedlist.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-linkedlist.obj -MD -MP -MF $(DEPDIR)/rsyslogd-linkedlist.Tpo -c -o rsyslogd-linkedlist.obj `if test -f 'linkedlist.c'; then $(CYGPATH_W) 'linkedlist.c'; else $(CYGPATH_W) '$(srcdir)/linkedlist.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-linkedlist.Tpo $(DEPDIR)/rsyslogd-linkedlist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='linkedlist.c' object='rsyslogd-linkedlist.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-linkedlist.obj `if test -f 'linkedlist.c'; then $(CYGPATH_W) 'linkedlist.c'; else $(CYGPATH_W) '$(srcdir)/linkedlist.c'; fi`
+
+rsyslogd-iminternal.o: iminternal.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.o -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='iminternal.c' object='rsyslogd-iminternal.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c
+
+rsyslogd-iminternal.obj: iminternal.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.obj -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='iminternal.c' object='rsyslogd-iminternal.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi`
+
+rsyslogd-action.o: action.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-action.o -MD -MP -MF $(DEPDIR)/rsyslogd-action.Tpo -c -o rsyslogd-action.o `test -f 'action.c' || echo '$(srcdir)/'`action.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-action.Tpo $(DEPDIR)/rsyslogd-action.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='action.c' object='rsyslogd-action.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-action.o `test -f 'action.c' || echo '$(srcdir)/'`action.c
+
+rsyslogd-action.obj: action.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-action.obj -MD -MP -MF $(DEPDIR)/rsyslogd-action.Tpo -c -o rsyslogd-action.obj `if test -f 'action.c'; then $(CYGPATH_W) 'action.c'; else $(CYGPATH_W) '$(srcdir)/action.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/rsyslogd-action.Tpo $(DEPDIR)/rsyslogd-action.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='action.c' object='rsyslogd-action.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-action.obj `if test -f 'action.c'; then $(CYGPATH_W) 'action.c'; else $(CYGPATH_W) '$(srcdir)/action.c'; fi`
+install-man5: $(man5_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)"
+ @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.5*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 5*) ;; \
+ *) ext='5' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst"; \
+ done
+uninstall-man5:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.5*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 5*) ;; \
+ *) ext='5' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man5dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man5dir)/$$inst"; \
+ done
+install-man8: $(man8_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 8*) ;; \
+ *) ext='8' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+ done
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 8*) ;; \
+ *) ext='8' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+installdirs:
+ for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man: install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man uninstall-sbinPROGRAMS
+
+uninstall-man: uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \
+ clean-generic clean-sbinPROGRAMS ctags dist dist-all \
+ dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip distcheck \
+ distclean distclean-compile distclean-generic distclean-hdr \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-man5 \
+ install-man8 install-pdf install-pdf-am install-ps \
+ install-ps-am install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-man uninstall-man5 uninstall-man8 \
+ uninstall-sbinPROGRAMS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..1b14f65
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+This file has been superseeded by ChangeLog. Please see there.
diff --git a/README b/README
new file mode 100644
index 0000000..e8cc42f
--- /dev/null
+++ b/README
@@ -0,0 +1,5 @@
+This file has been superseeded by the fils in the doc folder.
+Please see doc/manual.html for futher details. If you are
+looking for install information doc/install.html is for you!
+If you do not have the doc set, see
+ http://www.rsyslog.com/doc
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..b6d1f15
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,896 @@
+# generated automatically by aclocal 1.10 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_if(m4_PACKAGE_VERSION, [2.61],,
+[m4_fatal([this file was generated for autoconf 2.61.
+You have another version of autoconf. If you want to use that,
+you should regenerate the build system entirely.], [63])])
+
+# Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.10], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10])dnl
+_AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 12
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $1 | $1:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+dnl Make sure AC_PROG_CC is never called again, or it will override our
+dnl setting of CC.
+m4_define([AC_PROG_CC],
+ [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/action.c b/action.c
new file mode 100644
index 0000000..6dc58c4
--- /dev/null
+++ b/action.c
@@ -0,0 +1,192 @@
+/* action.c
+ *
+ * Implementation of the action object.
+ *
+ * File begun on 2007-08-06 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "syslogd.h"
+#include "template.h"
+#include "action.h"
+#include "modules.h"
+
+
+/* object static data (once for all instances) */
+static int glbliActionResumeInterval = 30;
+
+/* destructs an action descriptor object
+ * rgerhards, 2007-08-01
+ */
+rsRetVal actionDestruct(action_t *pThis)
+{
+ assert(pThis != NULL);
+
+ if(pThis->pMod != NULL)
+ pThis->pMod->freeInstance(pThis->pModData);
+
+ if(pThis->f_pMsg != NULL)
+ MsgDestruct(pThis->f_pMsg);
+
+ if(pThis->ppTpl != NULL)
+ free(pThis->ppTpl);
+ if(pThis->ppMsgs != NULL)
+ free(pThis->ppMsgs);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* create a new action descriptor object
+ * rgerhards, 2007-08-01
+ */
+rsRetVal actionConstruct(action_t **ppThis)
+{
+ DEFiRet;
+ action_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (action_t*) calloc(1, sizeof(action_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->iResumeInterval = glbliActionResumeInterval;
+
+finalize_it:
+ *ppThis = pThis;
+ return iRet;
+}
+
+
+/* set an action back to active state -- rgerhards, 2007-08-02
+ */
+static rsRetVal actionResume(action_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ pThis->bSuspended = 0;
+
+ return iRet;
+}
+
+
+/* set the global resume interval
+ */
+rsRetVal actionSetGlobalResumeInterval(int iNewVal)
+{
+ glbliActionResumeInterval = iNewVal;
+ return RS_RET_OK;
+}
+
+
+/* suspend an action -- rgerhards, 2007-08-02
+ */
+rsRetVal actionSuspend(action_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ pThis->bSuspended = 1;
+ pThis->ttResumeRtry = time(NULL) + pThis->iResumeInterval;
+ pThis->iNbrResRtry = 0; /* tell that we did not yet retry to resume */
+
+ return iRet;
+}
+
+/* try to resume an action -- rgerhards, 2007-08-02
+ * returns RS_RET_OK if resumption worked, RS_RET_SUSPEND if the
+ * action is still suspended.
+ */
+rsRetVal actionTryResume(action_t *pThis)
+{
+ DEFiRet;
+ time_t ttNow;
+
+ assert(pThis != NULL);
+
+ ttNow = time(NULL); /* do the system call just once */
+
+ /* first check if it is time for a re-try */
+ if(ttNow > pThis->ttResumeRtry) {
+ iRet = pThis->pMod->tryResume(pThis->pModData);
+ if(iRet == RS_RET_SUSPENDED) {
+ /* set new tryResume time */
+ ++pThis->iNbrResRtry;
+ /* if we have more than 10 retries, we prolong the
+ * retry interval. If something is really stalled, it will
+ * get re-tried only very, very seldom - but that saves
+ * CPU time. TODO: maybe a config option for that?
+ * rgerhards, 2007-08-02
+ */
+ pThis->ttResumeRtry = ttNow + pThis->iResumeInterval * (pThis->iNbrResRtry / 10 + 1);
+ }
+ } else {
+ /* it's too early, we are still suspended --> indicate this */
+ iRet = RS_RET_SUSPENDED;
+ }
+
+ if(iRet == RS_RET_OK)
+ actionResume(pThis);
+
+ dbgprintf("actionTryResume: iRet: %d, next retry (if applicable): %u [now %u]\n",
+ iRet, (unsigned) pThis->ttResumeRtry, (unsigned) ttNow);
+
+ return iRet;
+}
+
+
+/* debug-print the contents of an action object
+ * rgerhards, 2007-08-02
+ */
+rsRetVal actionDbgPrint(action_t *pThis)
+{
+ DEFiRet;
+
+ printf("%s: ", modGetStateName(pThis->pMod));
+ pThis->pMod->dbgPrintInstInfo(pThis->pModData);
+ printf("\n\tInstance data: 0x%x\n", (unsigned) pThis->pModData);
+ printf("\tRepeatedMsgReduction: %d\n", pThis->f_ReduceRepeated);
+ printf("\tResume Interval: %d\n", pThis->iResumeInterval);
+ printf("\tSuspended: %d", pThis->bSuspended);
+ if(pThis->bSuspended) {
+ printf(" next retry: %u, number retries: %d", (unsigned) pThis->ttResumeRtry, pThis->iNbrResRtry);
+ }
+ printf("\n");
+ printf("\tDisabled: %d\n", !pThis->bEnabled);
+ printf("\tExec only when previous is suspended: %d\n", pThis->bExecWhenPrevSusp);
+ printf("\n");
+
+ return iRet;
+}
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/action.h b/action.h
new file mode 100644
index 0000000..e7757d7
--- /dev/null
+++ b/action.h
@@ -0,0 +1,82 @@
+/* action.h
+ * Header file for the action object
+ *
+ * File begun on 2007-08-06 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef ACTION_H_INCLUDED
+#define ACTION_H_INCLUDED 1
+
+#include "syslogd-types.h"
+
+/* the following struct defines the action object data structure
+ */
+struct action_s {
+ time_t f_time; /* time this was last written */
+ int bExecWhenPrevSusp;/* execute only when previous action is suspended? */
+ short bEnabled; /* is the related action enabled (1) or disabled (0)? */
+ short bSuspended; /* is the related action temporarily suspended? */
+ time_t ttResumeRtry; /* when is it time to retry the resume? */
+ int iResumeInterval;/* resume interval for this action */
+ int iNbrResRtry; /* number of retries since last suspend */
+ struct moduleInfo *pMod;/* pointer to output module handling this selector */
+ void *pModData; /* pointer to module data - contents is module-specific */
+ int f_ReduceRepeated;/* reduce repeated lines 0 - no, 1 - yes */
+ int f_prevcount; /* repetition cnt of prevline */
+ int f_repeatcount; /* number of "repeated" msgs */
+ int iNumTpls; /* number of array entries for template element below */
+ struct template **ppTpl;/* array of template to use - strings must be passed to doAction
+ * in this order. */
+
+ uchar **ppMsgs; /* array of message pointers for doAction */
+ struct msg* f_pMsg; /* pointer to the message (this will replace the other vars with msg
+ * content later). This is preserved after the message has been
+ * processed - it is also used to detect duplicates.
+ */
+};
+typedef struct action_s action_t;
+
+
+/* function prototypes
+ */
+rsRetVal actionConstruct(action_t **ppThis);
+rsRetVal actionDestruct(action_t *pThis);
+rsRetVal actionTryResume(action_t *pThis);
+rsRetVal actionSuspend(action_t *pThis);
+rsRetVal actionDbgPrint(action_t *pThis);
+rsRetVal actionSetGlobalResumeInterval(int iNewVal);
+
+#if 1
+#define actionIsSuspended(pThis) ((pThis)->bSuspended == 1)
+#else
+/* The function is a debugging aid */
+inline int actionIsSuspended(action_t *pThis)
+{
+ int i;
+ i = pThis->bSuspended == 1;
+ dbgprintf("in IsSuspend(), returns %d\n", i);
+ return i;
+}
+#endif
+
+#endif /* #ifndef ACTION_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/cfsysline.c b/cfsysline.c
new file mode 100644
index 0000000..fcbf139
--- /dev/null
+++ b/cfsysline.c
@@ -0,0 +1,661 @@
+/* cfsysline.c
+ * Implementation of the configuration system line object.
+ *
+ * File begun on 2007-07-30 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "syslogd.h" /* TODO: when the module interface & library design is done, this should be able to go away */
+#include "cfsysline.h"
+#include "srUtils.h"
+
+
+/* static data */
+linkedList_t llCmdList; /* this is NOT a pointer - no typo here ;) */
+
+/* --------------- START functions for handling canned syntaxes --------------- */
+
+
+/* parse a character from the config line
+ * added 2007-07-17 by rgerhards
+ * TODO: enhance this function to handle different classes of characters
+ * HINT: check if char is ' and, if so, use 'c' where c may also be things
+ * like \t etc.
+ */
+static rsRetVal doGetChar(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ /* if we are not at a '\0', we have our new char - no validity checks here... */
+ if(**pp == '\0') {
+ logerror("No character available");
+ iRet = RS_RET_NOT_FOUND;
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((uchar*)pVal) = **pp;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, **pp));
+ }
+ ++(*pp); /* eat processed char */
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Parse a number from the configuration line. This is more or less
+ * a shell to call the custom handler.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal doCustomHdlr(uchar **pp, rsRetVal (*pSetHdlr)(uchar**, void*), void *pVal)
+{
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ CHKiRet(pSetHdlr(pp, pVal));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Parse a number from the configuration line.
+ * rgerhards, 2007-07-31
+ */
+static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ uchar *p;
+ DEFiRet;
+ int i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+ p = *pp;
+
+ if(!isdigit((int) *p)) {
+ errno = 0;
+ logerror("invalid number");
+ ABORT_FINALIZE(RS_RET_INVALID_INT);
+ }
+
+ /* pull value */
+ for(i = 0 ; *p && isdigit((int) *p) ; ++p)
+ i = i * 10 + *p - '0';
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = i;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, i));
+ }
+
+ *pp = p;
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Parse and interpet a $FileCreateMode and $umask line. This function
+ * pulls the creation mode and, if successful, stores it
+ * into the global variable so that the rest of rsyslogd
+ * opens files with that mode. Any previous value will be
+ * overwritten.
+ * HINT: if we store the creation mode in selector_t, we
+ * can even specify multiple modes simply be virtue of
+ * being placed in the right section of rsyslog.conf
+ * rgerhards, 2007-07-4 (happy independence day to my US friends!)
+ * Parameter **pp has a pointer to the current config line.
+ * On exit, it will be updated to the processed position.
+ */
+static rsRetVal doFileCreateMode(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ uchar *p;
+ DEFiRet;
+ uchar errMsg[128]; /* for dynamic error messages */
+ int iVal;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+ p = *pp;
+
+ /* for now, we parse and accept only octal numbers
+ * Sequence of tests is important, we are using boolean shortcuts
+ * to avoid addressing invalid memory!
+ */
+ if(!( (*p == '0')
+ && (*(p+1) && *(p+1) >= '0' && *(p+1) <= '7')
+ && (*(p+2) && *(p+2) >= '0' && *(p+2) <= '7')
+ && (*(p+3) && *(p+3) >= '0' && *(p+3) <= '7') ) ) {
+ snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
+ "value must be octal (e.g 0644).");
+ errno = 0;
+ logerror((char*) errMsg);
+ ABORT_FINALIZE(RS_RET_INVALID_VALUE);
+ }
+
+ /* we reach this code only if the octal number is ok - so we can now
+ * compute the value.
+ */
+ iVal = (*(p+1)-'0') * 64 + (*(p+2)-'0') * 8 + (*(p+3)-'0');
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = iVal;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, iVal));
+ }
+
+ p += 4; /* eat the octal number */
+ *pp = p;
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Parse and interpret an on/off inside a config file line. This is most
+ * often used for boolean options, but of course it may also be used
+ * for other things. The passed-in pointer is updated to point to
+ * the first unparsed character on exit. Function emits error messages
+ * if the value is neither on or off. It returns 0 if the option is off,
+ * 1 if it is on and another value if there was an error.
+ * rgerhards, 2007-07-15
+ */
+static int doParseOnOffOption(uchar **pp)
+{
+ uchar *pOptStart;
+ uchar szOpt[32];
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ pOptStart = *pp;
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+ if(getSubString(pp, (char*) szOpt, sizeof(szOpt) / sizeof(uchar), ' ') != 0) {
+ logerror("Invalid $-configline - could not extract on/off option");
+ return -1;
+ }
+
+ if(!strcmp((char*)szOpt, "on")) {
+ return 1;
+ } else if(!strcmp((char*)szOpt, "off")) {
+ return 0;
+ } else {
+ logerrorSz("Option value must be on or off, but is '%s'", (char*)pOptStart);
+ return -1;
+ }
+}
+
+
+/* extract a groupname and return its gid.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ struct group *pgBuf;
+ struct group gBuf;
+ DEFiRet;
+ uchar szName[256];
+ char stringBuf[2048]; /* I hope this is large enough... */
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
+ logerror("could not extract group name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ getgrnam_r((char*)szName, &gBuf, stringBuf, sizeof(stringBuf), &pgBuf);
+
+ if(pgBuf == NULL) {
+ logerrorSz("ID for group '%s' could not be found or error", (char*)szName);
+ iRet = RS_RET_NOT_FOUND;
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((gid_t*)pVal) = pgBuf->gr_gid;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, pgBuf->gr_gid));
+ }
+ dbgprintf("gid %d obtained for group '%s'\n", pgBuf->gr_gid, szName);
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ return iRet;
+}
+
+
+/* extract a username and return its uid.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal doGetUID(uchar **pp, rsRetVal (*pSetHdlr)(void*, uid_t), void *pVal)
+{
+ struct passwd *ppwBuf;
+ struct passwd pwBuf;
+ DEFiRet;
+ uchar szName[256];
+ char stringBuf[2048]; /* I hope this is large enough... */
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
+ logerror("could not extract user name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ getpwnam_r((char*)szName, &pwBuf, stringBuf, sizeof(stringBuf), &ppwBuf);
+
+ if(ppwBuf == NULL) {
+ logerrorSz("ID for user '%s' could not be found or error", (char*)szName);
+ iRet = RS_RET_NOT_FOUND;
+ } else {
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((uid_t*)pVal) = ppwBuf->pw_uid;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, ppwBuf->pw_uid));
+ }
+ dbgprintf("uid %d obtained for user '%s'\n", ppwBuf->pw_uid, szName);
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Parse and process an binary cofig option. pVal must be
+ * a pointer to an integer which is to receive the option
+ * value.
+ * rgerhards, 2007-07-15
+ */
+static rsRetVal doBinaryOptionLine(uchar **pp, rsRetVal (*pSetHdlr)(void*, int), void *pVal)
+{
+ int iOption;
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if((iOption = doParseOnOffOption(pp)) == -1)
+ return RS_RET_ERR; /* nothing left to do */
+
+ if(pSetHdlr == NULL) {
+ /* we should set value directly to var */
+ *((int*)pVal) = iOption;
+ } else {
+ /* we set value via a set function */
+ CHKiRet(pSetHdlr(pVal, iOption));
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ return iRet;
+}
+
+
+/* --------------- END functions for handling canned syntaxes --------------- */
+
+/* destructor for cslCmdHdlr
+ * pThis is actually a cslCmdHdlr_t, but we do not cast it as all we currently
+ * need to do is free it.
+ */
+static rsRetVal cslchDestruct(void *pThis)
+{
+ assert(pThis != NULL);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor for cslCmdHdlr
+ */
+static rsRetVal cslchConstruct(cslCmdHdlr_t **ppThis)
+{
+ cslCmdHdlr_t *pThis;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ if((pThis = calloc(1, sizeof(cslCmdHdlr_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+finalize_it:
+ *ppThis = pThis;
+ return iRet;
+}
+
+/* set data members for this object
+ */
+rsRetVal cslchSetEntry(cslCmdHdlr_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
+{
+ assert(pThis != NULL);
+ assert(eType != eCmdHdlrInvalid);
+
+ pThis->eType = eType;
+ pThis->cslCmdHdlr = pHdlr;
+ pThis->pData = pData;
+
+ return RS_RET_OK;
+}
+
+
+/* call the specified handler
+ */
+static rsRetVal cslchCallHdlr(cslCmdHdlr_t *pThis, uchar **ppConfLine)
+{
+ DEFiRet;
+ rsRetVal (*pHdlr)() = NULL;
+ assert(pThis != NULL);
+ assert(ppConfLine != NULL);
+
+ switch(pThis->eType) {
+ case eCmdHdlrCustomHandler:
+ pHdlr = doCustomHdlr;
+ break;
+ case eCmdHdlrUID:
+ pHdlr = doGetUID;
+ break;
+ case eCmdHdlrGID:
+ pHdlr = doGetGID;
+ break;
+ case eCmdHdlrBinary:
+ pHdlr = doBinaryOptionLine;
+ break;
+ case eCmdHdlrFileCreateMode:
+ pHdlr = doFileCreateMode;
+ break;
+ case eCmdHdlrInt:
+ pHdlr = doGetInt;
+ break;
+ case eCmdHdlrGetChar:
+ pHdlr = doGetChar;
+ break;
+ default:
+ iRet = RS_RET_NOT_IMPLEMENTED;
+ goto finalize_it;
+ }
+
+ /* we got a pointer to the handler, so let's call it */
+ assert(pHdlr != NULL);
+ CHKiRet(pHdlr(ppConfLine, pThis->cslCmdHdlr, pThis->pData));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* ---------------------------------------------------------------------- *
+ * now come the handlers for cslCmd_t
+ * ---------------------------------------------------------------------- */
+
+/* destructor for a cslCmd list key (a string as of now)
+ */
+static rsRetVal cslcKeyDestruct(void *pData)
+{
+ free(pData); /* we do not need to cast as all we do is free it anyway... */
+ return RS_RET_OK;
+}
+
+/* destructor for cslCmd
+ */
+static rsRetVal cslcDestruct(void *pData)
+{
+ cslCmd_t *pThis = (cslCmd_t*) pData;
+
+ assert(pThis != NULL);
+
+ llDestroy(&pThis->llCmdHdlrs);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor for cslCmd
+ */
+static rsRetVal cslcConstruct(cslCmd_t **ppThis, int bChainingPermitted)
+{
+ cslCmd_t *pThis;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ if((pThis = calloc(1, sizeof(cslCmd_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->bChainingPermitted = bChainingPermitted;
+
+ CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, NULL, NULL));
+
+finalize_it:
+ *ppThis = pThis;
+ return iRet;
+}
+
+
+/* add a handler entry to a known command
+ */
+static rsRetVal cslcAddHdlr(cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
+{
+ DEFiRet;
+ cslCmdHdlr_t *pCmdHdlr = NULL;
+
+ assert(pThis != NULL);
+
+ CHKiRet(cslchConstruct(&pCmdHdlr));
+ CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData));
+ CHKiRet(llAppend(&pThis->llCmdHdlrs, NULL, pCmdHdlr));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pHdlr != NULL)
+ cslchDestruct(pCmdHdlr);
+ }
+
+ return iRet;
+}
+
+
+/* function that initializes this module here. This is primarily a hook
+ * for syslogd.
+ */
+rsRetVal cfsyslineInit(void)
+{
+ DEFiRet;
+
+ CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, strcasecmp));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* function that registers cfsysline handlers.
+ * The supplied pCmdName is copied and a new buffer is allocated. This
+ * buffer is automatically destroyed when the element is freed, the
+ * caller does not need to take care of that. The caller must, however,
+ * free pCmdName if he allocated it dynamically! -- rgerhards, 2007-08-09
+ */
+rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData)
+{
+ cslCmd_t *pThis;
+ uchar *pMyCmdName;
+ DEFiRet;
+
+ iRet = llFind(&llCmdList, (void *) pCmdName, (void**) &pThis);
+ if(iRet == RS_RET_NOT_FOUND) {
+ /* new command */
+ CHKiRet(cslcConstruct(&pThis, bChainingPermitted));
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData)) {
+ cslcDestruct(pThis);
+ goto finalize_it;
+ }
+ /* important: add to list, AFTER everything else is OK. Else
+ * we mess up things in the error case.
+ */
+ if((pMyCmdName = (uchar*) strdup((char*)pCmdName)) == NULL) {
+ cslcDestruct(pThis);
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ CHKiRet_Hdlr(llAppend(&llCmdList, pMyCmdName, (void*) pThis)) {
+ cslcDestruct(pThis);
+ goto finalize_it;
+ }
+ } else {
+ /* command already exists, are we allowed to chain? */
+ if(pThis->bChainingPermitted == 0 || bChainingPermitted == 0) {
+ ABORT_FINALIZE(RS_RET_CHAIN_NOT_PERMITTED);
+ }
+ CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData)) {
+ cslcDestruct(pThis);
+ goto finalize_it;
+ }
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* process a cfsysline command (based on handler structure)
+ * param "p" is a pointer to the command line after the command. Should be
+ * updated.
+ */
+rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p)
+{
+ DEFiRet;
+ rsRetVal iRetLL; /* for linked list handling */
+ cslCmd_t *pCmd;
+ cslCmdHdlr_t *pCmdHdlr;
+ linkedListCookie_t llCookieCmdHdlr;
+ uchar *pHdlrP; /* the handler's private p (else we could only call one handler) */
+ int bWasOnceOK; /* was the result of an handler at least once RS_RET_OK? */
+ uchar *pOKp = NULL; /* returned conf line pointer when it was OK */
+
+ iRet = llFind(&llCmdList, (void *) pCmdName, (void**) &pCmd);
+
+ if(iRet == RS_RET_NOT_FOUND) {
+ logerror("invalid or yet-unknown config file command - have you forgotten to load a module?");
+ }
+
+ if(iRet != RS_RET_OK)
+ goto finalize_it;
+
+ llCookieCmdHdlr = NULL;
+ bWasOnceOK = 0;
+ while((iRetLL = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void**)&pCmdHdlr)) == RS_RET_OK) {
+ /* for the time being, we ignore errors during handlers. The
+ * reason is that handlers are independent. An error in one
+ * handler does not necessarily mean that another one will
+ * fail, too. Later, we might add a config variable to control
+ * this behaviour (but I am not sure if that is rally
+ * necessary). -- rgerhards, 2007-07-31
+ */
+ pHdlrP = *p;
+ if((iRet = cslchCallHdlr(pCmdHdlr, &pHdlrP)) == RS_RET_OK) {
+ bWasOnceOK = 1;
+ pOKp = pHdlrP;
+ }
+ }
+
+ if(bWasOnceOK == 1) {
+ *p = pOKp;
+ iRet = RS_RET_OK;
+ }
+
+ if(iRetLL != RS_RET_END_OF_LINKEDLIST)
+ iRet = iRetLL;
+
+finalize_it:
+ return iRet;
+}
+
+
+/* debug print the command handler structure
+ */
+void dbgPrintCfSysLineHandlers(void)
+{
+ DEFiRet;
+
+ cslCmd_t *pCmd;
+ cslCmdHdlr_t *pCmdHdlr;
+ linkedListCookie_t llCookieCmd;
+ linkedListCookie_t llCookieCmdHdlr;
+ uchar *pKey;
+
+ printf("\nSytem Line Configuration Commands:\n");
+ llCookieCmd = NULL;
+ while((iRet = llGetNextElt(&llCmdList, &llCookieCmd, (void**)&pCmd)) == RS_RET_OK) {
+ llGetKey(llCookieCmd, (void**) &pKey); /* TODO: using the cookie is NOT clean! */
+ printf("\tCommand '%s':\n", pKey);
+ llCookieCmdHdlr = NULL;
+ while((iRet = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void**)&pCmdHdlr)) == RS_RET_OK) {
+ printf("\t\ttype : %d\n", pCmdHdlr->eType);
+ printf("\t\tpData: 0x%x\n", (unsigned) pCmdHdlr->pData);
+ printf("\t\tHdlr : 0x%x\n", (unsigned) pCmdHdlr->cslCmdHdlr);
+ printf("\n");
+ }
+ }
+ printf("\n");
+
+}
+
+/*
+ * vi:set ai:
+ */
diff --git a/cfsysline.h b/cfsysline.h
new file mode 100644
index 0000000..99217e6
--- /dev/null
+++ b/cfsysline.h
@@ -0,0 +1,68 @@
+/* Definition of the cfsysline (config file system line) object.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#ifndef CFSYSLINE_H_INCLUDED
+#define CFSYSLINE_H_INCLUDED
+
+#include "linkedlist.h"
+
+/* types of configuration handlers
+ */
+typedef enum cslCmdHdlrType {
+ eCmdHdlrInvalid = 0, /* invalid handler type - indicates a coding error */
+ eCmdHdlrCustomHandler, /* custom handler, just call handler function */
+ eCmdHdlrUID,
+ eCmdHdlrGID,
+ eCmdHdlrBinary,
+ eCmdHdlrFileCreateMode,
+ eCmdHdlrInt,
+ eCmdHdlrGetChar
+} ecslCmdHdrlType;
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct cslCmdHdlr_s { /* config file sysline parse entry */
+ ecslCmdHdrlType eType; /* which type of handler is this? */
+ rsRetVal (*cslCmdHdlr)(); /* function pointer to use with handler (params depending on eType) */
+ void *pData; /* user-supplied data pointer */
+};
+typedef struct cslCmdHdlr_s cslCmdHdlr_t;
+
+
+/* this is the list of known configuration commands with pointers to
+ * their handlers.
+ * The short name is cslc (Configfile SysLine Command)
+ */
+struct cslCmd_s { /* config file sysline parse entry */
+ int bChainingPermitted; /* may multiple handlers be chained for this command? */
+ linkedList_t llCmdHdlrs; /* linked list of command handlers */
+};
+typedef struct cslCmd_s cslCmd_t;
+
+/* prototypes */
+rsRetVal regCfSysLineHdlr(uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData);
+rsRetVal processCfSysLineCommand(uchar *pCmd, uchar **p);
+rsRetVal cfsyslineInit(void);
+void dbgPrintCfSysLineHandlers(void);
+
+#endif /* #ifndef CFSYSLINE_H_INCLUDED */
diff --git a/compile b/compile
new file mode 100755
index 0000000..1b1d232
--- /dev/null
+++ b/compile
@@ -0,0 +1,142 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2005-05-14.22
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program 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 2, or (at your option)
+# any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as `compile cc -o foo foo.c'.
+ # So we strip `-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no `-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # `.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..0f0fe71
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1516 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-03-06'
+
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa:Linux:*:*)
+ echo xtensa-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..b3eff83
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,304 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Description */
+#undef BSD
+
+/* klogd functionality is integrated. */
+#undef FEATURE_KLOGD
+
+/* Regular expressions support enabled. */
+#undef FEATURE_REGEXP
+
+/* Description */
+#undef FSSTND
+
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#undef HAVE_ARPA_NAMESER_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `fork' function. */
+#undef HAVE_FORK
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `rt' library (-lrt). */
+#undef HAVE_LIBRT
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <mysql/mysql.h> header file. */
+#undef HAVE_MYSQL_MYSQL_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `regcomp' function. */
+#undef HAVE_REGCOMP
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#undef HAVE_RESOLV_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio_ext.h> header file. */
+#undef HAVE_STDIO_EXT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if `sa_len' is member of `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* Define to 1 if you have the `vfork' function. */
+#undef HAVE_VFORK
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#undef HAVE_VFORK_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the `wait3' system call. Deprecated, you should no
+ longer depend upon `wait3'. */
+#undef HAVE_WAIT3
+
+/* Define to 1 if `fork' works. */
+#undef HAVE_WORKING_FORK
+
+/* Define to 1 if `vfork' works. */
+#undef HAVE_WORKING_VFORK
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Defined if debug mode is disabled. */
+#undef NDEBUG
+
+/* Defined when large file support is disabled. */
+#undef NOLARGEFILE
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg 1 for `select'. */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for `select'. */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg 5 for `select'. */
+#undef SELECT_TYPE_ARG5
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* network support is integrated. */
+#undef SYSLOG_INET
+
+/* Description */
+#undef SYSLOG_UNIXAF
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Define if you want to enable zlib support */
+#undef USE_NETZIP
+
+/* Multithreading support enabled. */
+#undef USE_PTHREADS
+
+/* Version number of package */
+#undef VERSION
+
+/* MySql database support enabled */
+#undef WITH_DB
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define as `fork' if `vfork' does not work. */
+#undef vfork
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..5defff6
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1622 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+# Inc.
+
+timestamp='2007-01-18'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..75d16a8
--- /dev/null
+++ b/configure
@@ -0,0 +1,9385 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for rsyslog 1.18.2.
+#
+# Report bugs to <rsyslog@lists.adiscon.com.>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='rsyslog'
+PACKAGE_TARNAME='rsyslog'
+PACKAGE_VERSION='1.18.2'
+PACKAGE_STRING='rsyslog 1.18.2'
+PACKAGE_BUGREPORT='rsyslog@lists.adiscon.com.'
+
+ac_unique_file="syslogd.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+CPP
+GREP
+EGREP
+LIBOBJS
+enable_mysql_TRUE
+enable_mysql_FALSE
+mysql_includes
+mysql_libs
+zlib_libs
+pthreads_libs
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures rsyslog 1.18.2 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/rsyslog]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of rsyslog 1.18.2:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-largefile Enable large file support [default=yes]
+ --enable-mysql Enable MySql database support [default=no]
+ --enable-regexp Enable regular expressions support [default=yes]
+ --enable-zlib Enable zlib compression support [default=yes]
+ --enable-pthreads Enable multithreading via pthreads [default=yes]
+ --enable-klogd Integrated klogd functionality [default=yes]
+ --disable-unix disable support for unix
+ --enable-inet Enable networking support [default=yes]
+ --disable-fsstnd disable support for FSSTND
+ --enable-debug Enable debug mode [default=no]
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <rsyslog@lists.adiscon.com.>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+rsyslog configure 1.18.2
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by rsyslog $as_me 1.18.2, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.10'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+done
+IFS=$as_save_IFS
+
+fi
+
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ test -d ./--version && rmdir ./--version
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE=rsyslog
+ VERSION=1.18.2
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+if test "x$CC" != xcc; then
+ { echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5
+echo $ECHO_N "checking whether $CC and cc understand -c and -o together... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5
+echo $ECHO_N "checking whether cc understands -c and -o together... $ECHO_C" >&6; }
+fi
+set dummy $CC; ac_cc=`echo $2 |
+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); };
+then
+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+ if test "x$CC" != xcc; then
+ # Test first that cc exists at all.
+ if { ac_try='cc -c conftest.$ac_ext >&5'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+ rm -f conftest2.*
+ if { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); };
+ then
+ # cc works too.
+ :
+ else
+ # cc exists but doesn't like -o.
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+ fi
+ fi
+ fi
+else
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f core conftest*
+
+fi
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define NO_MINUS_C_MINUS_O 1
+_ACEOF
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+
+
+if test "$GCC" = "yes"
+then CFLAGS="$CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute -g"
+fi
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+case "${host}" in
+ *-*-linux*)
+ # This feature indicates if klogd functionality
+ # should be integrated. If it is switched off, klogd
+ # is still compiled, but it is an empty shell.
+
+cat >>confdefs.h <<\_ACEOF
+#define FEATURE_KLOGD 1
+_ACEOF
+
+ ;;
+ *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
+
+cat >>confdefs.h <<\_ACEOF
+#define BSD 1
+_ACEOF
+
+ ;;
+esac
+
+# Checks for libraries.
+
+
+{ echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
+echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_rt_clock_gettime=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_rt_clock_gettime=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6; }
+if test $ac_cv_lib_rt_clock_gettime = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRT 1
+_ACEOF
+
+ LIBS="-lrt $LIBS"
+
+fi
+
+
+# Checks for header files.
+
+
+
+
+
+for ac_header in sys/types.h netinet/in.h arpa/nameser.h netdb.h resolv.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h> /* inet_ functions / structs */
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h> /* DNS HEADER struct */
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; }
+if test "${ac_cv_header_sys_wait_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_sys_wait_h=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_WAIT_H 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in arpa/inet.h fcntl.h locale.h netdb.h netinet/in.h paths.h stdio_ext.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset cs;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_inline=$ac_kw
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_off_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef off_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_off_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_off_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
+if test $ac_cv_type_off_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_pid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef pid_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_pid_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_pid_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
+if test $ac_cv_type_pid_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_ssize_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef ssize_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_ssize_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_ssize_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6; }
+if test $ac_cv_type_ssize_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; }
+if test "${ac_cv_struct_tm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_struct_tm=time.h
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_struct_tm=sys/time.h
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for working volatile" >&5
+echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; }
+if test "${ac_cv_c_volatile+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_volatile=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_volatile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_volatile" >&5
+echo "${ECHO_T}$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define volatile
+_ACEOF
+
+fi
+
+
+sa_includes="\
+$ac_includes_default
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+"
+{ echo "$as_me:$LINENO: checking for struct sockaddr.sa_len" >&5
+echo $ECHO_N "checking for struct sockaddr.sa_len... $ECHO_C" >&6; }
+if test "${ac_cv_member_struct_sockaddr_sa_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$sa_includes
+
+int
+main ()
+{
+static struct sockaddr ac_aggr;
+if (ac_aggr.sa_len)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_struct_sockaddr_sa_len=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$sa_includes
+
+int
+main ()
+{
+static struct sockaddr ac_aggr;
+if (sizeof ac_aggr.sa_len)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_member_struct_sockaddr_sa_len=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_member_struct_sockaddr_sa_len=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_sa_len" >&5
+echo "${ECHO_T}$ac_cv_member_struct_sockaddr_sa_len" >&6; }
+if test $ac_cv_member_struct_sockaddr_sa_len = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+_ACEOF
+
+
+fi
+
+
+# Checks for library functions.
+
+for ac_header in vfork.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_func in fork vfork
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { echo "$as_me:$LINENO: checking for working fork" >&5
+echo $ECHO_N "checking for working fork... $ECHO_C" >&6; }
+if test "${ac_cv_func_fork_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_fork_works=cross
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_fork_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5
+echo "${ECHO_T}$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { echo "$as_me:$LINENO: checking for working vfork" >&5
+echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; }
+if test "${ac_cv_func_vfork_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_vfork_works=cross
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_vfork_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5
+echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_VFORK 1
+_ACEOF
+
+else
+
+cat >>confdefs.h <<\_ACEOF
+#define vfork fork
+_ACEOF
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_FORK 1
+_ACEOF
+
+fi
+
+if test $ac_cv_c_compiler_gnu = yes; then
+ { echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6; }
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_pattern="Autoconf.*'x'"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+else
+ ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+ if test $ac_cv_prog_gcc_traditional = no; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "$ac_pattern" >/dev/null 2>&1; then
+ ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6; }
+ if test $ac_cv_prog_gcc_traditional = yes; then
+ CC="$CC -traditional"
+ fi
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_malloc_0_nonnull=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_malloc_0_nonnull=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+ case " $LIBOBJS " in
+ *" malloc.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5
+echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; }
+if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_realloc_0_nonnull=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+return ! realloc (0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_realloc_0_nonnull=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; }
+if test $ac_cv_func_realloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 1
+_ACEOF
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_REALLOC 0
+_ACEOF
+
+ case " $LIBOBJS " in
+ *" realloc.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define realloc rpl_realloc
+_ACEOF
+
+fi
+
+
+
+
+
+for ac_header in sys/select.h sys/socket.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ echo "$as_me:$LINENO: checking types of arguments for select" >&5
+echo $ECHO_N "checking types of arguments for select... $ECHO_C" >&6; }
+if test "${ac_cv_func_select_args+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ for ac_arg234 in 'fd_set *' 'int *' 'void *'; do
+ for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do
+ for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+int
+main ()
+{
+extern int select ($ac_arg1,
+ $ac_arg234, $ac_arg234, $ac_arg234,
+ $ac_arg5);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+ done
+done
+# Provide a safe default value.
+: ${ac_cv_func_select_args='int,int *,struct timeval *'}
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_select_args" >&5
+echo "${ECHO_T}$ac_cv_func_select_args" >&6; }
+ac_save_IFS=$IFS; IFS=','
+set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'`
+IFS=$ac_save_IFS
+shift
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG1 $1
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG234 ($2)
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define SELECT_TYPE_ARG5 ($3)
+_ACEOF
+
+rm -f conftest*
+
+{ echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+if test "${ac_cv_type_signal+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <signal.h>
+
+int
+main ()
+{
+return *(signal (0, 0)) (0) == 1;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_signal=int
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_signal=void
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+{ echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
+echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; }
+if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ /* Linux will dereference the symlink and fail.
+ That is better in the sense that it means we will not
+ have to compile and use the lstat wrapper. */
+ return lstat ("conftest.sym/", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+else
+ # If the `ln -s' command failed, then we probably don't even
+ # have an lstat function.
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; }
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+ case " $LIBOBJS " in
+ *" lstat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS lstat.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
+echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; }
+if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ return stat ("", &sbuf) == 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_stat_empty_string_bug=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_stat_empty_string_bug=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; }
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+ case " $LIBOBJS " in
+ *" stat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS stat.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+{ echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; }
+if test "${ac_cv_func__doprnt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub__doprnt || defined __stub____doprnt
+choke me
+#endif
+
+int
+main ()
+{
+return _doprnt ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func__doprnt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func__doprnt=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6; }
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+{ echo "$as_me:$LINENO: checking for wait3 that fills in rusage" >&5
+echo $ECHO_N "checking for wait3 that fills in rusage... $ECHO_C" >&6; }
+if test "${ac_cv_func_wait3_rusage+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_wait3_rusage=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+/* HP-UX has wait3 but does not fill in rusage at all. */
+int
+main ()
+{
+ struct rusage r;
+ int i;
+ /* Use a field that we can force nonzero --
+ voluntary context switches.
+ For systems like NeXT and OSF/1 that don't set it,
+ also use the system CPU time. And page faults (I/O) for Linux. */
+ r.ru_nvcsw = 0;
+ r.ru_stime.tv_sec = 0;
+ r.ru_stime.tv_usec = 0;
+ r.ru_majflt = r.ru_minflt = 0;
+ switch (fork ())
+ {
+ case 0: /* Child. */
+ sleep(1); /* Give up the CPU. */
+ _exit(0);
+ break;
+ case -1: /* What can we do? */
+ _exit(0);
+ break;
+ default: /* Parent. */
+ wait3(&i, 0, &r);
+ /* Avoid "text file busy" from rm on fast HP-UX machines. */
+ sleep(2);
+ return (r.ru_nvcsw == 0 && r.ru_majflt == 0 && r.ru_minflt == 0
+ && r.ru_stime.tv_sec == 0 && r.ru_stime.tv_usec == 0);
+ }
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_wait3_rusage=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_wait3_rusage=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_wait3_rusage" >&5
+echo "${ECHO_T}$ac_cv_func_wait3_rusage" >&6; }
+if test $ac_cv_func_wait3_rusage = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WAIT3 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in setsid alarm gethostbyname gethostname gettimeofday memset regcomp select socket strcasecmp strchr strerror strndup strnlen strrchr strstr strtol strtoul uname
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+# Large file support
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval=$enable_largefile; case "${enableval}" in
+ yes) enable_largefile="yes" ;;
+ no) enable_largefile="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-largefile" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-largefile" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_largefile="yes"
+
+fi
+
+if test "$enable_largefile" = "no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NOLARGEFILE 1
+_ACEOF
+
+fi
+
+# SQL support
+# Check whether --enable-mysql was given.
+if test "${enable_mysql+set}" = set; then
+ enableval=$enable_mysql; case "${enableval}" in
+ yes) enable_mysql="yes" ;;
+ no) enable_mysql="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-mysql" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-mysql" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_mysql=no
+
+fi
+
+if test "x$enable_mysql" != "xno"; then
+
+for ac_header in mysql/mysql.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+#TODO: re-enable
+# AC_CHECK_LIB(
+# [mysqlclient],
+# [mysql_init],
+# [
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_DB 1
+_ACEOF
+
+ mysql_includes=`mysql_config --cflags`
+ mysql_libs=`mysql_config --libs`
+# ],
+# [AC_MSG_FAILURE([MySQL is missing])],
+# [-lmysqlclient]
+# )
+
+else
+ { { echo "$as_me:$LINENO: error: MySQL is missing
+See \`config.log' for more details." >&5
+echo "$as_me: error: MySQL is missing
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+
+done
+
+
+fi
+
+ if test x$enable_mysql = xyes; then
+ enable_mysql_TRUE=
+ enable_mysql_FALSE='#'
+else
+ enable_mysql_TRUE='#'
+ enable_mysql_FALSE=
+fi
+
+
+
+
+# Regular expressions
+# Check whether --enable-regexp was given.
+if test "${enable_regexp+set}" = set; then
+ enableval=$enable_regexp; case "${enableval}" in
+ yes) enable_regexp="yes" ;;
+ no) enable_regexp="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-regexp" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-regexp" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_regexp=yes
+
+fi
+
+if test "$enable_regexp" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FEATURE_REGEXP 1
+_ACEOF
+
+fi
+
+# zlib compression
+# Check whether --enable-zlib was given.
+if test "${enable_zlib+set}" = set; then
+ enableval=$enable_zlib; case "${enableval}" in
+ yes) enable_zlib="yes" ;;
+ no) enable_zlib="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-zlib" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-zlib" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_zlib=yes
+
+fi
+
+if test "$enable_zlib" = "yes"; then
+ if test "${ac_cv_header_zlib_h+set}" = set; then
+ { echo "$as_me:$LINENO: checking for zlib.h" >&5
+echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking zlib.h usability" >&5
+echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <zlib.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking zlib.h presence" >&5
+echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <zlib.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for zlib.h" >&5
+echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_zlib_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; }
+
+fi
+if test $ac_cv_header_zlib_h = yes; then
+ zlib_header="yes"
+else
+ zlib_header="no" enable_zlib="false"
+fi
+
+
+ if test "$zlib_header" = "yes"; then
+ { echo "$as_me:$LINENO: checking for deflate in -lz" >&5
+echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6; }
+if test "${ac_cv_lib_z_deflate+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char deflate ();
+int
+main ()
+{
+return deflate ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_z_deflate=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_z_deflate=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_deflate" >&5
+echo "${ECHO_T}$ac_cv_lib_z_deflate" >&6; }
+if test $ac_cv_lib_z_deflate = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_NETZIP 1
+_ACEOF
+
+ zlib_libs="-lz"
+
+else
+ enable_zlib="false"
+fi
+
+ fi
+fi
+
+# multithreading via pthreads
+# Check whether --enable-pthreads was given.
+if test "${enable_pthreads+set}" = set; then
+ enableval=$enable_pthreads; case "${enableval}" in
+ yes) enable_pthreads="yes" ;;
+ no) enable_pthreads="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-pthreads" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-pthreads" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_pthreads=yes
+
+fi
+
+if test "x$enable_pthreads" != "xno"; then
+
+for ac_header in pthread.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ----------------------------------------- ##
+## Report this to rsyslog@lists.adiscon.com. ##
+## ----------------------------------------- ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5
+echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread -lpthread
+ $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6; }
+if test $ac_cv_lib_pthread_pthread_create = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_PTHREADS 1
+_ACEOF
+
+ pthreads_libs="-lpthread"
+
+
+else
+ { { echo "$as_me:$LINENO: error: pthread is missing
+See \`config.log' for more details." >&5
+echo "$as_me: error: pthread is missing
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+else
+ { { echo "$as_me:$LINENO: error: pthread is missing
+See \`config.log' for more details." >&5
+echo "$as_me: error: pthread is missing
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+
+done
+
+
+fi
+
+
+# klogd
+# Check whether --enable-klogd was given.
+if test "${enable_klogd+set}" = set; then
+ enableval=$enable_klogd; case "${enableval}" in
+ yes) enable_klogd="yes" ;;
+ no) enable_klogd="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-klogd" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-klogd" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_klogd="yes"
+
+fi
+
+if test "$enable_klogd" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FEATURE_KLOGD 1
+_ACEOF
+
+fi
+
+#
+# SYSLOG_UNIXAF
+#
+{ echo "$as_me:$LINENO: checking for SYSLOG_UNIXAF support" >&5
+echo $ECHO_N "checking for SYSLOG_UNIXAF support... $ECHO_C" >&6; }
+# Check whether --enable-unix was given.
+if test "${enable_unix+set}" = set; then
+ enableval=$enable_unix;
+ if test "x${enableval}" = "xyes"; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define SYSLOG_UNIXAF 1
+_ACEOF
+
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+
+else
+
+ # enabled by default
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define SYSLOG_UNIXAF 1
+_ACEOF
+
+
+fi
+
+
+# inet
+# Check whether --enable-inet was given.
+if test "${enable_inet+set}" = set; then
+ enableval=$enable_inet; case "${enableval}" in
+ yes) enable_inet="yes" ;;
+ no) enable_inet="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-inet" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-inet" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_inet="yes"
+
+fi
+
+if test "$enable_inet" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define SYSLOG_INET 1
+_ACEOF
+
+fi
+
+#
+# The following define determines whether the package adheres to the
+# file system standard.
+#
+{ echo "$as_me:$LINENO: checking for FSSTND support" >&5
+echo $ECHO_N "checking for FSSTND support... $ECHO_C" >&6; }
+# Check whether --enable-fsstnd was given.
+if test "${enable_fsstnd+set}" = set; then
+ enableval=$enable_fsstnd;
+ if test "x${enableval}" = "xyes"; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define FSSTND 1
+_ACEOF
+
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+
+else
+
+ # enabled by default
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define FSSTND 1
+_ACEOF
+
+
+fi
+
+
+# debug
+# Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval=$enable_debug; case "${enableval}" in
+ yes) enable_debug="yes" ;;
+ no) enable_debug="no" ;;
+ *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-debug" >&5
+echo "$as_me: error: bad value ${enableval} for --enable-debug" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+else
+ enable_debug="no"
+
+fi
+
+if test "$enable_debug" = "no"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define NDEBUG 1
+_ACEOF
+
+fi
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${enable_mysql_TRUE}" && test -z "${enable_mysql_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"enable_mysql\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"enable_mysql\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by rsyslog $as_me 1.18.2, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+rsyslog config.status 1.18.2
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+enable_mysql_TRUE!$enable_mysql_TRUE$ac_delim
+enable_mysql_FALSE!$enable_mysql_FALSE$ac_delim
+mysql_includes!$mysql_includes$ac_delim
+mysql_libs!$mysql_libs$ac_delim
+zlib_libs!$zlib_libs$ac_delim
+pthreads_libs!$pthreads_libs$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 94; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $ac_file | $ac_file:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $ac_file" >`$as_dirname -- $ac_file ||
+$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X$ac_file : 'X\(//\)[^/]' \| \
+ X$ac_file : 'X\(//\)$' \| \
+ X$ac_file : 'X\(/\)' \| . 2>/dev/null ||
+echo X$ac_file |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+echo "****************************************************"
+echo "rsyslog will be compiled with the followig settings:"
+echo
+echo "Multithreading support enabled: $enable_pthreads"
+echo "Klogd functionality enabled: $enable_klogd"
+echo "Regular expressions support enabled: $enable_regexp"
+echo "Zlib compression support enabled: $enable_zlib"
+echo "MySql support enabled: $enable_mysql"
+echo "Large file support enabled: $enable_largefile"
+echo "Networking support enabled: $enable_inet"
+echo "Debug mode enabled: $enable_debug"
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..c613d5e
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,280 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.61)
+AC_INIT([rsyslog],[1.18.2],[rsyslog@lists.adiscon.com.])
+AM_INIT_AUTOMAKE(rsyslog, 1.18.2)
+AC_CONFIG_SRCDIR([syslogd.c])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+if test "$GCC" = "yes"
+then CFLAGS="$CFLAGS -W -Wall -Wformat-security -Wshadow -Wcast-align -Wpointer-arith -Wmissing-format-attribute -g"
+fi
+AC_CANONICAL_HOST
+
+case "${host}" in
+ *-*-linux*)
+ # This feature indicates if klogd functionality
+ # should be integrated. If it is switched off, klogd
+ # is still compiled, but it is an empty shell.
+ AC_DEFINE([FEATURE_KLOGD], [1], [Description])
+ ;;
+ *-*-*darwin*|*-*-freebsd*|*-*-netbsd*|*-*-openbsd*)
+ AC_DEFINE([BSD], [1], [Description])
+ ;;
+esac
+
+# Checks for libraries.
+AC_CHECK_LIB(rt,clock_gettime,,,)
+
+# Checks for header files.
+AC_HEADER_RESOLV
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h locale.h netdb.h netinet/in.h paths.h stdio_ext.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+AC_C_VOLATILE
+
+sa_includes="\
+$ac_includes_default
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+"
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[$sa_includes])
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_FUNC_VPRINTF
+AC_FUNC_WAIT3
+AC_CHECK_FUNCS([setsid alarm gethostbyname gethostname gettimeofday memset regcomp select socket strcasecmp strchr strerror strndup strnlen strrchr strstr strtol strtoul uname])
+
+
+# Large file support
+AC_ARG_ENABLE(largefile,
+ [AS_HELP_STRING([--enable-largefile],[Enable large file support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_largefile="yes" ;;
+ no) enable_largefile="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-largefile) ;;
+ esac],
+ [enable_largefile="yes"]
+)
+if test "$enable_largefile" = "no"; then
+ AC_DEFINE(NOLARGEFILE, 1, [Defined when large file support is disabled.])
+fi
+
+# SQL support
+AC_ARG_ENABLE(mysql,
+ [AS_HELP_STRING([--enable-mysql],[Enable MySql database support @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_mysql="yes" ;;
+ no) enable_mysql="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-mysql) ;;
+ esac],
+ [enable_mysql=no]
+)
+AS_IF([test "x$enable_mysql" != "xno"],
+ [AC_CHECK_HEADERS(
+ [mysql/mysql.h],
+ [
+#TODO: re-enable
+# AC_CHECK_LIB(
+# [mysqlclient],
+# [mysql_init],
+# [
+ AC_DEFINE([WITH_DB], [1], [MySql database support enabled])
+ mysql_includes=`mysql_config --cflags`
+ mysql_libs=`mysql_config --libs`
+# ],
+# [AC_MSG_FAILURE([MySQL is missing])],
+# [-lmysqlclient]
+# )
+ ],
+ [AC_MSG_FAILURE([MySQL is missing])]
+ )]
+)
+AM_CONDITIONAL(enable_mysql, test x$enable_mysql = xyes)
+AC_SUBST(mysql_includes)
+AC_SUBST(mysql_libs)
+
+# Regular expressions
+AC_ARG_ENABLE(regexp,
+ [AS_HELP_STRING([--enable-regexp],[Enable regular expressions support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_regexp="yes" ;;
+ no) enable_regexp="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-regexp) ;;
+ esac],
+ [enable_regexp=yes]
+)
+if test "$enable_regexp" = "yes"; then
+ AC_DEFINE(FEATURE_REGEXP, 1, [Regular expressions support enabled.])
+fi
+
+# zlib compression
+AC_ARG_ENABLE(zlib,
+ [AS_HELP_STRING([--enable-zlib],[Enable zlib compression support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_zlib="yes" ;;
+ no) enable_zlib="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-zlib) ;;
+ esac],
+ [enable_zlib=yes]
+)
+if test "$enable_zlib" = "yes"; then
+ AC_CHECK_HEADER(zlib.h, [zlib_header="yes"], [zlib_header="no" enable_zlib="false"])
+ if test "$zlib_header" = "yes"; then
+ AC_CHECK_LIB(z, deflate,
+ [AC_DEFINE(USE_NETZIP, 1, [Define if you want to enable zlib support])
+ zlib_libs="-lz"
+ AC_SUBST(zlib_libs)], enable_zlib="false")
+ fi
+fi
+
+# multithreading via pthreads
+AC_ARG_ENABLE(pthreads,
+ [AS_HELP_STRING([--enable-pthreads],[Enable multithreading via pthreads @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_pthreads="yes" ;;
+ no) enable_pthreads="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-pthreads) ;;
+ esac],
+ [enable_pthreads=yes]
+)
+AS_IF([test "x$enable_pthreads" != "xno"],
+ [AC_CHECK_HEADERS(
+ [pthread.h],
+ [
+ AC_CHECK_LIB(
+ [pthread],
+ [pthread_create],
+ [
+ AC_DEFINE([USE_PTHREADS], [1], [Multithreading support enabled.])
+ pthreads_libs="-lpthread"
+ AC_SUBST(pthreads_libs)
+ ],
+ [AC_MSG_FAILURE([pthread is missing])],
+ [-lpthread]
+ )
+ ],
+ [AC_MSG_FAILURE([pthread is missing])]
+ )]
+)
+
+# klogd
+AC_ARG_ENABLE(klogd,
+ [AS_HELP_STRING([--enable-klogd],[Integrated klogd functionality @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_klogd="yes" ;;
+ no) enable_klogd="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-klogd) ;;
+ esac],
+ [enable_klogd="yes"]
+)
+if test "$enable_klogd" = "yes"; then
+ AC_DEFINE(FEATURE_KLOGD, 1, [klogd functionality is integrated.])
+fi
+
+#
+# SYSLOG_UNIXAF
+#
+AC_MSG_CHECKING(for SYSLOG_UNIXAF support)
+AC_ARG_ENABLE([unix],
+ [AS_HELP_STRING([--disable-unix], [disable support for unix])],
+ [
+ if test "x${enableval}" = "xyes"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([SYSLOG_UNIXAF], [1], [Description])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ],
+ [
+ # enabled by default
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([SYSLOG_UNIXAF], [1], [Description])
+ ])
+
+# inet
+AC_ARG_ENABLE(inet,
+ [AS_HELP_STRING([--enable-inet],[Enable networking support @<:@default=yes@:>@])],
+ [case "${enableval}" in
+ yes) enable_inet="yes" ;;
+ no) enable_inet="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-inet) ;;
+ esac],
+ [enable_inet="yes"]
+)
+if test "$enable_inet" = "yes"; then
+ AC_DEFINE(SYSLOG_INET, 1, [network support is integrated.])
+fi
+
+#
+# The following define determines whether the package adheres to the
+# file system standard.
+#
+AC_MSG_CHECKING(for FSSTND support)
+AC_ARG_ENABLE([fsstnd],
+ [AS_HELP_STRING([--disable-fsstnd], [disable support for FSSTND])],
+ [
+ if test "x${enableval}" = "xyes"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([FSSTND], [1], [Description])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ],
+ [
+ # enabled by default
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([FSSTND], [1], [Description])
+ ])
+
+# debug
+AC_ARG_ENABLE(debug,
+ [AS_HELP_STRING([--enable-debug],[Enable debug mode @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_debug="yes" ;;
+ no) enable_debug="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
+ esac],
+ [enable_debug="no"]
+)
+if test "$enable_debug" = "no"; then
+ AC_DEFINE(NDEBUG, 1, [Defined if debug mode is disabled.])
+fi
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
+
+echo "****************************************************"
+echo "rsyslog will be compiled with the followig settings:"
+echo
+echo "Multithreading support enabled: $enable_pthreads"
+echo "Klogd functionality enabled: $enable_klogd"
+echo "Regular expressions support enabled: $enable_regexp"
+echo "Zlib compression support enabled: $enable_zlib"
+echo "MySql support enabled: $enable_mysql"
+echo "Large file support enabled: $enable_largefile"
+echo "Networking support enabled: $enable_inet"
+echo "Debug mode enabled: $enable_debug"
+
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..d8ef3dd
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,12 @@
+This directory contains a number of possibly useful things that do not
+directly relate to rsyslog. They are not actively supported, but as
+I said often helpful. Use them with some care, as they may be outdated
+in respect to the current release of rsyslog.
+
+At least some of this stuff has been found by our users and been
+included after a brief check and possibly an adapation. If you have
+something useful you would like to see in contrib, just drop us a
+note (see http://www.rsyslog.com for how to do that at the time your
+are reading this document).
+
+rgerhards, 2007-08-08
diff --git a/contrib/delete_mysql b/contrib/delete_mysql
new file mode 100644
index 0000000..3ed84d1
--- /dev/null
+++ b/contrib/delete_mysql
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# Database maintance script which can be used for rsyslog
+# and phplogcon default database schema.
+# Michael Mansour suggested it to be included - thx!
+
+# This program was original part of of PHPloghost
+# Copyright (C) 2004 Tuatha de Dana
+# some modifications for rsyslog by mmeckelein at 2007-08-08
+# 2007-08-13 mmeckelein: added dbhost and some other improvements
+# suggested by Michael Mansour - thx a lot!
+
+# This program 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 2
+# of the License, or (at your option) any later version.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111- 1307, USA.
+
+# Change these variables to reflect your situation.
+database=sqlrsyslogd
+dbhost="localhost"
+export table=systemevents
+sqluser=""
+password=""
+
+# Location of the mysql daemon:
+mysqld=/usr/bin/mysql
+
+# A couple of steps should be taken to maintain your database.
+# If not, the number of messages will fill your database.
+# By default, logs are deleted after they're 30 days old.
+# Change this to meet your requirements.
+# rsyslog's default database template use two date columns
+# ReceivedAt and DeviceReportedTime. You can use either of
+# the two and in most cases it doesn't make a huge difference.
+# See the property replacer doc at http://www.rsyslog.com/doc
+# for details on the two dates.
+SQL_DELETE="DELETE FROM $table WHERE ReceivedAt < CURDATE() - INTERVAL 30 DAY;"
+
+# After a large amount of rows have been deleted, we should # optimize the table.
+SQL_OPT="OPTIMIZE TABLE $table;";
+
+$mysqld -u$sqluser -p$password -h$dbhost -e"$SQL_DELETE" -D$database
+$mysqld -u$sqluser -p$password -h$dbhost -e"$SQL_OPT" -D$database
diff --git a/createDB.sql b/createDB.sql
new file mode 100644
index 0000000..211cfb0
--- /dev/null
+++ b/createDB.sql
@@ -0,0 +1,37 @@
+CREATE DATABASE Syslog;
+USE Syslog;
+CREATE TABLE SystemEvents
+(
+ ID int unsigned not null auto_increment primary key,
+ CustomerID bigint,
+ ReceivedAt datetime NULL,
+ DeviceReportedTime datetime NULL,
+ Facility smallint NULL,
+ Priority smallint NULL,
+ FromHost varchar(60) NULL,
+ Message text,
+ NTSeverity int NULL,
+ Importance int NULL,
+ EventSource varchar(60),
+ EventUser varchar(60) NULL,
+ EventCategory int NULL,
+ EventID int NULL,
+ EventBinaryData text NULL,
+ MaxAvailable int NULL,
+ CurrUsage int NULL,
+ MinUsage int NULL,
+ MaxUsage int NULL,
+ InfoUnitID int NULL ,
+ SysLogTag varchar(60),
+ EventLogType varchar(60),
+ GenericFileName VarChar(60),
+ SystemID int NULL
+);
+
+CREATE TABLE SystemEventsProperties
+(
+ ID int unsigned not null auto_increment primary key,
+ SystemEventID int NULL ,
+ ParamName varchar(255) NULL ,
+ ParamValue text NULL
+);
diff --git a/depcomp b/depcomp
new file mode 100755
index 0000000..ca5ea4e
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,584 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2006-10-15.18
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software
+# Foundation, Inc.
+
+# This program 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 2, or (at your option)
+# any later version.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
+ tmpdepfile="$stripped.u"
+ if test "$libtool" = yes; then
+ "$@" -Wc,-M
+ else
+ "$@" -M
+ fi
+ stat=$?
+
+ if test -f "$tmpdepfile"; then :
+ else
+ stripped=`echo "$stripped" | sed 's,^.*/,,'`
+ tmpdepfile="$stripped.u"
+ fi
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+
+ if test -f "$tmpdepfile"; then
+ outname="$stripped.o"
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
+ sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/doc/bugs.html b/doc/bugs.html
new file mode 100644
index 0000000..5510b76
--- /dev/null
+++ b/doc/bugs.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>rsyslog bugs and annoyances</title>
+</head>
+<body>
+<h1>rsyslog bugs and annoyances</h1>
+<p><b>This page lists the known bugs rsyslog has to offer.</b> Please note that
+we also have a
+<a href="http://sourceforge.net/tracker/?atid=696552&group_id=123448&func=browse">
+bug tracker at sourceforge.net</a>. This list here contains more architectural
+things while the bug tracker most often lists things that you will actually
+experience. Please be sure to visit the bug tracker in addition to this list
+here.</p>
+<p>This list has last been updated on 2007-07-30 by
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>.</p>
+<h1>rsyslogd</h1>
+<h2>forwarding remotely received messages</h2>
+<p>Sysklogd does not forward remotely received messages to other network
+destionation except when the -h option is given. This code is currently defunct.
+No matter if -h is specified or not, messages are ALWAYS forwarded. It is
+currently under review if the sysklogd's functionality is actually needed.
+Please see my
+<a href="http://rgerhards.blogspot.com/2007/07/on-syslogd-h-option.html">blog
+post on this topic</a> for futher detail.</p>
+<h2>EQUALLY-NAMED TEMPLATES</h2>
+<p>If multiple templates with the SAME name are created, all but the
+ first definition is IGNORED. So you can NOT (yet) replace a
+ template definition. I also strongly doubt I will ever support this, because
+it does not make an awful lot of sense (after all, why not use two template
+names...).</p>
+<h2>WALLMSG FORMAT (* selector)
+ </h2>
+<p>This format is actually not 100% compatible with stock syslogd - the
+ date is missing. Will be fixed soon and can also be fixed just via
+ the proper template. Anyone up for this? ;)</p>
+<h2>SIGPIPE HANDLING</h2>
+<p>Currently, SIGPIPE is ignored. This is necessary to handle broken TCP
+ connections. We should further look into this issue and see which other
+ ways exist to handle the situation.</p>
+<h2>MULTIPLE INSTANCES</h2>
+<p>If multiple instances are running on a single machine, the one with
+ the -r switch must start first. Also, UDP-based syslog forwarding between the
+instances does not work. Use TCP instead.</p>
+
+</body>
+</html>
diff --git a/doc/contributors.html b/doc/contributors.html
new file mode 100644
index 0000000..ebbf1a5
--- /dev/null
+++ b/doc/contributors.html
@@ -0,0 +1,60 @@
+<html>
+<head>
+<title>Contributor Hall of Fame</title>
+</head>
+<body>
+<h2>Contributor Hall of Fame</h2>
+<p><b>This page is dedicated to all the people who helped make
+<a href="http://www.rsyslog.com/">rsyslog</a> become a reality.</b>
+Unfortunately, I have begun this page in July of 2007, long after the project
+started. I try to extract all past contributor information from CVS, readme's,
+code etc - but I may fail. If you contributed and do not find yourself listed
+below, please accept my sincere apologies and drop me a line.</p>
+<p>Please also note that I will do the checks for past contibutors once the
+current very busy development phase is over, so it may take a few weeks to fully
+populate this file.</p>
+<p>Contributors are listed in alphabetical order. If I know an Alias only, that
+alias is used as heading. Else the real name is used. If I know first and last
+name, they are listed in that order (&quot;Rainer Gerhards&quot; and not &quot;Gerhards,
+Rainer&quot;). I tend to be sparse with information on contributors, at least without
+their permission. If you contribute, let me know if I may include your email
+and/or web page address.</p>
+<p>Thanks to all past, present and future contributors!</p>
+<p><a href="http://www.gerhards.net/rainer">Rainer Gerhards</a><br>
+Project Initiator and Maintainer</p>
+<h2>Bartosz Kuzma</h2>
+<ul>
+ <li>provided many contributions before I started this list, so there are
+ probably some missing</li>
+ <li>suggested the use of autotools in parallel to Peter Vrabec and helped me
+ get it going</li>
+ <li>sent a number of patches (see cvs log for details)</li>
+</ul>
+<h2>Michel Samia</h2>
+<ul>
+ <li>provided patch with regex functionality for filters on 2007-07-14, first
+ seen in 1.16.1</li>
+</ul>
+<h2>mildew@gmail.com</h2>
+<ul>
+ <li>provided a large patch to enhance $AllowedSender directive for IPv6 as
+ well as DNS names</li>
+</ul>
+<h2>Peter Vrabec</h2>
+<ul>
+ <li>provided many contributions before I started this list, so there are
+ probably some missing</li>
+ <li>provided basic IPv6 support</li>
+ <li>convinced me to use autotools and provided the first working config for
+ it</li>
+ <li>provided Rainer with ongoing support, inspiration and motivation</li>
+</ul>
+<h2>varmojfekoj@gmail.com</h2>
+<ul>
+ <li>provided contributions before I started this list, so there are probably
+ some missing</li>
+ <li>provided patches for several memory leaks</li>
+</ul>
+<p><font size="2">Last Updated: 2007-07-19</font></p>
+</body>
+</html>
diff --git a/doc/features.html b/doc/features.html
new file mode 100644
index 0000000..725c3d7
--- /dev/null
+++ b/doc/features.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+<title>rsyslog features</title>
+</head>
+<body>
+<h1>RSyslog - Features</h1>
+<p><b>This page lists both current features as well as those being considered
+for future versions of rsyslog.</b> If you think a feature is missing, drop
+<a href="mailto:rgerhards@adiscon.com">Rainer</a> a note. Rsyslog is a vital
+project. Features are added each few days. If you would like to keep up of what
+is going on, you can also subscribe to the <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">rsyslog mailing list</a>.
+</p>
+<h2>Current Features</h2>
+<ul>
+
+ <li>native support for <a href="rsyslog_mysql.html">writing to MySQL databases</a><li>support for (plain) tcp
+ based syslog - much better reliability<li>support for sending and receiving
+ compressed syslog messages<li>ability to configure backup syslog/database
+ servers - if the primary fails, control is switched to a prioritized list of
+ backups<li>support for receiving messages via reliable <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php"> RFC 3195</a> delivery<li>ability to generate file names and directories (log targets)
+ dynamically, based on many different properties<li>control of log output format,
+ including ability to present channel and priority as visible log data<li>good timestamp format control; at a minimum, ISO 8601/RFC 3339
+ second-resolution UTC zone<li>ability to reformat message contents and work with substrings<li>support for
+ log files larger than 2gb<li>support for file size limitation and automatic
+ rollover command execution<li>support for running multiple rsyslogd
+ instances on a single machine<li>support for <a href="rsyslog_stunnel.html">
+ ssl-protected syslog</a> (via stunnel)<li>ability to filter on any part of
+ the message, not just facility and severity<li>ability to use regular
+ expressions in filters<li>support for discarding
+ messages based on filters<li>ability to execute shell scripts on received
+ messages<li>control of whether the local hostname or the hostname of the
+ origin of the data is shown as the hostname in the output<li>ability to
+ preserve the original hostname in NAT environments and relay chains
+ <li>ability to limit the allowed network senders<li>powerful BSD-style hostname and program name blocks for easy multi-host support<li> multi-threaded (<a href="http://rgerhards.blogspot.com/2007/08/why-is-rsyslog-multi-threaded-and-is-it.html">is
+ this important? why?</a>)<li>very experimental and volatile support for <a href="syslog-protocol.html">syslog-protocol</a> compliant messages (it is volatile because standardization is currently underway and this is a proof-of-concept implementation to aid this effort)<li>
+ experimental support for syslog-transport-tls based framing on syslog/tcp
+ connections<li>
+ a copy of klogd.c has been included under the name of rklogd for those Linux
+ systems that need one. So rsyslog is a full replacement for the sysklogd
+ package<li>
+ support for IPv6<li>
+ ability to control repeated line reduction (&quot;last message repeated n times&quot;)
+ on a per selector-line basis<li>
+ supports sub-configuration files, which can be automatically read from
+ directories. Includes are specified in the main configuration file<li>
+ supports multiple actions per selector/filter condition</ul>
+<p>&nbsp;</p>
+<h2>Upcoming Features</h2>
+<p>The list below is something like a repository of ideas we'd like to
+implement. Features on this list are typically NOT scheduled for immediate
+inclusion. We maintain a
+<a href="http://sourceforge.net/tracker/?group_id=123448&atid=696555">feature
+request tracker at sourceforge.net</a>. This tracker has things typically within
+reach of implementation. Users are encouraged to submit feature requests there
+(or via our forums). If we like them but they look quite long-lived (aka &quot;not
+soon to be implemented&quot;), they will possibly be migrated to this list here and
+at some time moved back to the sourceforge tracker.</p>
+<ul>
+ <li>create a plug-in-interface - we are very close to this. A neat interface is
+ already used internally for output modules.<li>implement native email-functionality in
+ selector (probably best done as a plug-in)<li>port it to more *nix variants
+ (eg AIX and HP UX) - this needs volunteers with access to those machines and
+ knowledge<li>provide an on-disk queue for syslog messages; should be
+ combined with reliable delivery to the next hop<li>support for native SSL enryption of plain tcp syslog sessions. This will
+ most probably happen based on syslog-transport-tls.<li>even more enhanced multi-threading,
+ with a message queue for each action (when implementing this, search
+ for CHECKMULTIQUEUE comments in the source - they already contain hints of
+ what to look at). Some detail information on this can already be found in
+ <a href="http://rgerhards.blogspot.com/2007/08/syslog-worker-pools-future-hardware-and.html">
+ Rainer's blog</a>.<li>pcre filtering - maybe (depending on feedback)&nbsp; - simple regex already
+ partly added. So far, this seems sufficient so that there is no urgent need
+ to do pcre<li>support for <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC 3195</a> as a sender - this is currently unlikely to happen, because there is no real
+ demand for it. Any work on RFC 3195 has been suspend until we see some real
+ interest in it.&nbsp; It is probably much better to use TCP-based syslog,
+ which is interoprable with a large number of applications.</ul>
+<p>To see when each feature was added, see the
+<a href="http://www.rsyslog.com/Topic4.phtml">rsyslog change log</a> (online
+only).</p>
+</body>
+</html>
diff --git a/doc/generic_design.html b/doc/generic_design.html
new file mode 100644
index 0000000..03a55fa
--- /dev/null
+++ b/doc/generic_design.html
@@ -0,0 +1,149 @@
+<html>
+<head>
+<title>syslogd generic design</title>
+</head>
+<body>
+<h2>Generic design of a syslogd</h2>
+<p>Written 2007-04-10 by
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a></p>
+<p>The text below describes a generic approach on how a syslogd can be
+implemented. I created this description for some other project, where it was not
+used. Instead of throwing it away, I thought it would be a good addition to the
+rsyslog documentation. While rsyslog differs in details from the description
+below, it is sufficiently close to it. Further development of rsyslog will
+probably match it even closer to the description.</p>
+<p>If you intend to read the rsyslog source code, I recommend reading this
+document here first. You will not find the same names and not all of the
+concepts inside rsyslog. However, I think your understanding will benefit from
+knowing the generic architecture.</p>
+<font size="3"><pre>
+
+ +-----------------+
+ | "remote" PLOrig |
+ +-----------------+
+ |
+ I +--------+-----+-----+ +-----+-------+------+-----+
+ P | PLOrig | GWI | ... | | GWO | Store | Disc | ... |
+ C +--------+-----+-----+ +-----+-------+------+-----+
+ | | ^
+ v v |
+ +--------------+ +------------+ +--------------+
+ | PLGenerator | | RelayEng | | CollectorEng |
+ +--------------+ +------------+ +--------------+
+ | ^ ^
+ | | |
+ v v |
+ +-------------+ +------------+ +--------------+
+ | PLG Ext | | RelEng Ext | | CollcEng Ext |
+ +-------------+ +------------+ +--------------+
+ | ^ ^
+ | | |
+ v v |
+ +--------------------------------------------------------------+
+ | Message Router |
+ +--------------------------------------------------------------+
+ | ^
+ v |
+ +--------------------------------------------------------------+
+ | Message CoDec (e.g. RFC 3164, RFCYYYY) |
+ +--------------------------------------------------------------+
+ | ^
+ v |
+ +---------------------+-----------------------+----------------+
+ | transport UDP | transport TLS | ... |
+ +---------------------+-----------------------+----------------+
+
+ Generic Syslog Application Architecture
+</pre></font>
+<ul>
+ <li>A &quot;syslog application&quot; is an application whos purpose is the
+processing of syslog messages. It may be part of a larger
+application with a broader purpose. An example: a database
+application might come with its own syslog send subsystem and not
+go through a central syslog application. In the sense of this
+document, that application is called a &quot;syslog application&quot; even
+though a casual observer might correctly call it a database
+application and may not even know that it supports sending of
+syslog messages.</li>
+ <li>Payload is the information that is to be conveyed. Payload by
+itself may have any format and is totally independent from to
+format specified in this document. The &quot;Message CoDec&quot; of the
+syslog application will bring it into the required format.</li>
+ <li>Payload Orginators (&quot;PLOrig&quot;) are the orginal creators of payload.
+Typically, these are application programs.</li>
+ <li>A &quot;Remote PLOrig&quot; is a payload originator residing in a different
+application than the syslog application itself. That application
+may reside on a different machine and may talk to the syslog
+application via RPC.</li>
+ <li>A &quot;PLOrig&quot; is a payload originator residing within the syslog
+application itself. Typically, this PLOrig emits syslog
+application startup, shutdown, error and status log messages.</li>
+ <li>A &quot;GWI&quot; is a inbound gateway. For example, a SNMP-to-syslog
+gateway may receive SNMP messages and translate them into syslog.</li>
+ <li>The ellipsis after &quot;GWI&quot; indicates that there are potentially a
+variety of different other ways to originally generate payload.</li>
+ <li>A &quot;PLGenerator&quot; is a payload generator. It takes the information
+from the payload-generating source and integrates it into the
+syslog subsystem of the application. This is a highly theoretical
+concept. In practice, there may not actually be any such
+component. Instead, the payload generators (or other parts like
+the GWI) may talk directly to the syslog subsystem. Conceptually,
+the &quot;PLGenerator&quot; is the first component where the information is
+actually syslog content.</li>
+ <li>A &quot;PLG Ext&quot; is a payload generator extension. It is used to
+modify the syslog information. An example of a &quot;PLG Ext&quot; might be
+the addition of cryptographic signatures to the syslog
+information.</li>
+ <li>A &quot;Message Router&quot; is a component that accepts in- and outbound
+syslog information and routes it to the proper next destination
+inside the syslog application. The routing information itself is
+expected to be learnt by operator configuration.</li>
+ <li>A &quot;Message CoDec&quot; is the message encoder/decoder. The encoder
+takes syslog information and encodes them into the required format<br>for a syslog message. The decoder takes a syslog message and
+decodes it into syslog information. Codecs for multiple syslog
+formats may be present inside a single syslog application.</li>
+ <li>A transport (UDP, TLS, yet-to-be-defined ones) sends and receives
+syslog messages. Multiple transports may be used by a single<br>syslog application at the same time. A single transport instance
+may be used for both sending and receiving. Alternatively, a
+single instance might be used for sending and receiving
+exclusively. Multiple instances may be used for different
+listener ports and receivers.</li>
+ <li>A &quot;RelayEng&quot; is the relaying engine. It provides functionality
+necessary for receiving syslog information and sending it to
+another syslog application.</li>
+ <li>A &quot;RelEng Ext&quot; is an extension that processes syslog information
+as it enters or exits a RelayEng. An example of such a component
+might be a relay cryptographically signing received syslog
+messages. Such a function might be useful to guarantee authenticy
+starting from a given point inside a relay chain.</li>
+ <li>A &quot;CollectorEng&quot; is a collector engine. At this component, syslog
+information leaves the syslog system and is translated into some
+other form. After the CollectorEng, the information is no longer
+defined to be of native syslog type.</li>
+ <li>A &quot;CollcEng Ext&quot; is a collector engine extension. It modifies
+syslog information before it is passed on to the CollectorEng. An
+example for this might be the verification of cryptographically
+signed syslog message information. Please note that another
+implementation appraoch would be to do the verification outside of
+the syslog application or in a stage after &quot;CollectorEng&quot;.</li>
+ <li>A &quot;GWO&quot; is an outbound gateway. An example of this might be the
+forwarding of syslog information via SNMP or SMTP. Please note
+that when a GWO directly connects to a GWI on a different syslog
+application, no native exchange of syslog information takes place.
+Instead, the native protocol of these gateways (e.g. SNMP) is
+used. The syslog information is embedded inside that protocol.
+Depending on protocol and gatway implementation, some of the
+native syslog information might be lost.</li>
+ <li>A &quot;Store&quot; is any way to persistently store the extracted syslog
+information, e.g. to the file system or to a data base.</li>
+ <li>&quot;Disc&quot; means the discarding of messages. Operators often find it
+useful to discard noise messages and so most syslog applications<br>contain a way to do that.</li>
+ <li>The ellipsis after &quot;Disc&quot; indicates that there are potentially avariety of different other ways to consume syslog information.</li>
+ <li>There may be multiple instances of each of the described
+components in a single syslog application.</li>
+ <li>A syslog application is made up of all or some of the above
+mentioned components.</li>
+</ul>
+</p>
+</body>
+</html>
diff --git a/doc/history.html b/doc/history.html
new file mode 100644
index 0000000..48a6489
--- /dev/null
+++ b/doc/history.html
@@ -0,0 +1,94 @@
+<html>
+<head>
+<title>rsyslog history</title>
+</head>
+<body>
+<h1>RSyslog - History</h1>
+
+<b>Rsyslog is a GPL-ed, enhanced syslogd. Among others, it offers support for
+reliable syslog over TCP, writing to
+MySQL databases and fully configurable output formats (including great timestamps).</b>
+Rsyslog was initiated by <a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>.
+If you are interested to learn why&nbsp; Rainer initiated&nbsp; the project, you
+may want to read his blog posting on &quot;<a href="http://rgerhards.blogspot.com/2007/08/why-does-world-need-another-syslogd.html">why
+the world neeeds another syslogd</a>&quot;.<p>Rsyslog has
+been forked in <b>2004</b> from the <a href="http://www.infodrom.org/projects/sysklogd/">sysklogd standard package</a>.
+The goal of the
+rsyslog project is to provide a feature-richer and reliable
+syslog deamon while retaining drop-in replacement capabilities to stock syslogd. By "reliable", we mean support for reliable transmission
+modes like TCP or <a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC 3195</a>
+(syslog-reliable). We do NOT imply that the sysklogd package is unreliable.</p>
+<p>The name "rsyslog" stems back to the
+planned support for syslog-reliable. Ironically, the initial release
+of rsyslog did NEITHER support syslog-reliable NOR tcp based syslog.
+Instead, it contained enhanced configurability and other enhancements
+(like database support). The reason for this is that full support for RFC 3195 would require even more changes and especially fundamental architectural
+changes. Also, questions asked on the loganalysis list and at other
+places indicated that RFC3195 is NOT a prime priority for users, but
+rather better control over the output format. So there we were, with
+a rsyslod that covers a lot of enhancements, but not a single one
+of these that made its name ;) Since version 0.9.2, receiving syslog messages
+via plain tcp is finally supported, a bit later sending via TCP, too. Starting
+with 1.11.0, RFC 3195 is finally support at the receiving side (a.k.a. &quot;listener&quot;).
+Support for sending via RFC 3195 is still due. Anyhow, rsyslog has come much
+closer to what it name promises.</p>
+<p>
+The database support was initially included so that our web-based syslog
+interface could be used. This is another open source project which can be found
+under <a href="http://www.phplogcon.org">http://www.phplogcon.org</a>. We highly recommend having a look at
+it. It might not work for you if you expect thousands of messages per
+second (because your database won't be able to provide adequate performance),
+but in many cases it is a very handy analysis and troubleshooting tool.
+
+In the mean time, of course, lots of people have found many applications for
+writing to databases, so the prime focus is no longer on phpLogcon.
+
+</p>
+<p>Rsyslogd supports an enhanced syslog.conf file format, and also works
+with the standard syslog.conf. In theory, it should be possible to simply replace
+the syslogd binary with the one that comes with rsyslog. Of course, in order
+to use any of the new features, you must re-write your syslog.conf. To learn
+how to do this, please review our commented <a href="sample.conf.php">sample.conf</a>
+file. It outlines the enhancements over stock syslogd. Discussion has often
+arisen of whether having an &quot;old syslogd&quot; logfile format is good or evil. So
+far, this has not been solved (but Rainer likes the idea of a new format), so we
+need to live with it for the time being. It is planned to be reconsidered in the
+3.x release time frame.
+<p>If you are interested in the <a href="http://en.wikipedia.org/wiki/IHE">IHE</a>
+environment, you might be interested to hear that rsyslog supports message with
+sizes of 32k and more. This feature has been tested, but by default is turned off
+(as it has some memory footprint that we didn't want to put on users not
+actually requiring it). Search the file syslogd.c and search for &quot;IHE&quot; - you
+will find easy and precise instructions on what you need to change (it's just
+one line of code!). Please note that RFC 3195/COOKED supports 1K message sizes
+only. It'll probably support longer messages in the future, but it is our
+believe that using larger messages with current RFC 3195 is a violation of the
+standard.<p>In <b>February 2007</b>, 1.13.1 was released and served for quite a
+while as a stable reference. Unfortunately, it was not later released as stable,
+so the stable build became quite outdated.<p>In <b>June 2007</b>, Peter Vrabec from Red Hat helped us to create
+RPM files for Fedora as well as supporting IPv6. There also seemed to be some
+interest from the Red Hat community. This interest and new ideas resulted in a
+very busy time with many great additions.<p>In <b>July 2007</b>, Andrew
+Pantyukhin added BSD ports files for rsyslog and liblogging. We were strongly
+encouraged by this too. It looks like rsyslog is getting more and more momentum.
+Let's see what comes next...<p>Also in <b>July 2007</b> (and beginning of
+August), Rainer remodled the output part of rsyslog. It got a clean object model
+and is now prepared for a plug-in architecture. During that time, some base
+ideas for the overall new object model appeared.<p>In <b>August 2007</b>
+community involvment grew more and more. Also, more packages appeared. We were
+quite happy about that. To facilitate user contributíons, we set up a
+<a href="http://wiki.rsyslog.com/">wiki</a> on August 10th, 2007. Also in August
+2007, rsyslog 1.18.2 appeared, which is deemed to be quite close to the final
+2.0.0 release. With its appearance, the pace of changes was deliberatly reduced,
+in order to allow it to mature (see Rainers's
+<a href="http://rgerhards.blogspot.com/2007/07/pace-of-changes-in-rsyslog.html">
+blog post</a> on this topic, written a bit early, but covering the essence).<p>Be sure to visit Rainer's <a href="http://rgerhards.blogspot.com/">syslog block</a>
+to get some more insight into the development and futures of rsyslog and syslog in general.
+Don't be shy to post to either the blog or the
+<a href="http://www.rsyslog.com/PNphpBB2.phtml">rsyslog forums</a>.</p>
+<h2>Some useful links</h2>
+<ul>
+ <li><a href="http://www.rsyslog.com/Topic4.phtml">the rsyslog change log</a></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/how2help.html b/doc/how2help.html
new file mode 100644
index 0000000..5c612e1
--- /dev/null
+++ b/doc/how2help.html
@@ -0,0 +1,59 @@
+<html>
+<head>
+<title>How you can Help</title>
+</head>
+<body>
+<h2>How you can Help</h2>
+<p><b>You like rsyslog and would like to lend us a helping hand?</b> This page
+tells you how easy it is to help a little bit. You can contribute to the project
+even with a single mouse click! If you could pick a single item from the
+whishlist, that would be awfully helpful!</p>
+<p>This is our whishlist:</p>
+<ul>
+ <li>let others know how great rsyslog is<ul>
+ <li>rate us at <a href="http://freshmeat.net/rate/52985/">freshmeat.net</a>
+ and <a href="http://www.icewalkers.com/vote.php?ID=2420">icewalkers.com</a></li>
+ <li>spread word about rsyslog in forums and newsgroups</li>
+ <li>place a link to <a href="http://www.rsyslog.com">www.rsyslog.com</a>
+ from your home page</li>
+ </ul>
+ </li>
+ <li>let us know about rsyslog - we are eager for feedback<ul>
+ <li>tell us what you like and what you not like - so that we can include
+ that into development</li>
+ <li>tell us what you use rsyslog for - esepcially if you have high
+ traffic volume or an otherwise &quot;uncommon&quot; deployment. We are looking for
+ case studies and experience how rsyslog performs in unusual scenarios.</li>
+ <li>allow us to post your thoughts and experiences as a &quot;user story&quot; on
+ the web site (so far, none are there ;))</li>
+ </ul>
+ </li>
+ <li>if you know how to create packages (rpm, deb, ...)<ul>
+ <li>we would very much appreciate your help with package creation. We know
+ that it is important to have good binary packages for a product to
+ spread widely. Yet, we do not have the knowledge to do it all ourselfs.
+ <a href="mailto:rgerhards@adiscon.com">Drop Rainer a note </a>if you
+ could help us out.</li>
+ </ul>
+ </li>
+ <li>if you have configured a device for sending syslog data, and that device
+ is not in our
+ <a href="http://www.monitorware.com/en/syslog-enabled-products/">syslog
+ configuration database</a>, you might want to tell us how to configure it.</li>
+ <li>if you are a corporate user<ul>
+ <li>you might consider <a href="http://www.adiscon.com">Adiscon</a>'s
+ commercial <a href="http://www.monitorware.com/">MonitorWare products</a>
+ for Windows, e.g. to deliver Windows Event Log data to rsyslogd (sales
+ of the commercial products funds the open source development - and they
+ also work very well).</li>
+ <li>you might be interested in
+ <a href="http://www.adiscon.com/Common/en/Products/techsup.php">
+ purchasing professional support or add-on development</a> for rsyslog</li>
+ </ul>
+ </li>
+</ul>
+<p><b>We appreciate your help very much.</b> A big thank you for anything you
+might do!</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/install.html b/doc/install.html
new file mode 100644
index 0000000..fb9e893
--- /dev/null
+++ b/doc/install.html
@@ -0,0 +1,156 @@
+<html><head>
+<title>SSL Encrypting syslog with stunnel</title>
+<meta name="KEYWORDS" content="syslog encryption, rsyslog, stunnel, secure syslog, tcp, reliable, howto, ssl">
+</head>
+<body>
+<h1>HOWTO install rsyslog</h1>
+ <P><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a></i></small></P>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to install
+<a href="http://www.rsyslog.com/">rsyslog</a>.</b> It is intentionally a brief
+step-by-step guide, targeted to those who want to quickly get it up and running.
+For more elaborate information, please consult the rest of the
+<a href="manual.html">manual set</a>.</i></p>
+<h2>How to make your life easier...</h2>
+<p>Some folks have thankfully created <a href="rsyslog_packages.html">
+RPMs/packages for rsyslog</a>. If you use them, you can spare yourself many of
+the steps below. This is highly recommended if there is a package for your
+distribution available.</p>
+<h2>Steps To Do</h2>
+<p>Rsyslog does currently only have very limited availability as a package (if
+you volunteer to create one, <a href="mailto:rgerhards@adiscon.com">drop me a
+line</a>). Thus, this guide focuses on installing from the source, which
+thankfully is <b>quite easy</b>.</p>
+<h3>Step 1 - Download Software</h3>
+<p>For obvious reasons, you need to download rsyslog. Load the most recent build
+from <a href="http://www.rsyslog.com/downloads">http://www.rsyslog.com/downloads</a>.
+Extract the software with &quot;tar xzf -nameOfDownloadSet-&quot;. This will create a new
+subdirectory rsyslog-version in the current working directory. CD into that. </p>
+<p>Depending on your system configuration, you also need to install some build
+tools, most importantly make, the gcc compiler and the MySQL development system
+(if you intend to use MySQL - the package is often named &quot;mysql-dev&quot;). On many systems, these things should already be
+present. If you don't know exactly, simply skip this step for now and see if
+nice error messages pop up during the compile process. If they do, you can still
+install the missing build environment tools. So this is nothing that you need to
+look at very carefully.</p>
+<h3>Step 2 - Run ./configure</h3>
+<p>Run ./configure to adopt rsyslog to your environment. While doing so, you can
+also enable options. Configure will display selected options when it is
+finished. For example, to enable MySQL support, run</p>
+<p>./configure --enable-mysql</p>
+<p>Please note that MySQL support by default is NOT disabled.</p>
+<h3>Step 3 - Compile</h3>
+<p>That is easy. Just type &quot;make&quot; and let the compiler work. On any recent
+system, that should be a very quick task, on many systems just a matter of a few
+seconds. If an error message comes up, most probably a part of your build
+environment is not installed. Check with step 1 in those cases. </p>
+<h3>Step 4 - Install</h3>
+<p>Again, that is quite easy. All it takes is a &quot;make install&quot;. That will copy
+the rsyslogd and the man pages to the relavant directories.</p>
+<h3>Step 5 - Configure rsyslogd</h3>
+<p>In this step, you tell rsyslogd what to do with received messages. If you are
+upgrading from stock syslogd, /etc/syslog.conf is probably a good starting
+point. Rsyslogd understands stock syslogd syntax, so you can simply copy over
+/etc/syslog.conf to /etc/rsyslog.conf. Then, edit rsyslog.conf for any
+enhancements you would like to see. For example, you can add database writing as
+outlined in the paper &quot;<a href="rsyslog_mysql.html">Writing syslog Data to MySQL</a>&quot;
+(remember you need to enable MySQL support during step 2 if you want to do
+that!).</p>
+<h3>Step 6 - Disable stock syslogd</h3>
+<p>In almost all cases, there already is stock syslogd installed. Because both
+it and rsyslogd listen to the same sockets, they can NOT be run concurrently. So
+you need to disable the stock syslogd. To do this, you typically must change
+your rc.d startup scripts.</p>
+<p>For example, under <a href="http://www.debian.org/">Debian</a> this must be
+done as follows: The default runlevel is 2. We modify the init scripts for
+runlevel 2 - in parctice, you need to do this for all run levels you will ever
+use (which probably means all). Under /etc/rc2.d there is a S10sysklogd script (actually
+a symlink). Change the name to _S10sysklogd (this keeps the symlink in place,
+but will prevent further execution - effectively disabling it).</p>
+<h3>Step 7 - Enable rsyslogd Autostart</h3>
+<p>This step is very close to step 3. Now, we want to enable rsyslogd to start
+automatically. The rsyslog package contains a (currently small) number of
+startup scripts. They are inside the distro-specific directory (e.g. debian). If
+there is nothing for your operating system, you can simply copy the stock
+syslogd startup script and make the minor modifications to run rsyslogd (the
+samples should be of help if you intend to do this).</p>
+<p>In our Debian example, the actual scripts are stored in /etc/init.d. Copy the
+standard script to that location. Then, you need to add a symlink to it in the
+respective rc.d directory. In our sample, we modify rc2.d, and can do this via
+the command &quot;ln -s ../init.d/rsyslogd S10rsyslogd&quot;. Please note that the S10
+prefix tells the system to start rsyslogd at the same time stock sysklogd was
+started.</p>
+<p><b>Important:</b> if you use the database functionality, you should make sure
+that MySQL starts before rsyslogd. If it starts later, you will receive an error
+message during each restart (this might be acceptable to you). To do so, either
+move MySQL's start order before rsyslogd or rsyslogd's after MySQL.</p>
+<h3>Step 8 - Check daily cron scripts</h3>
+<p>Most distributions come pre-configured with some daily scripts for log
+rotation. As long as you use the same log file names, the log rotation scripts
+will probably work quite well. There is one caveat, though. The scripts need to
+tell syslogd that the files have been rotated. To do this, they typically have a
+part using syslogd's init script to do that. Obviously, the default scripts do
+not know about rsyslogd, so they manipulate syslogd. If that happens, in most
+cases an additional instance of stock syslogd is started (in almost all cases,
+this was not functional, but it is at least distracting). It also means that
+rsyslogd is not properly told about the log rotation, which will lead it to
+continue to write to the now-rotated files.</p>
+<p>So you need to fix these scripts. See your distro-specific documentation how
+they are located. Under most Linuxes, the primary script to modify is /etc/cron.daily/sysklogd.
+Watch for a comment &quot;Restart syslogd&quot; (usually at the very end of the file). The
+restart command must be changed to use rsyslogd's rc script.</p>
+<p>Also, if you use klogd together with rsyslogd (under most Linuxes you will do
+that), you need to make sure that klogd is restarted after rsyslogd is restarted.
+So it might be a good idea to put a klogd reload-or-restart command right after
+the rsyslogd command in your daily script. This can save you lots of troubles.</p>
+<h3>Done</h3>
+<p>This concludes the steps neccesary to install rsyslogd. Of course, it is
+always a good idea to test everything thouroughly. At a minimalist level, you
+should do a reboot and after that check if everything has come up correctly. Pay
+attention not only to running processes, but also check if the log files (or the
+database) are correctly being populated.</p>
+<p>If rsyslogd encounters any serious errors during startup, you should be able
+to see them at least on the system console. They might not be in log file, as
+errors might occur before the log file rules are in place. So it is always a
+good idea to check system console output when things don't go smooth. In some
+rare cases, enabling debug logging (-d option) in rsyslogd can be helpful. If
+all fails, go to <a href="http://www.rsyslog.com">www.rsyslog.com</a> and check
+the forum or mailing list for help with your issue.</p>
+<h2>Housekeeping stuff</h2>
+<p>This section and its subsections contain all these nice things that you
+usually need to read only if you are really curios ;)</p>
+<h3>Feedback requested</h3>
+<P>I would appreciate feedback on this tutorial. It is still in its infancy, so additional ideas,
+comments or bug sighting reports are very welcome. Please
+<a href="mailto:rgerhards@adiscon.com">let me know</a> about them.</P>
+<h3>Revision History</h3>
+<ul>
+ <li>2005-08-08 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Initial
+ version created</li>
+ <li>2005-08-09 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * updated to include distro-specific directories, which are now mandatory</li>
+ <li>2005-09-06 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * added information on log rotation scripts</li>
+ <li>2007-07-13 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>&nbsp;
+ * updated to new autotools-based build system</li>
+</ul>
+<h3>Copyright</h3>
+<p>Copyright (c) 2005, 2007
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p> Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license can be viewed at
+<a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/ipv6.html b/doc/ipv6.html
new file mode 100644
index 0000000..f5a049c
--- /dev/null
+++ b/doc/ipv6.html
@@ -0,0 +1,48 @@
+<html>
+<head>
+<title>Notes on IPv6 Handling in Rsyslog</title>
+</head>
+<body>
+<h1>Notes on IPv6 Handling in Rsyslog</h1>
+<p><b>Rsyslog fully* supports sending and receiving syslog messages via both
+IPv4 and IPv6.</b> IPv6 is natively supported for both UDP and TCP. However,
+there are some options that control handling of IPv6 operations. I thought it is
+is a good idea to elaborate a little about them, so that you can probably find
+your way somewhat easier.</p>
+<p>First of all, you can restrict rsyslog to using IPv4 or IPv6 addresses only
+by specifying the -4 or -6 command line option (now guess which one does
+what...). If you do not provide any command line option, rsyslog uses IPv4 and
+IPv6 adresses concurrently. In practice, that means the listener binds to both
+addresses (provided they are configured). When sending syslog messages, rsyslog
+uses IPv4 addresses when the receiver can be reached via IPv4 and IPv6 addresses
+if it can be reached via IPv6. If it can be reached on either IPv4 and v6,
+rsyslog leaves the choice to the socket layer. The important point to know is
+that it uses whatever connectivity is available to reach the destination.</p>
+<p><b>There is one subtle difference between UDP and TCP.</b> With the new
+IPv4/v6 ignorant code, rsyslog has potentially different ways to reach
+destinations. The socket layer returns all of these pathes in a sorted array.
+For TCP, rsyslog loops through this array until a successful TCP connect can be
+made. If that happens, the other addresses are ignored and messages are sent via
+the succesfully-connected socket.</p>
+<p>For UDP, there is no such definite success indicator. Sure, the socket layer
+may detect some errors, but it may not notice other errors (due to the
+unreliable nature of UDP). By default, the UDP sender also tries one entry after
+the other in the sorted array of destination addresses. When a send fails, the
+next address is tried. When the send function finally succeeds, rsyslogd assumes
+the UDP packet has reached its final destination. However, if rsyslogd is
+started with the &quot;-A&quot; (capital A!) was given on the command line, rsyslogd will
+continue to send messages until the end of the destination address array is
+reached. This may result in duplicate messages, but it also provides some
+additional reliability in case a message could not be received. You need to be
+sure about the implications before applying this option. In general, it is NOT
+recommended to use the -A option.</p>
+<p><i><b>*</b>rsyslog does not support RFC 3195 over IPv6. The reason is that
+the RFC 3195 library, <a href="http://www.liblogging.org/">liblogging</a>,
+supports IPv4, only. Currently, there are no plans to update either rsyslog to
+another RFC 3195 stack or update liblogging. There is simply no demand for 3195
+solutions.</i></p>
+<p><font size="2">Last Updated: 2007-07-02<br>
+Copyright &copy; 2007 by Rainer Gerhards, released under the GNU GPL V2 or later.</font></p>
+
+</body>
+</html>
diff --git a/doc/manual.html b/doc/manual.html
new file mode 100644
index 0000000..3496c85
--- /dev/null
+++ b/doc/manual.html
@@ -0,0 +1,54 @@
+<html>
+<head>
+<title>rsyslog documentation</title>
+</head>
+<body>
+<h1>RSyslog - Documentation</h1>
+<p><b><a href="http://www.rsyslog.com/">Rsyslog</a> is an enhanced syslogd
+supporting, among others, <a href="rsyslog_mysql.html">MySQL</a>, <a href="http://wiki.rsyslog.com/index.php/FailoverSyslogServer">failover log destinations</a>, syslog/tcp,
+fine grain output format control, and the ability to filter on any message part.</b>
+It is quite compatible to stock
+sysklogd and can be used as a drop-in replacement. Its <a href="features.html">
+advanced features</a> make it suitable for enterprise-class,
+<a href="rsyslog_stunnel.html">encryption protected syslog</a>
+relay chains while at the same time being very easy to setup
+for the novice user.</p>
+<p><b>Visit the <i> <a href="status.html">rsyslog status page</a></i></b> to obtain current
+version information and ports. <b>If you like rsyslog, you might want to lend us
+a helping hand. </b>It doesn't require a lot of time - even a single mouse click
+helps. Learn <a href="how2help.html">how to help the rsyslog project</a>.</p>
+<p><b>Follow the links below for the</b></p>
+<ul>
+<li><a href="rsyslogd.man.txt">rsyslogd man page</a>
+<li><a href="rsyslog_conf.html">configuration file syntax (rsyslog.conf)</a><li> <a href="property_replacer.html">property replacer, an important core component</a><li>a commented <a href="sample.conf.html">sample rsyslog.conf</a>
+<li><a href="bugs.html">rsyslog bug list</a><li><a href="rsyslog_packages.html"> rsyslog packages</a><li><a href="generic_design.html">backgrounder on generic syslog application design</a><li><a href="contributors.html">contributor &quot;Hall of Fame&quot;</a><li><a href="modules.html">description of rsyslog modules</a></ul>
+<p><b>We have some in-depth papers on</b></p>
+<ul>
+ <li><a href="install.html">installing rsyslog</a></li> <li><a href="ipv6.html">rsyslog and IPv6</a> (which is fully supported)</li>
+ <li><a href="rsyslog_stunnel.html">ssl-encrypting syslog with stunnel</a></li>
+ <li><a href="rsyslog_mysql.html">writing syslog messages to MySQL</a></li>
+ <li><a href="rsyslog_php_syslog_ng.html">using php-syslog-ng with rsyslog</a></li> <li><a href="rsyslog_recording_pri.html">recording the syslog priority (severity and facility) to the log file</a></li> <li><a href="http://www.rsyslog.com/Article19.phtml">preserving syslog sender over NAT</a> (online only)</li>
+</ul>
+<p>Also, there is an article from Dennis Olvany on
+<a href="rsyslog084-freebsd5.4.txt">Syslog-to-SQL with rsyslog-0.8.4 on FreeBSD 5.4</a>
+(which unfortunately is a bit outdated now).</p>
+<p>Our <a href="history.html">rsyslog history</a> page is for you if you would like to learn a little more
+on why there is an rsyslog at all. If you are interested why you should care about rsyslog at all, you may want to read Rainer's essay on &quot;<a href="http://rgerhards.blogspot.com/2007/08/why-does-world-need-another-syslogd.html">why the world needs another syslogd</a>&quot;.</p>
+<p>Documentation is added continuously. Please note that the documentation here
+matches only the current version of rsyslog. If you use an older version, be sure
+to use the doc that came with it.</p>
+<p><b>You can also browse the following online resources:</b></p>
+<ul>
+<li>the <a href="http://wiki.rsyslog.com/">rsyslog wiki</a>, a community resource</li>
+<li><a href="http://www.rsyslog.com/module-Static_Docs-view-f-manual.html.phtml">rsyslog online documentation</a></li>
+<li><a href="http://www.rsyslog.com/Topic3.phtml">rsyslog FAQ</a></li>
+<li><a href="http://www.rsyslog.com/PNphpBB2.phtml">rsyslog discussion forum</a></li>
+<li><a href="http://www.rsyslog.com/Topic4.phtml">rsyslog change log</a></li>
+<li><a href="http://www.monitorware.com/en/syslog-enabled-products/">syslog device configuration guide</a> (off-site)</li>
+</ul>
+<p>And don't forget about the <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">rsyslog mailing list</a>.
+If you are interested in the &quot;backstage&quot;, you may find
+<a href="http://www.gerhards.net/rainer">Rainer</a>'s
+<a href="http://rgerhards.blogspot.com/">blog</a> an interesting read (filter on syslog and rsyslog tags).</p>
+</body>
+</html>
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
new file mode 100644
index 0000000..3df2fd0
--- /dev/null
+++ b/doc/property_replacer.html
@@ -0,0 +1,148 @@
+<html>
+<head>
+<title>The Rsyslogd Property Replacer</title>
+</head>
+<body>
+<h1>The Property Replacer</h1>
+<p><b>The property replacer is a core component in rsyslogd's output system.</b>
+A syslog message has a number of well-defined properties (see below). Each of
+this properties can be accessed <b>and</b> manipulated by the property replacer.
+With it, it is easy to use only part of a property value or manipulate the value,
+e.g. by converting all characters to lower case.</p>
+<h1>Accessing Properties</h1>
+<p>Syslog message properties are used inside templates. They are accessed by putting them between percent signs. Properties can be modified by
+the property replacer. The full syntax is as follows:</p>
+<blockquote><b><code>%propname:fromChar:toChar:options%</code></b></blockquote>
+<h2>Available Properties</h2>
+<p><b><code>propname</code></b> is the name of the property to access. It is case-sensitive.
+Currently supported are:</p>
+<table>
+<tr><td><b>msg</b></td><td>the MSG part of the message (aka &quot;the message&quot; ;))</td></tr>
+<tr><td><b>rawmsg</b></td><td>the message excactly as it was received from the
+socket. Should be useful for debugging.</td></tr>
+<tr><td><b>UxTradMsg</b></td><td>will disappear soon - do NOT use!</td></tr>
+<tr><td><b>HOSTNAME</b></td><td>hostname from the message</td></tr>
+<tr><td><b>source</b></td><td>alias for HOSTNAME</td></tr>
+<tr><td><b>FROMHOST</b></td><td>hostname of the system the message was received
+ from (in a relay chain, this is the system immediately in front of us and
+ not necessarily the original sender)</td></tr>
+<tr><td><b>syslogtag</b></td><td>TAG from the message</td></tr>
+<tr><td><b>programname</b></td><td>the &quot;static&quot; part of the tag, as defined by
+BSD syslogd. For example, when TAG is "named[12345]", programname is "named".</td></tr>
+<tr><td><b>PRI</b></td><td>PRI part of the message - undecoded (single value)</td></tr>
+<tr><td><b>PRI-text</b></td><td>the PRI part of the message in a textual form
+ (e.g. &quot;syslog.info&quot;)</td></tr>
+<tr><td><b>IUT</b></td><td>the monitorware InfoUnitType - used when talking
+to a <a href="http://www.monitorware.com">MonitorWare</a> backend (also for
+ <a href="http://www.phplogcon.org/">phpLogCon</a>)</td></tr>
+<tr><td><b>syslogfacility</b></td><td>the facility from the message - in numerical form</td></tr>
+<tr>
+ <td><b>syslogfacility-text</b></td><td>the facility from the message - in
+ text form</td>
+</tr>
+<tr>
+ <td><b>syslogseverity</b></td><td>severity from the
+ message - in numerical form</td>
+</tr>
+<tr><td><b>syslogseverity-text</b></td><td>severity from the
+ message - in text form</td></tr>
+<tr><td><b>syslogpriority</b></td><td>an alias for syslogseverity - included for
+ historical reasons (be careful: it still is the severity, not PRI!)</td></tr>
+<tr><td><b>syslogpriority-text</b></td><td>an alias for syslogseverity-text</td></tr>
+<tr><td><b>timegenerated</b></td><td>timestamp when the message was RECEIVED. Always in
+ high resolution</td></tr>
+<tr><td><b>timereported</b></td><td>timestamp from the message. Resolution depends on
+what was provided in the message (in most cases,
+only seconds)</td></tr>
+<tr><td><b>TIMESTAMP</b></td><td>alias for timereported</td></tr>
+<tr><td><b>PROTOCOL-VERSION</b></td><td>The contents of the PROTCOL-VERSION
+ field from IETF draft draft-ietf-syslog-protcol</td></tr>
+<tr><td><b>STRUCTURED-DATA</b></td><td>The contents of the STRUCTURED-DATA field
+ from IETF draft draft-ietf-syslog-protocol</td></tr>
+<tr><td><b>APP-NAME</b></td><td>The contents of the APP-NAME field from IETF
+ draft draft-ietf-syslog-protocol</td></tr>
+<tr><td><b>PROCID</b></td><td>The contents of the PROCID field from IETF draft
+ draft-ietf-syslog-protocol</td></tr>
+<tr><td height="24"><b>MSGID</b></td><td height="24">The contents of the MSGID field from IETF draft
+ draft-ietf-syslog-protocol</td></tr>
+<tr><td><b>$NOW</b></td><td>The current date stamp in the format YYYY-MM-DD</td></tr>
+<tr><td><b>$YEAR</b></td><td>The current year (4-digit)</td></tr>
+<tr><td><b>$MONTH</b></td><td>The current month (2-digit)</td></tr>
+<tr><td><b>$DAY</b></td><td>The current day of the month (2-digit)</td></tr>
+<tr><td><b>$HOUR</b></td><td>The current hour in military (24 hour) time
+ (2-digit)</td></tr>
+<tr><td><b>$MINUTE</b></td><td>The current minute (2-digit)</td></tr>
+</table>
+<p>Properties starting with a $-sign are so-called system properties. These do
+NOT stem from the message but are rather internally-generated.</p>
+<h2>Character Positions</h2>
+<p><b><code>FromChar</code></b> and <b><code>toChar</code></b> are used to build substrings. They specify the offset within
+the string that should be copied. Offset counting starts at 1, so if you need to
+obtain the first 2 characters of the message text, you can use this syntax:
+&quot;%msg:1:2%&quot;. If you do not whish to specify from and to, but you want to specify
+options, you still need to include the colons. For example, if you would like to
+convert the full message text to lower case, use &quot;%msg:::lowercase%&quot;.
+If you would like to extract from a position until the end of the string, you
+can place a dollar-sign (&quot;$&quot;) in toChar (e.g. %msg:10:$%, which will extract
+from position 10 to the end of the string).<p>
+There is also support for <b>regular expressions</b>. To use them, you need to
+place a &quot;R&quot; into FromChar. This tells rsyslog that a regular expression instead
+of position-based extraction is desired. The actual regular expression must then
+be provided in toChar. The regular expression <b>must</b> be followed by the
+string &quot;--end&quot;. It denotes the end of the regular expression and will not become
+part of it. If you are using regular expressions, the property replacer will
+return the part of the property text that matches the regular expression. An
+example for a property replacer sequence with a regular expression is: &quot;%msg:R:.*Sev:.
+\(.*\) \[.*--end%&quot;<br>
+<p>
+<b>Also, extraction can be done based on so-called &quot;fields&quot;</b>. To do so, place
+a &quot;F&quot; into FromChar. A field in its current definition is anything
+that is delimited by a delimiter character. The delimiter by default is TAB
+(US-ASCII value 9). However, if can be changed to any other US-ASCII character
+by specifying a comma and the <b>decimal</b> US-ASCII value of the delimiter immediately after the
+&quot;F&quot;. For example, to use comma (&quot;,&quot;) as a delimiter, use this field specifier:
+&quot;F,44&quot;.&nbsp; If your syslog data is delimited,
+this is a quicker way to extract than via regular expressions (actually, a *much*
+quicker way). Field counting starts at 1. Field zero is accepted, but will
+always lead to a &quot;field not found&quot; error. The same happens if a field number
+higher than the number of fields in the property is requested. The field number
+must be placed in the &quot;ToChar&quot; parameter. An example where the 3rd field
+(delimited by TAB) from
+the msg property is extracted is as follows: &quot;%msg:F:3%&quot;. The same
+example with semicolon as delimiter is &quot;%msg:F,59:3%&quot;.<p>
+Please note that the special characters &quot;F&quot; and &quot;R&quot; are case-sensitive. Only
+upper case works, lower case will return an error. There are no white spaces
+permitted inside the sequence (that will lead to error messages and will NOT
+provide the intended result).<br>
+<h2>Property Options</h2>
+<b><code>property options</code></b> are case-insensitive. Currently, the following options
+are defined:</p>
+<table>
+<tr><td><b>uppercase</b></td><td>convert property to lowercase only</td></tr>
+<tr><td><b>lowercase</b></td><td>convert property text to uppercase only</td></tr>
+<tr><td><b>drop-last-lf</b></td><td>The last LF in the message (if any), is dropped.
+ Especially useful for PIX.</td></tr>
+<tr><td><b>date-mysql</b></td><td>format as mysql date</td></tr>
+<tr><td><b>date-rfc3164</b></td><td>format as RFC 3164 date</td></tr>
+<tr><td><b>date-rfc3339</b></td><td>format as RFC 3339 date</td></tr>
+<tr><td><b>escape-cc</b></td><td>replace control characters (ASCII value 127 and
+ values less then 32) with an escape sequence. The sequnce is &quot;#&lt;charval&gt;&quot;
+ where charval is the 3-digit decimal value of the control character. For
+ example, a tabulator would be replaced by &quot;#009&quot;.</td></tr>
+<tr><td><b>space-cc</b></td><td>replace control characters by spaces</td></tr>
+<tr><td><b>drop-cc</b></td><td>drop control characters - the resulting string
+ will neither contain control characters, escape sequences nor any other
+ replacement character like space.</td></tr>
+</table>
+
+<h2>Further Links</h2>
+<ul>
+ <li>Article on &quot;<a href="rsyslog_recording_pri.html">Recording the Priority of
+ Syslog Messages</a>&quot; (describes use of templates to record severity and
+ facility of a message)</li>
+ <li><a href="rsyslog_conf.html">Configuration file syntax</a>, this is where you
+ actually use the property replacer.</li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/rsconf1_actionexeconlyifpreviousissuspended.html b/doc/rsconf1_actionexeconlyifpreviousissuspended.html
new file mode 100644
index 0000000..2568ccf
--- /dev/null
+++ b/doc/rsconf1_actionexeconlyifpreviousissuspended.html
@@ -0,0 +1,29 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$ActionExecOnlyIfPreviousIsSuspended</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> off</p>
+<p><b>Description:</b></p>
+<p>This directive allows to specify if actions should always be executed ("off," the default) or only if the previous action is suspended ("on"). This directive works hand-in-hand with the multiple actions per selector feature. It can be used, for example, to create rules that automatically switch destination servers or databases to a (set of) backup(s), if the primary server fails. Note that this feature depends on proper implementation of the suspend feature in the output module. All built-in output modules properly support it (most importantly the database write and the syslog message forwarder).</p>
+<p>This selector processes all messages it receives (*.*). It tries to forward every message to primary-syslog.example.com (via tcp). If it can not reach that server, it tries secondary-1-syslog.example.com, if that fails too, it tries secondary-2-syslog.example.com. If neither of these servers can be connected, the data is stored in /var/log/localbuffer. Please note that the secondaries and the local log buffer are only used if the one before them does not work. So ideally, /var/log/localbuffer will never receive a message. If one of the servers resumes operation, it automatically takes over processing again.</p>
+<p>We strongly advise not to use repeated line reduction together with ActionExecOnlyIfPreviousIsSuspended. It may lead to "interesting" and undesired results (but you can try it if you like).</p>
+<p><b>Sample:</b></p>
+<p><code><b>*.* @@primary-syslog.example.com
+<br>$ActionExecOnlyIfPreviousIsSuspended on
+<br>& @@secondary-1-syslog.example.com # & is used to have more than one action for
+<br>& @@secondary-2-syslog.example.com # the same selector - the mult-action feature
+<br>& /var/log/localbuffer
+<br>$ActionExecOnlyIfPreviousIsSuspended off # to re-set it for the next selector </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> \ No newline at end of file
diff --git a/doc/rsconf1_actionresumeinterval.html b/doc/rsconf1_actionresumeinterval.html
new file mode 100644
index 0000000..a854a21
--- /dev/null
+++ b/doc/rsconf1_actionresumeinterval.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$ActionResumeInterval</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> 30</p>
+<p><b>Description:</b></p>
+<p>Sets the ActionResumeInterval for all following actions. The interval
+provided is always in seconds. Thus, multiply by 60 if you need minutes and
+3,600 if you need hours (not recommended).</p>
+<p>When an action is suspended (e.g. destination can not be connected), the
+action is resumed for the configured interval. Thereafter, it is retried. If
+multiple retires fail, the interval is automatically extended. This is to
+prevent excessive ressource use for retires. After each 10 retries, the interval
+is extended by itself. To be precise, the actual interval is (numRetries / 10 +
+1) * $ActionResumeInterval. so after the 10th try, it by default is 60 and after
+the 100th try it is 330.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$ActionResumeInterval 30 </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> \ No newline at end of file
diff --git a/doc/rsconf1_allowedsender.html b/doc/rsconf1_allowedsender.html
new file mode 100644
index 0000000..619b71e
--- /dev/null
+++ b/doc/rsconf1_allowedsender.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$AllowedSender</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> all allowed</p>
+<p><b>Description:</b></p>
+<p>Allowed sender lists can be used to specify which remote systems are allowed to send syslog messages to rsyslogd. With them, further hurdles can be placed between an attacker and rsyslogd. If a message from a system not in the allowed sender list is received, that message is discarded. A diagnostic message is logged, so that the fact is recorded (this message can be turned off with the "-w" rsyslogd command line option).</p>
+<p>Allowed sender lists can be defined for UDP and TCP senders separately. There can be as many allowed senders as needed. The syntax to specify them is:</p>
+<p><code><b>$AllowedSender <protocol>, ip[/bits], ip[/bits]</b></code></p>
+<p>"$AllowedSender" is the directive - it must be written exactly as shown and the $ must start at the first column of the line. "<protocol>" is either "UDP" or "TCP". It must immediately be followed by the comma, else you will receive an error message. "ip[/bits]" is a machine or network ip address as in "192.0.2.0/24" or "127.0.0.1". If the "/bits" part is omitted, a single host is assumed (32 bits or mask 255.255.255.255). "/0" is not allowed, because that would match any sending system. If you intend to do that, just remove all $AllowedSender directives. If more than 32 bits are requested with IPv4, they are adjusted to 32. For IPv6, the limit is 128 for obvious reasons. Hostnames, with and without wildcards, may also be provided. If so, the result of revers DNS resolution is used for filtering. Multiple allowed senders can be specified in a comma-delimited list. Also, multiple $AllowedSender lines can be given. They are all combined into one UDP and one TCP list. Performance-wise, it is good to specify those allowed senders with high traffic volume before those with lower volume. As soon as a match is found, no further evaluation is necessary and so you can save CPU cycles.</p>
+<p>Rsyslogd handles allowed sender detection very early in the code, nearly as the first action after receiving a message. This keeps the access to potential vulnerable code in rsyslog at a minimum. However, it is still a good idea to impose allowed sender limitations via firewalling.</p>
+<p><b>WARNING:</b> by UDP design, rsyslogd can not identify a spoofed sender address in UDP syslog packets. As such, a malicious person could spoof the address of an allowed sender, send such packets to rsyslogd and rsyslogd would accept them as being from the faked sender. To prevent this, use syslog via TCP exclusively. If you need to use UDP-based syslog, make sure that you do proper egress and ingress filtering at the firewall and router level.</p>
+<p>Rsyslog also detects some kind of malicious reverse DNS entries. In any case, using DNS names adds an extra layer of vulnerability. We recommend to stick with hard-coded IP addresses whereever possible.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$AllowedSender UDP, 127.0.0.1, 192.0.2.0/24, [::1]/128, *.example.net, somehost.example.com</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> \ No newline at end of file
diff --git a/doc/rsconf1_controlcharacterescapeprefix.html b/doc/rsconf1_controlcharacterescapeprefix.html
new file mode 100644
index 0000000..23bf5c6
--- /dev/null
+++ b/doc/rsconf1_controlcharacterescapeprefix.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$ControlCharacterEscapePrefix</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> \</p>
+<p><b>Description:</b></p>
+<p>This option specifies the prefix character to be used for control character escaping (see option $EscapeControlCharactersOnReceive). By default, it is '\', which is backwards-compatible with sysklogd. Change it to '#' in order to be compliant to the value that is somewhat suggested by Internet-Draft syslog-protocol.</p>
+<p><b>IMPORTANT</b>: do not use the ' character. This is reserved and will most probably be used in the future as a character delimiter. For the same reason, the syntax of this directive will probably change in furture releases.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$EscapeControlCharactersOnReceive #&nbsp; # as of syslog-protocol</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> \ No newline at end of file
diff --git a/doc/rsconf1_debugprintcfsyslinehandlerlist.html b/doc/rsconf1_debugprintcfsyslinehandlerlist.html
new file mode 100644
index 0000000..1aad755
--- /dev/null
+++ b/doc/rsconf1_debugprintcfsyslinehandlerlist.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DebugPrintCFSyslineHandlerList</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>Specifies whether or not the configuration file sysline handler list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled.</p>
+<p><b>Sample:</b></p>
+<p><code><b></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> \ No newline at end of file
diff --git a/doc/rsconf1_debugprintmodulelist.html b/doc/rsconf1_debugprintmodulelist.html
new file mode 100644
index 0000000..4d8e9bf
--- /dev/null
+++ b/doc/rsconf1_debugprintmodulelist.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DebugPrintModuleList</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>Specifies whether or not the module list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled.</p>
+<p><b>Sample:</b></p>
+<p><code><b></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> \ No newline at end of file
diff --git a/doc/rsconf1_debugprinttemplatelist.html b/doc/rsconf1_debugprinttemplatelist.html
new file mode 100644
index 0000000..243530e
--- /dev/null
+++ b/doc/rsconf1_debugprinttemplatelist.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DebugPrintTemplateList</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>Specifies whether or not the template list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled..</p>
+<p><b>Sample:</b></p>
+<p><code><b></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> \ No newline at end of file
diff --git a/doc/rsconf1_dircreatemode.html b/doc/rsconf1_dircreatemode.html
new file mode 100644
index 0000000..66a35e1
--- /dev/null
+++ b/doc/rsconf1_dircreatemode.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DirCreateMode</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> 0644</p>
+<p><b>Description:</b></p>
+<p>This is the same as $FileCreateMode, but for directories automatically generated.</p>
+<p><b>Sample:</b></p>
+<p><code><b></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> \ No newline at end of file
diff --git a/doc/rsconf1_dirgroup.html b/doc/rsconf1_dirgroup.html
new file mode 100644
index 0000000..868e5ec
--- /dev/null
+++ b/doc/rsconf1_dirgroup.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DirGroup</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>Set the group for directories newly created. Please note that this setting does not affect the group of directories already existing. The parameter is a group name, for which the groupid is obtained by rsyslogd on startup and on HUPing. Interim changes to the user mapping are not detected.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$DirGroup loggroup</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> \ No newline at end of file
diff --git a/doc/rsconf1_dirowner.html b/doc/rsconf1_dirowner.html
new file mode 100644
index 0000000..e85a512
--- /dev/null
+++ b/doc/rsconf1_dirowner.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DirOwner</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>Set the file owner for directories newly created. Please note that this setting does not affect the owner of directories already existing. The parameter is a user name, for which the userid is obtained by rsyslogd on startup and on HUPing. Interim changes to the user mapping are not detected.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$DirOwner loguser</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> \ No newline at end of file
diff --git a/doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html b/doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html
new file mode 100644
index 0000000..e0a53ae
--- /dev/null
+++ b/doc/rsconf1_dropmsgswithmaliciousdnsptrrecords.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DropMsgsWithMaliciousDnsPTRRecords</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> off</p>
+<p><b>Description:</b></p>
+<p>Rsyslog contains code to detect malicious DNS PTR records (reverse name resolution). An attacker might use specially-crafted DNS entries to make you think that a message might have originated on another IP address. Rsyslog can detect those cases. It will log an error message in any case. If this option here is set to "on", the malicious message will be completely dropped from your logs. If the option is set to "off", the message will be logged, but the original IP will be used instead of the DNS name.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$DropMsgsWithMaliciousDnsPTRRecords 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> \ No newline at end of file
diff --git a/doc/rsconf1_droptrailinglfonreception.html b/doc/rsconf1_droptrailinglfonreception.html
new file mode 100644
index 0000000..e0054cc
--- /dev/null
+++ b/doc/rsconf1_droptrailinglfonreception.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DropTrailingLFOnReception</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>Syslog messages frequently have the line feed character (LF) as the last character of the message. In allmost all cases, this LF should not really become part of the message. However, recent IETF syslog standardization recommends against modifying syslog messages (e.g. to keep digital signatures valid). This option allows to specify if trailing LFs should be dropped or not. The default is to drop them, which is consistent with what sysklogd does.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$DropTrailingLFOnRecption 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> \ No newline at end of file
diff --git a/doc/rsconf1_dynafilecachesize.html b/doc/rsconf1_dynafilecachesize.html
new file mode 100644
index 0000000..3813f98
--- /dev/null
+++ b/doc/rsconf1_dynafilecachesize.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$DynaFileCacheSize</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> 10</p>
+<p><b>Description:</b></p>
+<p>This directive specifies the maximum size of the cache for dynamically-generated file names. Selector lines with dynamic files names ('?' indicator) support writing to multiple files with a single selector line. This setting specifies how many open file handles should be cached. If, for example, the file name is generated with the hostname in it and you have 100 different hosts, a cache size of 100 would ensure that files are opened once and then stay open. This can be a great way to increase performance. If the cache size is lower than the number of different files, the least recently used one is discarded (and the file closed). The hardcoded maximum is 10,000 - a value that we assume should already be very extreme. Please note that if you expect to run with a very large number of files, you probably need to reconfigure the kernel to support such a large number. In practice, we do NOT recommend to use a cache of more than 1,000 entries. The cache lookup would probably require more time than the open and close operations. The minimum value is 1.</p>
+<p>Numbers are always in decimal. Leading zeros should be avoided (in some later version, they may be mis-interpreted as being octal). Multiple directives may be given. They are applied to selector lines based on order of appearance.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$DynaFileCacheSize 100&nbsp;&nbsp;&nbsp; # a cache of 100 files at most</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> \ No newline at end of file
diff --git a/doc/rsconf1_escapecontrolcharactersonreceive.html b/doc/rsconf1_escapecontrolcharactersonreceive.html
new file mode 100644
index 0000000..f273b85
--- /dev/null
+++ b/doc/rsconf1_escapecontrolcharactersonreceive.html
@@ -0,0 +1,29 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$EscapeControlCharactersOnReceive</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>This directive instructs rsyslogd to replace control characters during reception of the message. The intent is to provide a way to stop non-printable messages from entering the syslog system as whole. If this option is truned on, all control-characters are converted to a 3-digit octal number and be prefixed with the $ControlCharacterEscapePrefix character (being '\' by default). For example, if the BEL character (ctrl-g) is included in the message, it would be converted to "\007". To be compatible to sysklogd, this option must be turned on.</p>
+<p><b>Warning:</b></p>
+<ul>
+ <li>turning on this option most probably destroys non-western character sets
+ (like Japanese, Chinese and Korean)</li>
+ <li>turning on this option destroys digital signatures if such exists inside
+ the message</li>
+</ul>
+<p><b>Sample:</b></p>
+<p><code><b>$EscapeControlCharactersOnReceive 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> \ No newline at end of file
diff --git a/doc/rsconf1_failonchownfailure.html b/doc/rsconf1_failonchownfailure.html
new file mode 100644
index 0000000..0e646e3
--- /dev/null
+++ b/doc/rsconf1_failonchownfailure.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$FailOnChownFailure</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> on</p>
+<p><b>Description:</b></p>
+<p>This option modifies behaviour of dynaFile creation. If different owners or groups are specified for new files or directories and rsyslogd fails to set these new owners or groups, it will log an error and NOT write to the file in question if that option is set to "on". If it is set to "off", the error will be ignored and processing continues. Keep in mind, that the files in this case may be (in)accessible by people who should not have permission. The default is "on".</p>
+<p><b>Sample:</b></p>
+<p><code><b>$FailOnChownFailure off</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> \ No newline at end of file
diff --git a/doc/rsconf1_filecreatemode.html b/doc/rsconf1_filecreatemode.html
new file mode 100644
index 0000000..b6498cd
--- /dev/null
+++ b/doc/rsconf1_filecreatemode.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$FileCreateMode</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> 0644</p>
+<p><b>Description:</b></p>
+<p>The $FileCreateMode directive allows to specify the creation mode with which rsyslogd creates new files. If not specified, the value 0644 is used (which retains backward-compatibility with earlier releases). The value given must always be a 4-digit octal number, with the initial digit being zero.</p>
+<p>Please note that the actual permission depend on rsyslogd's process umask. If in doubt, use "$umask 0000" right at the beginning of the configuration file to remove any restrictions.</p>
+<p>$FileCreateMode may be specified multiple times. If so, it specifies the creation mode for all selector lines that follow until the next $FileCreateMode directive. Order of lines is vitally important.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$FileCreateMode 0600</b></code></p>
+<p>This sample lets rsyslog create files with read and write access only for the users it runs under.</p>
+<p>The following sample is deemed to be a complete rsyslog.conf:
+<p><code><b>$umask 0000 # make sure nothing interfers with the following
+definitions<br>
+*.* /var/log/file-with-0644-default<br>
+$FileCreateMode 0600<br>
+*.* /var/log/file-with-0600<br>
+$FileCreateMode 0644<br>
+*.* /var/log/file-with-0644</b></code></p>
+<p>As you can see, open modes depend on position in the config file. Note the
+first line, which is created with the hardcoded default creation mode.</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> \ No newline at end of file
diff --git a/doc/rsconf1_filegroup.html b/doc/rsconf1_filegroup.html
new file mode 100644
index 0000000..b9acaab
--- /dev/null
+++ b/doc/rsconf1_filegroup.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$FileGroup</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>Set the group for dynaFiles newly created. Please note that this setting does not affect the group of files already existing. The parameter is a group name, for which the groupid is obtained by rsyslogd on startup and on HUPing. Interim changes to the user mapping are not detected.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$FileGroup loggroup</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> \ No newline at end of file
diff --git a/doc/rsconf1_fileowner.html b/doc/rsconf1_fileowner.html
new file mode 100644
index 0000000..7a9cbbc
--- /dev/null
+++ b/doc/rsconf1_fileowner.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$FileOwner</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>Set the file owner for dynaFiles newly created. Please note that this setting does not affect the owner of files already existing. The parameter is a user name, for which the userid is obtained by rsyslogd on startup and on HUPing. Interim changes to the user mapping are not detected.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$FileOwner loguser</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> \ No newline at end of file
diff --git a/doc/rsconf1_includeconfig.html b/doc/rsconf1_includeconfig.html
new file mode 100644
index 0000000..155dcd4
--- /dev/null
+++ b/doc/rsconf1_includeconfig.html
@@ -0,0 +1,44 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$IncludeConfig</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>This directive allows to include other files into the main configuration file. As soon as an IncludeConfig directive is found, the contents of the new file is processed. IncludeConfigs can be nested. Please note that from a logical point of view the files are merged. Thus, if the include modifies some parameters (e.g. $DynaFileChacheSize), these new parameters are in place for the "calling" configuration file when the include is completed. To avoid any side effects, do a $ResetConfigVariables after the $IncludeConfig. It may also be a good idea to do a $ResetConfigVariables right at the start of the include, so that the module knows exactly what it does. Of course, one might specifically NOT do this to inherit parameters from the main file. As always, use it as it best fits...</p>
+<p>If all regular files in the /etc/rsyslog.d directory are included, then files starting with "." are ignored - so you can use them to place comments into the dir (e.g. "/etc/rsyslog.d/.mycomment" will be ignored). <a href="http://sourceforge.net/tracker/index.php?func=detail&aid=1764088&group_id=123448&atid=696555">Michael Biebl had the idea to this functionality</a>. Let me quote hím:</p>
+<blockquote>
+<p><i>Say you can add an option<br>
+$IncludeConfig /etc/rsyslog.d/<br>
+(which probably would make a good default)<br>
+to /etc/rsyslog.conf, which would then merge and include all *.conf files<br>
+in /etc/rsyslog.d/.<br>
+<br>
+This way, a distribution can modify its packages easily to drop a simple<br>
+config file into this directory upon installation.<br>
+<br>
+As an example, the network-manager package could install a simple config<br>
+file /etc/rsyslog.d/network-manager.conf which would contain.<br>
+:programname, contains, &quot;NetworkManager&quot; -/var/log/NetworkManager.log<br>
+<br>
+Upon uninstallation, the file could be easily removed again. This approach<br>
+would be much cleaner and less error prone, than having to munge around<br>
+with the /etc/rsyslog.conf file directly.</i></p>
+</blockquote>
+<p>Please note that in this description, only "*.conf" files would be read. The actual implementation, however, reads all files except for those starting with a dot. If you find this is a real big problem, please complain.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$IncludeConfig /etc/some-included-file.conf</b></code></p>
+<p>Directories can also be included. To do so, the name must end on a slash:</p>
+<p><code><b>$IncludeConfig /etc/rsyslog.d/</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> \ No newline at end of file
diff --git a/doc/rsconf1_mainmsgqueuesize.html b/doc/rsconf1_mainmsgqueuesize.html
new file mode 100644
index 0000000..b9501e0
--- /dev/null
+++ b/doc/rsconf1_mainmsgqueuesize.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$MainMsgQueueSize</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> 10000</p>
+<p><b>Description:</b></p>
+<p>This allows to specify the maximum size of the message queue. This directive is only available when rsyslogd has been compiled with multithreading support. In this mode, receiver and output modules are de-coupled via an in-memory queue. This queue buffers messages when the output modules are not capable to process them as fast as they are received. Once the queue size is exhausted, messages will be dropped. The slower the output (e.g. MySQL), the larger the queue should be. Buffer space for the actual queue entries is allocated on an as-needed basis. Please keep in mind that a very large queue may exhaust available system memory and swap space. Keep this in mind when configuring the max size. The actual size of a message depends largely on its content and the orginator. As a rule of thumb, typically messages should not take up more then roughtly 1k (this is the memory structure, not what you see in a network dump!). For typical linux messages, 512 bytes should be a good bet. Please also note that there is a minimal amout of memory taken for each queue entry, no matter if it is used or not. This is one pointer value, so on 32bit systems, it should typically be 4 bytes and on 64bit systems it should typically be 8 bytes. For example, the default queue size of 10,000 entries needs roughly 40k fixed overhead on a 32 bit system.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$MainMsgQueueSize 100000 # 100,000 may be a value to handle bursty traffic</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> \ No newline at end of file
diff --git a/doc/rsconf1_modload.html b/doc/rsconf1_modload.html
new file mode 100644
index 0000000..7108a21
--- /dev/null
+++ b/doc/rsconf1_modload.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$ModLoad</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>This currently is a dummy directive. It will support the loading of plug-ins in future releases of rsyslog supporting plug-ins. Currently, only "MySQL" is supported as parameter. This activates MySQL support (if rsyslog is compiled with MySQL functionality).</p>
+<p><b>Sample:</b></p>
+<p><code><b>$ModLoad MySQL</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> \ No newline at end of file
diff --git a/doc/rsconf1_repeatedmsgreduction.html b/doc/rsconf1_repeatedmsgreduction.html
new file mode 100644
index 0000000..20e56f8
--- /dev/null
+++ b/doc/rsconf1_repeatedmsgreduction.html
@@ -0,0 +1,23 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$RepeatedMsgReduction</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> depending on -e</p>
+<p><b>Description:</b></p>
+<p>This directive specifies whether or not repeated messages should be reduced (this is the "Last line repeated n times" feature). If set to on, repeated messages are reduced. If set to off, every message is logged. Please note that this directive overrides the -e command line option. In case -e is given, it is just the default value until the first RepeatedMsgReduction directive is encountered.</p>
+<p>This directives affects selector lines until a new directive is specified.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$RepeatedMsgReduction off&nbsp;&nbsp;&nbsp; # log every message</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> \ No newline at end of file
diff --git a/doc/rsconf1_resetconfigvariables.html b/doc/rsconf1_resetconfigvariables.html
new file mode 100644
index 0000000..9794d15
--- /dev/null
+++ b/doc/rsconf1_resetconfigvariables.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$ResetConfigVariables</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>Resets all configuration variables to their default value. Any settings made will not be applied to configuration lines following the $ResetConfigVariables. This is a good method to make sure no side-effects exists from previous directives. This directive has no parameters.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$ResetConfigVariables</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> \ No newline at end of file
diff --git a/doc/rsconf1_umask.html b/doc/rsconf1_umask.html
new file mode 100644
index 0000000..ee47dba
--- /dev/null
+++ b/doc/rsconf1_umask.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h2>$UMASK</h2>
+<p><b>Type:</b> global configuration directive</p>
+<p><b>Default:</b> </p>
+<p><b>Description:</b></p>
+<p>The $umask directive allows to specify the rsyslogd processes' umask. If not specified, the system-provided default is used. The value given must always be a 4-digit octal number, with the initial digit being zero.</p>
+<p>If $umask is specified multiple times in the configuration file, results may be somewhat unpredictable. It is recommended to specify it only once.</p>
+<p><b>Sample:</b></p>
+<p><code><b>$umask 0000</b></code></p>
+<p>This sample removes all restrictions.</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> \ No newline at end of file
diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html
new file mode 100644
index 0000000..dcbf5da
--- /dev/null
+++ b/doc/rsyslog_conf.html
@@ -0,0 +1,811 @@
+<html>
+<head>
+<title>rsyslog.conf file</title>
+</head>
+<body>
+<h1>rsyslog.conf configuration file</h1>
+<p><b>This document is currently being enhanced. Please pardon its current
+appearance.</b></p>
+<p><b>Rsyslogd is configured via the rsyslog.conf file</b>, typically found in
+/etc. By default, rsyslogd reads the file /etc/rsyslog.conf.</p>
+<p>While rsyslogd contains enhancements over standard syslogd, efforts have been
+made to keep the configuration file as compatible as possible. While, for
+obvious reasons, <a href="features.html">enhanced features</a> require a
+different config file syntax, rsyslogd should be able to work with a standard
+syslog.conf file. This is especially useful while you are migrating from syslogd
+to rsyslogd.</p>
+<h2>Global Directives</h2>
+<p>All global directives need to be specified on a line by their own and must
+start with a dollar-sign. Here is a list in alphabetical order. Follow links for
+a description.</p>
+<ul>
+ <li><a href="rsconf1_actionexeconlyifpreviousissuspended.html">$ActionExecOnlyIfPreviousIsSuspended</a></li>
+ <li><a href="rsconf1_actionresumeinterval.html">$ActionResumeInterval</a></li>
+ <li><a href="rsconf1_allowedsender.html">$AllowedSender</a></li>
+ <li><a href="rsconf1_controlcharacterescapeprefix.html">$ControlCharacterEscapePrefix</a></li>
+ <li><a href="rsconf1_debugprintcfsyslinehandlerlist.html">$DebugPrintCFSyslineHandlerList</a></li>
+ <li><a href="rsconf1_debugprintmodulelist.html">$DebugPrintModuleList</a></li>
+ <li><a href="rsconf1_debugprinttemplatelist.html">$DebugPrintTemplateList</a></li>
+ <li><a href="rsconf1_dircreatemode.html">$DirCreateMode</a></li>
+ <li><a href="rsconf1_dirgroup.html">$DirGroup</a></li>
+ <li><a href="rsconf1_dirowner.html">$DirOwner</a></li>
+ <li><a href="rsconf1_dropmsgswithmaliciousdnsptrrecords.html">$DropMsgsWithMaliciousDnsPTRRecords</a></li>
+ <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><a href="rsconf1_failonchownfailure.html">$FailOnChownFailure</a></li>
+ <li><a href="rsconf1_filecreatemode.html">$FileCreateMode</a></li>
+ <li><a href="rsconf1_filegroup.html">$FileGroup</a></li>
+ <li><a href="rsconf1_fileowner.html">$FileOwner</a></li>
+ <li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li>
+ <li><a href="rsconf1_mainmsgqueuesize.html">$MainMsgQueueSize</a></li>
+ <li><a href="rsconf1_modload.html">$ModLoad</a></li>
+ <li><a href="rsconf1_repeatedmsgreduction.html">$RepeatedMsgReduction</a></li>
+ <li><a href="rsconf1_resetconfigvariables.html">$ResetConfigVariables</a></li>
+ <li><a href="rsconf1_umask.html">$UMASK</a></li>
+</ul>
+<h2>Basic Structure</h2>
+<p>Rsyslog supports standard sysklogd's configuration file format and extends
+it. So in general, you can take a &quot;normal&quot; syslog.conf and use it together with
+rsyslogd. It will understand everything. However, to use most of rsyslogd's
+unique features, you need to add extended configuration directives.<p>Rsyslogd
+supports the classical, selector-based rule lines. They are still at the heart
+of it and all actions are initiated via rule lines. A rule lines is any line not
+starting with a $ or the comment sign (#). Lines starting with $ carry
+rsyslog-specific directives.<p>Every rule line consists of two fields, a selector field and an action field.
+These two fields are separated by one or more spaces or tabs. The selector field
+specifies a pattern of facilities and priorities belonging to the specified
+action.<br>
+<br>
+Lines starting with a hash mark (&quot;#'') and empty lines are ignored.
+
+<h2>Templates</h2>
+<p>Templates are a key feature of rsyslog. They allow to specify any format a user
+might want. They are also used for dynamic file name generation. Every output in rsyslog uses templates - this holds true for files,
+user messages and so on. The database writer expects its template to be a proper
+SQL statement - so this is highly customizable too. You might ask how does all
+of this work when no templates at all are specified. Good question ;) The answer
+is simple, though. Templates compatible with the stock syslogd formats are
+hardcoded into rsyslogd. So if no template is specified, we use one of these
+hardcoded templates. Search for &quot;template_&quot; in syslogd.c and you will find the
+hardcoded ones.</p>
+<p>A template consists of a template directive, a name, the actual template text
+and optional options. A sample is:</p>
+<blockquote><code>$template MyTemplateName,&quot;\7Text %property% some more text\n&quot;,&lt;options&gt;</code></blockquote>
+<p>The &quot;$template&quot; is the template directive. It tells rsyslog that this line
+contains a template. &quot;MyTemplateName&quot; is the template name. All
+other config lines refer to this name. The text within quotes is the actual
+template text. The backslash is an escape character, much as it is in C. It does
+all these &quot;cool&quot; things. For example, \7 rings the bell (this is an ASCII
+value), \n is a new line. C programmers and perl coders have the advantage of
+knowing this, but the set in rsyslog is a bit restricted currently.
+<p>
+All text in the template is used literally, except for things within percent
+signs. These are properties and allow you access to the contents of the syslog
+message. Properties are accessed via the property replacer (nice name, huh) and
+it can do cool things, too. For example, it can pick a substring or do
+date-specific formatting. More on this is below, on some lines of the property
+replacer.<br>
+<br>
+The &lt;options&gt; part is optional. It carries options influencing the template as
+whole. See details below. Be sure NOT to mistake template options with property
+options - the later ones are processed by the property replacer and apply to a
+SINGLE property, only (and not the whole template).<br>
+<br>
+Template options are case-insensitive. Currently defined are: </p>
+<p><b>sql</b> - format the string suitable for a SQL statement in MySQL format. This will
+replace single quotes (&quot;'&quot;) and the backslash character by their
+backslash-escaped counterpart (&quot;\'&quot; and &quot;\\&quot;) inside each field. Please note
+that in MySQL configuration, the <code class="literal">NO_BACKSLASH_ESCAPES</code>
+mode must be turned off for this format to work (this is the default).</p>
+<p><b>stdsql</b> - format the string suitable for a SQL statement that is to be
+sent to a standards-compliant sql server. This will
+replace single quotes (&quot;'&quot;) by two single quotes (&quot;''&quot;) inside each field.
+You must use stdsql together with MySQL if in MySQL configuration the
+<code class="literal">NO_BACKSLASH_ESCAPES</code> is turned on.</p>
+<p>Either the <b>sql</b> or <b>stdsql</b>&nbsp;
+option <b>must</b> be specified when a template is used for writing to a database,
+otherwise injection might occur. Please note that due to the unfortunate fact
+that several vendors have violated the sql standard and introduced their own
+escape methods, it is impossible to have a single option doing all the work.&nbsp;
+So you yourself must make sure you are using the right format. <b>If you choose
+the wrong one, you are still vulnerable to sql injection.</b><br>
+<br>
+Please note that the database writer *checks* that the sql option is present in
+the template. If it is not present, the write database action is disabled. This
+is to guard you against accidential forgetting it and then becoming vulnerable
+to SQL injection. The sql option can also be useful with files - especially if
+you want to import them into a database on another machine for performance
+reasons. However, do NOT use it if you do not have a real need for it - among
+others, it takes some toll on the processing time. Not much, but on a really
+busy system you might notice it ;)</p>
+<p>The default template for the write to database action has the sql option set.
+As we currently support only MySQL and the sql option matches the default MySQL
+configuration, this is a good choice. However, if you have turned on
+<code class="literal">NO_BACKSLASH_ESCAPES</code> in your MySQL config, you need
+to supply a template with the stdsql option. Otherwise you will become
+vulnerable to SQL injection. <br>
+<br>
+To escape:<br>
+% = \%<br>
+\ = \\ --&gt; '\' is used to escape (as in C)<br>
+$template TraditionalFormat,%timegenerated% %HOSTNAME% %syslogtag%%msg%\n&quot;<br>
+<br>
+Properties can be accessed by the <a href="property_replacer.html">property replacer</a>
+(see there for details).</p>
+<p><b>Please note that as of 1.15.0, templates can also by used to generate
+selector lines with dynamic file names.</b> For example, if you would like to
+split syslog messages from different hosts to different files (one per host),
+you can define the following template:</p>
+<blockquote><code>$template DynFile,&quot;/var/log/system-%HOSTNAME%.log&quot;</code></blockquote>
+<p>This template can then be used when defining an output selector line. It will
+result in something like &quot;/var/log/system-localhost.log&quot;</p>
+<h2>Output Channels</h2>
+<p>Output Channels are a new concept first introduced in rsyslog 0.9.0. <b>As of this
+writing, it is most likely that they will be replaced by something different in
+the future.</b> So if you
+use them, be prepared to change you configuration file syntax when you upgrade
+to a later release.<br>
+<br>
+The idea behind output channel definitions is that it shall provide an umbrella
+for any type of output that the user might want. In essence,<br>
+this is the &quot;file&quot; part of selector lines (and this is why we are not sure
+output channel syntax will stay after the next review). There is a<br>
+difference, though: selector channels both have filter conditions (currently
+facility and severity) as well as the output destination. Output channels define
+the output defintion, only. As of this build, they can only be used to write to
+files - not pipes, ttys or whatever else. If we stick with output channels, this
+will change over time.</p>
+<p>In concept, an output channel includes everything needed to know about an
+output actions. In practice, the current implementation only carries<br>
+a filename, a maximum file size and a command to be issued when this file size
+is reached. More things might be present in future version, which might also
+change the syntax of the directive.</p>
+<p>Output channels are defined via an $outchannel directive. It's syntax is as
+follows:<br>
+<br>
+$outchannel name,file-name,max-size,action-on-max-size<br>
+<br>
+name is the name of the output channel (not the file), file-name is the file
+name to be written to, max-size the maximum allowed size and action-on-max-size
+a command to be issued when the max size is reached. This command always has
+exactly one parameter. The binary is that part of action-on-max-size before the
+first space, its parameter is everything behind that space.<br>
+<br>
+Please note that max-size is queried BEFORE writing the log message to the file.
+So be sure to set this limit reasonably low so that any message might fit. For
+the current release, setting it 1k lower than you expected is helpful. The
+max-size must always be specified in bytes - there are no special symbols (like
+1k, 1m,...) at this point of development.<br>
+<br>
+Keep in mind that $outchannel just defines a channel with &quot;name&quot;. It does not
+activate it. To do so, you must use a selector line (see below). That selector
+line includes the channel name plus an $ sign in front of it. A sample might be:<br>
+<br>
+*.* $mychannel<br>
+<br>
+In its current form, output channels primarily provide the ability to size-limit
+an output file. To do so, specify a maximum size. When this size is reachead,
+rsyslogd will execute the action-on-max-size command and then reopen the file
+and retry. The command should be something like a log rotation script or a
+similar thing.</p>
+<p>If there is no action-on-max-size command or the command did not resolve the
+situation, the file is closed and never reopened by rsyslogd (except, of course,
+by huping it). This logic was integrated when we first experienced severe issues
+with files larger 2gb, which could lead to rsyslogd dumping core. In such cases,
+it is more appropriate to stop writing to a single file. Meanwhile, rsyslogd has
+been fixed to support files larger 2gb, but obviously only on file systems and
+operating system versions that do so. So it can still make sense to enforce a
+2gb file size limit.</p>
+<h2>Filter Conditions</h2>
+<p>Rsyslog offers two different types &quot;filter conditions&quot;:</p>
+<ul>
+ <li>&quot;traditional&quot; severity and facility based selectors</li>
+ <li>property-based filters</li>
+</ul>
+<h3>Blocks</h3>
+<p>Rsyslogd supports BSD-style blocks inside rsyslog.conf. Each block of lines
+is separated from the previous block by a program or hostname specification. A
+block will only log messages corresponding to the most recent program and
+hostname specifications given. Thus, a block which selects ‘ppp’ as the program,
+directly followed by a block that selects messages from the hostname ‘dialhost’,
+then the second block will only log messages from the ppp program on dialhost.
+</p>
+<p>A program specification is a line beginning with ‘!prog’ and the following
+blocks will be associated with calls to syslog from that specific program. A
+program specification for ‘foo’ will also match any message logged by the kernel
+with the prefix ‘foo: ’. A hostname specification of the form ‘+hostname’ and
+the following blocks will be applied to messages received from the specified
+hostname. Alternatively, a hostname specification ‘-hostname’ causes the
+following blocks to be applied to messages from any host but the one specified.
+If the hostname is given as ‘@’, the local hostname will be used. (NOT YET
+IMPLEMENTED) A program or hostname specification may be reset by giving the
+program or hostname as ‘*’.</p>
+<p>Please note that the &quot;#!prog&quot;, &quot;#+hostname&quot; and &quot;#-hostname&quot; syntax available
+in BSD syslogd is not supported by rsyslogd. By default, no hostname or program
+is set.</p>
+<h3>Selectors</h3>
+<p><b>Selectors are the traditional way of filtering syslog messages.</b> They
+have been kept in rsyslog with their orginal syntax, because it is well-known,
+highly effective and also needed for compatibility with stock syslogd
+configuration files. If you just need to filter based on priority and facility,
+you should do this with selector lines. They are <b>not</b> second-class
+citicens in rsyslog and offer the best performance for this job.</p>
+<p>The selector field itself again consists of two parts, a facility and a
+priority, separated by a period (``.''). Both parts are case insenstive and can
+also be specified as decimal numbers, but don't do that, you have been warned.
+Both facilities and priorities are described in rsyslog(3). The names mentioned
+below correspond to the similar LOG_-values in /usr/include/rsyslog.h.<br><br>The facility is one of the following keywords: auth, authpriv, cron, daemon,
+kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and
+local0 through local7. The keyword security should not be used anymore and mark
+is only for internal use and therefore should not be used in applications.
+Anyway, you may want to specify and redirect these messages here. The facility
+specifies the subsystem that produced the message, i.e. all mail programs log
+with the mail facility (LOG_MAIL) if they log using syslog.<br><br>Please note that the upcoming next syslog-RFC specifies many more facilities.
+Support for them will be added in a future version of rsyslog, which might
+require changes to existing configuration files.<br><br>The priority is one of the following keywords, in ascending order: debug, info,
+notice, warning, warn (same as warning), err, error (same as err), crit, alert,
+emerg, panic (same as emerg). The keywords error, warn and panic are deprecated
+and should not be used anymore. The priority defines the severity of the message<br>
+<br>The behavior of the original BSD syslogd is that all messages of the specified
+priority and higher are logged according to the given action. Rsyslogd behaves the same, but has some extensions.<br><br>In addition to the above mentioned names the rsyslogd(8) understands the
+following extensions: An asterisk (``*'') stands for all facilities or all
+priorities, depending on where it is used (before or after the period). The
+keyword none stands for no priority of the given facility.<br><br>You can specify multiple facilities with the same priority pattern in one
+statement using the comma (``,'') operator. You may specify as much facilities
+as you want. Remember that only the facility part from such a statement is
+taken, a priority part would be skipped.</p>
+<p>Multiple selectors may be specified for a single action using the semicolon
+(``;'') separator. Remember that each selector in the selector field is capable
+to overwrite the preceding ones. Using this behavior you can exclude some
+priorities from the pattern.</p>
+<p>Rsyslogd has a syntax extension to the original BSD source, that makes its
+use more intuitively. You may precede every priority with an equation sign
+(``='') to specify only this single priority and not any of the above. You may
+also (both is valid, too) precede the priority with an exclamation mark (``!'')
+to ignore all that priorities, either exact this one or this and any higher
+priority. If you use both extensions than the exclamation mark must occur before
+the equation sign, just use it intuitively.</p>
+<h3>Property-Based Filters</h3>
+<p>Property-based filters are unique to rsyslogd. They allow to filter on any
+property, like HOSTNAME, syslogtag and msg. A list of all currently-supported
+properties can be found in the <a href="property_replacer.html">property
+replacer documentation</a> (but keep in mind that only the properties, not the
+replacer is supported). With this filter, each properties can be checked against
+a specified value, using a specified compare operation. Currently, there is only
+a single compare operation (contains) available, but additional operations will be added in the
+future.</p>
+<p>A property-based filter must start with a colon in column 0. This tells
+rsyslogd that it is the new filter type. The colon must be followed by the
+property name, a comma, the name of the compare operation to carry out, another
+comma and then the value to compare against. This value must be quoted. There
+can be spaces and tabs between the commas. Property names and compare operations
+are case-sensitive, so &quot;msg&quot; works, while &quot;MSG&quot; is an invalid property name. In
+brief, the syntax is as follows:</p>
+<p><code><b>:property, [!]compare-operation, &quot;value&quot;</b></code></p>
+<p>The following <b>compare-operations</b> are currently supported:</p>
+<table border="1" width="100%" id="table1">
+ <tr>
+ <td>contains</td>
+ <td>Checks if the string provided in value is contained in the property.
+ There must be an exact match, wildcards are not supported.</td>
+ </tr>
+ <tr>
+ <td>isequal</td>
+ <td>Compares the &quot;value&quot; string provided and the property contents.
+ These two values must be exactly equal to match. The difference to
+ contains is that contains searchs for the value anywhere inside the
+ property value, whereas all characters must be identical for isequal. As
+ such, isequal is most useful for fields like syslogtag or FROMHOST,
+ where you probably know the exact contents.</td>
+ </tr>
+ <tr>
+ <td>startswith</td>
+ <td>Checks if the value is found exactly at the beginning of the
+ property value. For example, if you search for &quot;val&quot; with<p><code><b>:msg,
+ startswith, &quot;val&quot;</b></code></p>
+ <p>it will be a match if msg contains &quot;values are in this message&quot; but
+ it won't match if the msg contains &quot;There are values in this message&quot;
+ (in the later case, contains would match). Please note that &quot;startswith&quot;
+ is by far faster than regular expressions. So even once they are
+ implemented, it can make very much sense (performance-wise) to use &quot;startswith&quot;.</td>
+ </tr>
+ <tr>
+ <td>regex</td>
+ <td>Compares the property against the provided regular expression.</td>
+ </tr>
+</table>
+<p>You can use the bang-character (!) immediately in front of a
+compare-operation, the outcome of this operation is negated. For example, if msg
+contains &quot;This is an informative message&quot;, the following sample would not match:</p>
+<p><code><b>:msg, contains, &quot;error&quot;</b></code></p>
+<p>but this one matches:</p>
+<p><code><b>:msg, !contains, &quot;error&quot;</b></code></p>
+<p>Using negation can be useful if you would like to do some generic processing
+but exclude some specific events. You can use the discard action in conjunction
+with that. A sample would be:</p>
+<p><code><b>*.* /var/log/allmsgs-including-informational.log<br>
+:msg, contains, &quot;informational&quot;&nbsp; <font color="#FF0000" size="4">~</font>
+<br>*.* /var/log/allmsgs-but-informational.log</b></code></p>
+<p>Do not overlook the red tilde in line 2! In this sample, all messages are
+written to the file allmsgs-including-informational.log. Then, all messages
+containing the string &quot;informational&quot; are discarded. That means the config file
+lines below the &quot;discard line&quot; (number 2 in our sample) will not be applied to
+this message. Then, all remaining lines will also be written to the file
+allmsgs-but-informational.log.</p>
+<p><b>Value</b> is a quoted string. It supports some escape sequences:</p>
+<p>\&quot; - the quote character (e.g. &quot;String with \&quot;Quotes\&quot;&quot;)<br>
+\\ - the backslash character (e.g. &quot;C:\\tmp&quot;)</p>
+<p>Escape sequences always start with a backslash. Additional escape sequences
+might be added in the future. Backslash characters <b>must</b> be escaped. Any
+other sequence then those outlined above is invalid and may lead to
+unpredictable results.</p>
+<p>Probably, &quot;msg&quot; is the most prominent use case of property based filters. It
+is the actual message text. If you would like to filter based on some message
+content (e.g. the presence of a specific code), this can be done easily by:</p>
+<p><code><b>:msg, contains, &quot;ID-4711&quot;</b></code></p>
+<p>This filter will match when the message contains the string &quot;ID-4711&quot;. Please
+note that the comparison is case-sensitive, so it would not match if &quot;id-4711&quot;
+would be contained in the message.</p>
+<p>Getting property-based filters right can sometimes be challenging. In order
+to help you do it with as minimal effort as possible, rsyslogd spits out debug
+information for all property-based filters during their evaluation. To enable
+this, run rsyslogd in foreground and specify the &quot;-d&quot; option.</p>
+<p>Boolean operations inside property based filters (like 'message contains
+&quot;ID17&quot; or message contains &quot;ID18&quot;') are currently not supported
+(except for &quot;not&quot; as outlined above). Please note
+that while it is possible to query facility and severity via property-based filters,
+it is far more advisable to use classic selectors (see above) for those
+cases.</p>
+<h2>ACTIONS</h2>
+<p>The action field of a rule describes what to do with the message. In general,
+message content is written to a kind of &quot;logfile&quot;. But also other actions might
+be done, like writing to a database table or forwarding to another host.<br>
+<br>
+Templates can be used with all actions. If used, the specified template is used
+to generate the message content (instead of the default template). To specify a
+template, write a semicolon after the action value immediately followed by the
+template name.<br>
+<br>
+Beware: templates MUST be defined BEFORE they are used. It is OK to define some
+templates, then use them in selector lines, define more templates and use use
+them in the following selector lines. But it is NOT permitted to use a template
+in a selector line that is above its definition. If you do this, the action will be ignored.</p>
+<p><b>You can have multiple actions for a single selector </b>&nbsp;(or more
+precisely a single filter of such a selector line). Each action must be on its
+own line and the line must start with an ampersand ('&amp;') character and have no
+filters. An example would be</p>
+<p><code><b>*.=crit rger<br>
+&amp; root<br>
+&amp; /var/log/critmsgs</b></code></p>
+<p>These three lines send critical messages to the usrs rger and root and also
+store them in /var/log/critmsgs. <b>Using multiple actions per selector is</b>
+convenient and also <b>offers a performance benefit</b>. As the filter needs to
+be evaluated only once, there is less computation required to process the
+directive compared to the otherwise-equal config directives below:</p>
+<p><code><b>*.=crit rger<br>
+*.=crit root<br>
+*.=crit /var/log/critmsgs</b></code></p>
+<p>&nbsp;</p>
+<h3>Regular File</h3>
+<p>Typically messages are logged to real files. The file has to be specified with
+full pathname, beginning with a slash &quot;/''.<br>
+<br>
+You may prefix each entry with the minus ``-'' sign to omit syncing the file
+after every logging. Note that you might lose information if the system crashes
+right behind a write attempt. Nevertheless this might give you back some
+performance, especially if you run programs that use
+logging in a very verbose manner.</p>
+<p>If your system is connected to a reliable UPS and you receive lots of log
+data (e.g. firewall logs), it might be a very good idea to turn of
+syncing by specifying the &quot;-&quot; in front of the file name. </p>
+<p><b>The filename can be either static </b>(always the same) or <b>dynamic</b>
+(different based on message received). The later is useful if you would
+automatically split messages into different files based on some message
+criteria. For example, dynamic file name selectors allow you to split messages
+into different files based on the host that sent them. With dynamic file names,
+everything is automatic and you do not need any filters. </p>
+<p>It works via the template system. First, you define a template for the file
+name. An example can be seen above in the description of template. We will use
+the &quot;DynFile&quot; template defined there. Dynamic filenames are indicated by
+specifying a questions mark &quot;?&quot; instead of a slash, followed by the template
+name. Thus, the selector line for our dynamic file name would look as follows:</p>
+<p align="center">
+<code>*.* ?DynFile</code>
+</p>
+<p>That's all you need to do. Rsyslog will now automatically generate file names
+for you and store the right messages into the right files. Please note that the
+minus sign also works with dynamic file name selectors. Thus, to avoid syncing,
+you may use</p>
+<p align="center">
+<code>*.* -?DynFile</code></p>
+<p>And of course you can use templates to specify the output format:</p>
+<p align="center">
+<code>*.* ?DynFile;MyTemplate</code></p>
+<p><b>A word of caution:</b> rsyslog creates files as needed. So if a new host
+is using your syslog server, rsyslog will automatically create a new file for
+it. <b>However, directories are never created</b>. So if you use a dynamic
+directory name, you must make sure that all possible directories are created,
+otherwise the writes will fail. This restriction will most probably be removed
+in later versions of rsyslogd.</p>
+<h3>Named Pipes</h3>
+<p>This version of rsyslogd(8) has support for logging output to named pipes (fifos).
+A fifo or named pipe can be used as a destination for log messages by prepending
+a pipe symbol (``|'') to the name of the file. This is handy for debugging. Note
+that the fifo must be created with the mkfifo(1) command before rsyslogd(8) is
+started.</p>
+<h3>Terminal and Console</h3>
+<p>If the file you specified is a tty, special tty-handling is done, same with
+/dev/console.</p>
+<h3>Remote Machine</h3>
+<p>Rsyslogd provides full remote logging, i.e. is able to send messages to a
+remote host running rsyslogd(8) and to receive messages from remote hosts.
+Using this feature you're able to control all syslog messages on one host, if
+all other machines will log remotely to that. This tears down<br>
+administration needs.<br>
+<br>
+<b>Please note that this version of rsyslogd by default does NOT forward messages
+it has received from the network to another host. Specify the &quot;-h&quot; option to enable this.</b></p>
+<p>To forward messages to another host, prepend the hostname with the at sign (&quot;@&quot;).&nbsp;
+A single at sign means that messages will be forwarded via UDP protocol (the
+standard for syslog). If you prepend two at signs (&quot;@@&quot;), the messages will be
+transmitted via TCP. Please note that plain TCP based syslog is not officially
+standardized, but most major syslogds support it (e.g. syslog-ng or WinSyslog).
+The forwarding action indicator (at-sign) can be followed by one or more options.
+If they are given, they must be immediately (without a space) following the
+final at sign and be enclosed in parenthesis. The individual options must be
+separated by commas. The following options are right now defined:</p>
+<table border="1" width="100%" id="table2">
+ <tr>
+ <td>
+ <p align="center"><b>z&lt;number&gt;</b></td>
+ <td>Enable zlib-compression for the message. The &lt;number&gt; is the
+ compression level. It can be 1 (lowest gain, lowest CPU overhead) to 9 (maximum
+ compression, highest CPU overhead). The level can also be 0, which means
+ &quot;no compression&quot;. If given, the &quot;z&quot; option is ignored. So this does not
+ make an awful lot of sense. There is hardly a difference between level 1
+ and 9 for typical syslog messages. You can expect a compression gain
+ between 0% and 30% for typical messages. Very chatty messages may
+ compress up to 50%, but this is seldomly seen with typicaly traffic.
+ Please note that rsyslogd checks the compression gain. Messages with 60
+ bytes or less will never be compressed. This is because compression gain
+ is pretty unlikely and we prefer to save CPU cycles. Messags over that
+ size are always compressed. However, it is checked if there is a gain in
+ compression and only if there is, the compressed message is transmitted.
+ Otherwise, the uncompressed messages is transmitted. This saves the
+ receiver CPU cycles for decompression. It also prevents small message to
+ actually become larger in compressed form.<p><b>Please note that when a
+ TCP transport is used, compression will also turn on
+ syslog-transport-tls framing. See the &quot;o&quot; option for important
+ information on the implications.</b></p>
+ <p>Compressed messages are automatically detected and decompressed by
+ the receiver. There is nothing that needs to be configured on the
+ receiver side.</td>
+ </tr>
+ <tr>
+ <td>
+ <p align="center"><b>o</b></td>
+ <td><b>This option is experimental. Use at your own risk and only if you
+ know why you need it! If in doubt, do NOT turn it on.</b><p>This option
+ is only valid for plain TCP based transports. It selects a different
+ framing based on IETF internet draft syslog-transport-tls-06. This
+ framing offers some benefits over traditional LF-based framing. However,
+ the standardization effort is not yet complete. There may be changes in
+ upcoming versions of this standard. Rsyslog will be kept in line with
+ the standard. There is some chance that upcoming changes will be
+ incompatible to the current specification. In this case, all systems
+ using -transport-tls framing must be upgraded. There will be no effort
+ made to retain compatibility between different versions of rsyslog. The
+ primary reason for that is that it seems technically impossible to
+ provide compatibility between some of those changes. So you should take
+ this note very serious. It is not something we do not *like* to do (and
+ may change our mind if enough pepole beg...), it is something we most
+ probably *can not* do for technical reasons (aka: you can beg as much as
+ you like, it won't change anything...).</p>
+ <p>The most important implication is that compressed syslog messages via
+ TCP must be considered with care. Unfortunately, it is technically
+ impossible to transfer compressed records over traditional syslog plain
+ tcp transports, so you are left with two evil choices...</td>
+ </tr>
+</table>
+<p><br>
+The hostname may be followed by a colon and the destination port.</p>
+<p>The following is an example selector line with forwarding:</p>
+<p>*.*&nbsp;&nbsp;&nbsp; @@(o,z9)192.168.0.1:1470</p>
+<p>In this example, messages are forwarded via plain TCP with experimental
+framing and maximum compression to the host 192.168.0.1 at port 1470.</p>
+<p>*.* @192.168.0.1</p>
+<p>In the example above, messages are forwarded via UDP to the machine
+192.168.0.1, the destination port defaults to 514. Messages will not be
+compressed.</p>
+<h3>List of Users</h3>
+<p>Usually critical messages are also directed to ``root'' on that machine. You can
+specify a list of users that shall get the message by simply writing the login.
+You may specify more than one user by separating them with commas (&quot;,''). If
+they're logged in they get the message. Don't think a mail would be sent, that
+might be too late.</p>
+<h3>Everyone logged on</h3>
+<p>Emergency messages often go to all users currently online to notify them that
+something strange is happening with the system. To specify this wall(1)-feature
+use an asterisk (&quot;*'').</p>
+<h3>Database Table</h3>
+<p>This allows logging of the message to a database table. Currently, only MySQL
+databases are supported. By default, a MonitorWare-compatible schema is required
+for this to work. You can create that schema with the createDB.SQL file that
+came with the rsyslog package. You can also<br>
+use any other schema of your liking - you just need to define a proper template
+and assign this template to the action.<br>
+<br>
+The database writer is called by specifying a greater-then sign (&quot;&gt;&quot;) in front
+of the database connect information. Immediately after that<br>
+sign the database host name must be given, a comma, the database name, another
+comma, the database user, a comma and then the user's password. If a specific
+template is to be used, a semicolon followed by the template name can follow
+the connect information. This is as follows:<br>
+<br>
+&gt;dbhost,dbname,dbuser,dbpassword;dbtemplate</p>
+<p><b>Important: to use the database functionality, MySQL must be enabled in the
+config file</b> BEFORE the first database table action is used. This is done by
+placing the</p>
+<p><code><b>$ModLoad MySQL</b></code></p>
+<p>directive some place above the first use of the database write (we recommend
+doing at the the begining of the config file). <b>Please note that rsyslog must
+also have been built with MySQL support</b> (many packages do not do this by
+default).</p>
+<h3>Discard</h3>
+<p>If the discard action is carried out, the received message is immediately
+discarded. No further processing of it occurs. Discard has primarily been added
+to filter out messages before carrying on any further processing. For obvious
+reasons, the results of &quot;discard&quot; are depending on where in the configuration
+file it is being used. Please note that once a message has been discarded there
+is no way to retrive it in later configuration file lines.</p>
+<p>Discard can be highly effective if you want to filter out some annoying
+messages that otherwise would fill your log files. To do that, place the discard
+actions early in your log files. This often plays well with property-based
+filters, giving you great freedom in specifying what you do not want.</p>
+<p>Discard is just the single tilde character with no further parameters:</p>
+<p>~</p>
+<p>For example,</p>
+<p>*.*&nbsp;&nbsp; ~</p>
+<p>discards everything (ok, you can achive the same by not running rsyslogd at
+all...).</p>
+<h3>Output Channel</h3>
+<p>Binds an output channel definition (see there for details) to this action.
+Output channel actions must start with a $-sign, e.g. if you would like to bind
+your output channel definition &quot;mychannel&quot; to the action, use &quot;$mychannel&quot;.
+Output channels support template definitions like all all other actions.</p>
+<h3>Shell Execute</h3>
+<p>This executes a program in a subshell. The program is passed the
+template-generated message as the only command line parameter. Rsyslog waits
+until the program terminates and only then continues to run.</p>
+<p>^program-to-execute;template</p>
+<p>The program-to-execute can be any valid executable. It receives the template
+string as a single parameter (argv[1]).</p>
+<p><b>WARNING:</b> The Shell Execute action was added to serve an urgent need.
+While it is considered reasonable save when used with some thinking, its
+implications must be considered. The current implementation uses a system() call
+to execute the command. This is not the best way to do it (and will hopefully
+changed in further releases). Also, proper escaping of special characters is
+done to prevent command injection. However, attackers always find smart ways to
+circumvent escaping, so we can not say if the escaping applied will really safe
+you from all hassles. Lastly, rsyslog will wait until the shell command
+terminates. Thus, a program error in it (e.g. an infinite loop) can actually
+disable rsyslog. Even without that, during the programs run-time no messages are
+processed by rsyslog. As the IP stacks buffers are quickly overflowed, this
+bears an increased risk of message loss. You must be aware of these implications.
+Even though they are severe, there are several cases where the &quot;shell execute&quot;
+action is very useful. This is the reason why we have included it in its current
+form. To mitigate its risks, always a) test your program thoroughly, b) make
+sure its runtime is as short as possible (if it requires a longer run-time, you
+might want to spawn your own sub-shell asynchronously), c) apply proper
+firewalling so that only known senders can send syslog messages to rsyslog.
+Point c) is especially important: if rsyslog is accepting message from any hosts,
+chances are much higher that an attacker might try to exploit the &quot;shell execute&quot;
+action.</p>
+<h2>TEMPLATE NAME</h2>
+<p>Every ACTION can be followed by a template name. If so, that template is used
+for message formatting. If no name is given, a hard-coded default template is
+used for the action. There can only be one template name for each given action.
+The default template is specific to each action. For a description of what a
+template is and what you can do with it, see &quot;TEMPLATES&quot; at the top of this
+document.</p>
+<h2>EXAMPLES</h2>
+<p>Below are example for templates and selector lines. I hope they are
+self-explanatory. If not, please see www.monitorware.com/rsyslog/ for advise.</p>
+<h3>TEMPLATES</h3>
+<p>Please note that the samples are split across multiple lines. A template MUST
+NOT actually be split across multiple lines.<br>
+<br>
+A template that resambles traditional syslogd file output:<br>
+$template TraditionalFormat,&quot;%timegenerated% %HOSTNAME%<br>
+%syslogtag%%msg:::drop-last-lf%\n&quot;<br>
+<br>
+A template that tells you a little more about the message:<br>
+$template precise,&quot;%syslogpriority%,%syslogfacility%,%timegenerated%,%HOSTNAME%,<br>
+%syslogtag%,%msg%\n&quot;<br>
+<br>
+A template for RFC 3164 format:<br>
+$template RFC3164fmt,&quot;&lt;%PRI%&gt;%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%&quot;<br>
+<br>
+A template for the format traditonally used for user messages:<br>
+$template usermsg,&quot; XXXX%syslogtag%%msg%\n\r&quot;<br>
+<br>
+And a template with the traditonal wall-message format:<br>
+$template wallmsg,&quot;\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated%<br>
+<br>
+A template that can be used for the database write (please note the SQL<br>
+template option)<br>
+$template MySQLInsert,&quot;insert iut, message, receivedat values<br>
+('%iut%', '%msg:::UPPERCASE%', '%timegenerated:::date-mysql%')<br>
+into systemevents\r\n&quot;, SQL<br>
+<br>
+The following template emulates <a href="http://www.winsyslog.com/en/">WinSyslog</a>
+format (it's an <a href="http://www.adiscon.com/en/">Adiscon</a> format, you do
+not feel bad if you don't know it ;)). It's interesting to see how it takes
+different parts out of the date stamps. What happens is that the date stamp is
+split into the actual date and time and the these two are combined with just a
+comma in between them.<br>
+<br>
+$template WinSyslogFmt,&quot;%HOSTNAME%,%timegenerated:1:10:date-rfc3339%,<br>
+%timegenerated:12:19:date-rfc3339%,%timegenerated:1:10:date-rfc3339%,<br>
+%timegenerated:12:19:date-rfc3339%,%syslogfacility%,%syslogpriority%,<br>
+%syslogtag%%msg%\n&quot;</p>
+<h3>SELECTOR LINES</h3>
+<p># Store critical stuff in critical<br>
+#<br>
+*.=crit;kern.none /var/adm/critical<br>
+<br>
+This will store all messages with the priority crit in the file /var/adm/critical,
+except for any kernel message.<br>
+<br>
+<br>
+# Kernel messages are first, stored in the kernel<br>
+# file, critical messages and higher ones also go<br>
+# to another host and to the console. Messages to<br>
+# the host finlandia are forwarded in RFC 3164<br>
+# format (using the template defined above).<br>
+#<br>
+kern.* /var/adm/kernel<br>
+kern.crit @finlandia;RFC3164fmt<br>
+kern.crit /dev/console<br>
+kern.info;kern.!err /var/adm/kernel-info<br>
+<br>
+The first rule direct any message that has the kernel facility to the file /var/adm/kernel.<br>
+<br>
+The second statement directs all kernel messages of the priority crit and higher
+to the remote host finlandia. This is useful, because if the host crashes and
+the disks get irreparable errors you might not be able to read the stored
+messages. If they're on a remote host, too, you still can try to find out the
+reason for the crash.<br>
+<br>
+The third rule directs these messages to the actual console, so the person who
+works on the machine will get them, too.<br>
+<br>
+The fourth line tells rsyslogd to save all kernel messages that come with
+priorities from info up to warning in the file /var/adm/kernel-info. Everything
+from err and higher is excluded.<br>
+<br>
+<br>
+# The tcp wrapper loggs with mail.info, we display<br>
+# all the connections on tty12<br>
+#<br>
+mail.=info /dev/tty12<br>
+<br>
+This directs all messages that uses mail.info (in source LOG_MAIL | LOG_INFO) to
+/dev/tty12, the 12th console. For example the tcpwrapper tcpd(8) uses this as
+it's default.<br>
+<br>
+<br>
+# Store all mail concerning stuff in a file<br>
+#<br>
+mail.*;mail.!=info /var/adm/mail<br>
+<br>
+This pattern matches all messages that come with the mail facility, except for
+the info priority. These will be stored in the file /var/adm/mail.<br>
+<br>
+<br>
+# Log all mail.info and news.info messages to info<br>
+#<br>
+mail,news.=info /var/adm/info<br>
+<br>
+This will extract all messages that come either with mail.info or with news.info
+and store them in the file /var/adm/info.<br>
+<br>
+<br>
+# Log info and notice messages to messages file<br>
+#<br>
+*.=info;*.=notice;\<br>
+mail.none /var/log/messages<br>
+<br>
+This lets rsyslogd log all messages that come with either the info or the notice
+facility into the file /var/log/messages, except for all<br>
+messages that use the mail facility.<br>
+<br>
+<br>
+# Log info messages to messages file<br>
+#<br>
+*.=info;\<br>
+mail,news.none /var/log/messages<br>
+<br>
+This statement causes rsyslogd to log all messages that come with the info
+priority to the file /var/log/messages. But any message coming either with the
+mail or the news facility will not be stored.<br>
+<br>
+<br>
+# Emergency messages will be displayed using wall<br>
+#<br>
+*.=emerg *<br>
+<br>
+This rule tells rsyslogd to write all emergency messages to all currently logged
+in users. This is the wall action.<br>
+<br>
+<br>
+# Messages of the priority alert will be directed<br>
+# to the operator<br>
+#<br>
+*.alert root,rgerhards<br>
+<br>
+This rule directs all messages with a priority of alert or higher to the
+terminals of the operator, i.e. of the users ``root'' and ``rgerhards'' if
+they're logged in.<br>
+<br>
+<br>
+*.* @finlandia<br>
+<br>
+This rule would redirect all messages to a remote host called finlandia. This is
+useful especially in a cluster of machines where all syslog messages will be
+stored on only one machine.<br>
+<br>
+In the format shown above, UDP is used for transmitting the message. The
+destination port is set to the default auf 514. Rsyslog is also capable of using
+much more secure and reliable TCP sessions for message forwarding. Also, the
+destination port can be specified. To select TCP, simply add one additional @ in
+front of the host name (that is, @host is UPD, @@host is TCP). For example:<br>
+<br>
+<br>
+*.* @@finlandia<br>
+<br>
+To specify the destination port on the remote machine, use a colon followed by
+the port number after the machine name. The following forwards to port 1514 on
+finlandia:<br>
+<br>
+<br>
+*.* @@finlandia:1514<br>
+<br>
+This syntax works both with TCP and UDP based syslog. However, you will probably
+primarily need it for TCP, as there is no well-accepted port for this transport
+(it is non-standard). For UDP, you can usually stick with the default auf 514,
+but might want to modify it for security rea-<br>
+sons. If you would like to do that, it's quite easy:<br>
+<br>
+<br>
+*.* @finlandia:1514<br>
+<br>
+<br>
+<br>
+*.* &gt;dbhost,dbname,dbuser,dbpassword;dbtemplate<br>
+<br>
+This rule writes all message to the database &quot;dbname&quot; hosted on &quot;dbhost&quot;. The
+login is done with user &quot;dbuser&quot; and password &quot;dbpassword&quot;. The actual table
+that is updated is specified within the template (which contains the insert
+statement). The template is called &quot;dbtemplate&quot; in this case.</p>
+<p>:msg,contains,&quot;error&quot; @errorServer</p>
+<p>This rule forwards all messages that contain the word &quot;error&quot; in the msg part
+to the server &quot;errorServer&quot;. Forwarding is via UDP. Please note the colon in
+fron</p>
+<h2>CONFIGURATION FILE SYNTAX DIFFERENCES</h2>
+<p>Rsyslogd uses a slightly different syntax for its configuration file than the
+original BSD sources. Originally all messages of a specific priority and above
+were forwarded to the log file. The modifiers ``='', ``!'' and ``-'' were added
+to make rsyslogd more flexible and to use it in a more intuitive manner.<br>
+<br>
+The original BSD syslogd doesn't understand spaces as separators between the
+selector and the action field.<br>
+<br>
+When compared to syslogd from sysklogd package, rsyslogd offers additional
+<a href="features.html">features</a> (like template and database support). For obvious reasons, the syntax for
+defining such features is available
+in rsyslogd, only.<br>
+&nbsp;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rsyslog_mysql.html b/doc/rsyslog_mysql.html
new file mode 100644
index 0000000..41aced2
--- /dev/null
+++ b/doc/rsyslog_mysql.html
@@ -0,0 +1,240 @@
+<html><head>
+<title>Writing syslog Data to MySQL</title>
+<meta name="KEYWORDS" content="syslog, mysql, syslog to mysql, howto">
+</head>
+<body>
+<h1>Writing syslog messages to MySQL</h1>
+ <P><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a> (2005-08-02)</i></small></P>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to write
+<a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
+messages to a <a href="http://www.mysql.com">MySQL</a> database.</b> Having
+syslog messages in a database is often handy, especially when you intend to set
+up a front-end for viewing them. This paper describes an approach
+with <a href="http://www.rsyslog.com/">rsyslogd</a>, an alternative enhanced
+syslog daemon natively supporting MySQL. I describe the components needed
+to be installed and how to configure them.</i></p>
+<h2>Background</h2>
+<p>In many cases, syslog data is simply written to text files. This approach has
+some advantages, most notably it is very fast and efficient. However, data
+stored in text files is not readily accessible for real-time viewing and analysis.
+To do that, the messages need to be in a database. There are various
+ways to store syslog messages in a database. For example, some have the syslogd
+write text files which are later feed via a separate script into the database.
+Others have written scripts taking the data (via a pipe) from a
+non-database-aware syslogd and store them as they appear. Some others use
+database-aware syslogds and make them write the data directly to the database.
+In this paper, I use that &quot;direct write&quot; approach. I think it is superior,
+because the syslogd itself knows the status of the database connection and thus
+can handle it intelligently (well ... hopefully ;)). I use rsyslogd to acomplish
+this, simply because I have initiated the rsyslog project with
+database-awareness as one goal.</p>
+<p><b>One word of caution:</b> while message storage in the database provides an
+excellent foundation for interactive analysis, it comes at a cost. Database i/o
+is considerably slower than text file i/o. As such, directly writing to
+the database makes sense only if your message volume is low enough to allow a)
+the syslogd, b) the network, and c) the database server to catch
+up with it. Some time ago, I have written a paper on
+<a href="http://www.monitorware.com/Common/en/Articles/performance-optimizing-syslog-server.php">
+optimizing syslog server performance</a>. While this paper talks about
+Window-based solutions, the ideas in it are generic enough to apply here, too.
+So it might be worth reading if you anticipate medium high to high traffic. If you
+anticipate really high traffic (or very large traffic spikes), you should
+seriously consider forgetting about direct database writes - in my opinion, such
+a situation needs either a very specialised system or a different approach (the
+text-file-to-database approach might work better for you in this case).
+</p>
+<h2>Overall System Setup</h2>
+<P>In this paper, I concentrate on the server side. If you are thinking about
+interactive syslog message review, you probably want to centralize syslog. In
+such a scenario, you have multiple machines (the so-called clients) send their
+data to a central machine (called server in this context). While I expect such a
+setup to be typical when you are interested in storing messages in the database,
+I do not describe how to set it up. This is beyond the scope of this paper. If
+you search a little, you will probably find many good descriptions on how to
+centralize syslog. If you do that, it might be a good idea to do it securely, so
+you might also be interested in my paper on <a href="rsyslog_stunnel.html">
+ssl-encrypting syslog message transfer</a>.</P>
+<P>No matter how the messages arrive at the server, their processing is always the
+same. So you can use this paper in combination with any description for
+centralized syslog reporting.</P>
+<P>As I already said, I use rsyslogd on the server. It has intrinsic support for
+talking to MySQL databases. For obvious reasons, we also need an instance of
+MySQL running. To keep us focussed, the setup of MySQL itself is also beyond the
+scope of this paper. I assume that you have successfully installed MySQL and
+also have a front-end at hand to work with it (for example,
+<a href="http://www.phpmyadmin.net/">phpMyAdmin</a>). Please make sure that this
+is installed, actually working and you have a basic understanding of how to
+handle it.</P>
+<h2>Setting up the system</h2>
+<p>You need to download and install rsyslogd first. Obtain it from the
+<a href="http://www.rsyslog.com/">rsyslog site</a>. Make sure that you disable
+stock syslogd, otherwise you will experience some difficulties.</p>
+<p>It is important to understand how rsyslogd talks to the database. In rsyslogd,
+there is the concept of &quot;templates&quot;. Basically, a template is a string that
+includes some replacement characters, which are called &quot;properties&quot; in rsyslog.
+Properties are accessed via the &quot;<a href="property_replacer.html">Property
+Replacer</a>&quot;. Simply said, you access properties by including their name
+between percent signs inside the template. For example, if the syslog message is
+&quot;Test&quot;, the template &quot;%msg%&quot; would be expanded to &quot;Test&quot;. Rsyslogd supports
+sending template text as a SQL statement to MySQL. As such, the template must be
+a valid SQL statement. There is no limit in what the statement might be, but
+there are some obvious and not so obvious choices. For example, a template &quot;drop
+table xxx&quot; is possible, but does not make an awful lot of sense. In practice,
+you will always use an &quot;insert&quot; statment inside the template.</p>
+<p>An example: if you would just like to store the msg part of the full syslog
+message, you have probably created a table &quot;syslog&quot; with a single column &quot;message&quot;.
+In such a case, a good template would be &quot;insert into syslog(message) values ('%msg%')&quot;.
+With the example above, that would be expanded to &quot;insert into syslog(message)
+values('Test')&quot;. This expanded string is then sent to the database. It's that
+easy, no special magic. The only thing you must ensure is that your template
+expands to a proper SQL statement and that this statement matches your database
+design.</p>
+<p>Does that mean you need to create database schema yourself and also must
+fully understand rsyslogd's properties? No, that's not needed. Because we
+anticipated that folks are probably more interested in getting things going instead
+of designing them from scratch. So we have provided a default schema as well
+as build-in support for it. This schema also offers an additional
+benefit: rsyslog is part of <a href="http://www.adiscon.com/en/">Adiscon</a>'s
+<a href="http://www.monitorware.com/en/">MonitorWare product line</a> (which
+includes open source and closed source members). All of these tools share the
+same default schema and know how to operate on it. For this reason, the default
+schema is also called the &quot;MonitorWare Schema&quot;. If you use it, you can simply
+add <a href="http://www.phplogcon.org/">phpLogCon, a GPLed syslog web interface</a>,
+to your system and have instant interactive access to your database. So there
+are some benefits in using the provided schema.</p>
+<p>The schema definition is contained in the file &quot;createDB.sql&quot;. It comes with
+the rsyslog package. Review it to check that the database name is acceptable for
+you. Be sure to leave the table and field names unmodified, because
+otherwise you need to customize rsyslogd's default sql template, which we do not
+do
+in this paper. Then, run the script with your favourite MySQL tool. Double-check
+that the table was successfully created.</p>
+<p>Next, we need to tell rsyslogd to write data to the database. As we use
+the default schema, we do NOT need to define a template for this. We can use the
+hardcoded one (rsyslogd handles the proper template linking). So all we need to
+do is add a simple selector line to /etc/rsyslog.conf:</p>
+<blockquote>
+ <p><code>*.*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &gt;database-server,database-name,database-userid,database-password</code></p>
+</blockquote>
+<p>In many cases, MySQL will run on the local machine. In this case, you can
+simply use &quot;127.0.0.1&quot; for <i>database-server</i>. This can be especially
+advisable, if you do not need to expose MySQL to any process outside of the
+local machine. In this case, you can simply bind it to 127.0.0.1, which provides
+a quite secure setup. Of course, also supports remote MySQL instances. In that
+case, use the remote server name (e.g. mysql.example.com) or IP-address. The <i>
+database-name</i> by default is &quot;syslog&quot;. If you have modified the default, use
+your name here. <i>Database-userid</i> and <i>-password</i> are the credentials
+used to connect to the database. As they are stored in clear text in
+rsyslog.conf, that user should have only the least possible privileges. It is
+sufficient to grant it INSERT privileges to the systemevents table, only. As a
+side note, it is strongly advisable to make the rsyslog.conf file readable by
+root only - if you make it world-readable, everybody could obtain the password
+(and eventually other vital information from it). In our example, let's assume
+you have created a MySQL user named &quot;syslogwriter&quot; with a password of
+&quot;topsecret&quot; (just to say it bluntly: such a password is NOT a good idea...). If
+your MySQL database is on the local machine, your rsyslog.conf line might look
+like in this sample:</p>
+<blockquote>
+ <p><code>*.*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &gt;127.0.0.1,syslog,syslogwriter,topsecret</code></p>
+</blockquote>
+<p>Save rsyslog.conf, restart rsyslogd - and you should see syslog messages
+being stored in the &quot;systemevents&quot; table!</p>
+<p>The example line stores every message to the database. Especially if you have
+a high traffic volume, you will probably limit the amount of messages being
+logged. This is easy to acomplish: the &quot;write database&quot; action is just a regular
+selector line. As such, you can apply normal selector-line filtering. If, for
+example, you are only interested in messages from the mail subsystem, you can
+use the following selector line:</p>
+<blockquote>
+ <p><code>mail.*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &gt;127.0.0.1,syslog,syslogwriter,topsecret</code></p>
+</blockquote>
+<p>Review the <a href="rsyslog_conf.html">rsyslog.conf</a> documentation for
+details on selector lines and their filtering.</p>
+<p><b>You have now completed everything necessary to store syslog messages to
+the MySQL database.</b> If you would like to try out a front-end, you might want
+to look at <a href="http://www.phplogcon.org/">phpLogCon</a>, which displays
+syslog data in a browser. As of this writing, phpLogCon is not yet a powerful
+tool, but it's open source, so it might be a starting point for your own
+solution.</p>
+<h2>On Reliability...</h2>
+<p><b>This section needs updating. You can now solve the issue with failover
+database servers. Read the <a href="rsyslog_conf.html">rsyslog.conf </a>doc on
+that</b>.</p>
+<p>Rsyslogd writes syslog messages directly to the database. This implies that
+the database must be available at the time of message arrival. If the database
+is offline, no space is left or something else goes wrong - rsyslogd can not
+write the database record. If rsyslogd is unable to store a message, it performs
+one retry. This is helpful if the database server was restarted. In this case,
+the previous connection was broken but a reconnect immediately succeeds. However,
+if the database is down for an extended period of time, an immediate retry does
+not help. While rsyslogd could retry until it finally succeeds, that would have
+negative impact. Syslog messages keep coming in. If rsyslogd would be busy
+retrying the database, it would not be able to process these messages.
+Ultimately, this would lead to loss of newly arrived messages.</p>
+<p>In most cases, rsyslogd is configured not only to write to the database but
+to perform other actions as well. In the always-retry scenario, that would mean
+no other actions would be carried out. As such, the design of rsyslogd is
+limited to a single retry. If that does not succeed, the current message is will
+not be written to the database and the MySQL database writer be suspended for a
+short period of time. Obviously, this leads to the loss of the current message
+as well as all messages received during the suspension period. But they are only
+lost in regard to the database, all other actions are correctly carried out.
+While not perfect, we consider this to be a better approach then the potential
+loss of all messages in all actions.</p>
+<p><b>In short: try to avoid database downtime if you do not want to experience
+message loss.</b></p>
+<p>Please note that this restriction is not rsyslogd specific. All approaches to
+real-time database storage share this problem area.</p>
+<h2>Conclusion</h2>
+<P>With minimal effort, you can use rsyslogd to write syslog messages to a MySQL
+database. Once the messages are arrived there, you can interactivley review and
+analyse them. In practice, the messages are also stored in text files for
+longer-term archival and the databases are cleared out after some time (to avoid
+becoming too slow). If you expect an extremely high syslog message volume,
+storing it in real-time to the database may outperform your database server. In
+such cases, either filter out some messages or think about alternate approaches
+involving non-real-time database writing (beyond the scope of this paper).</P>
+<P>The method outlined in this paper provides an easy to setup and maintain
+solution for most use cases, especially with low and medium syslog message
+volume (or fast database servers).</P>
+<h3>Feedback Requested</h3>
+<P>I would appreciate feedback on this paper. If you have additional ideas,
+comments or find bugs, please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
+<h2>References and Additional Material</h2>
+<ul>
+ <li><a href="http://www.rsyslog.com">www.rsyslog.com</a> - the rsyslog site</li>
+ <li>
+ <a href="http://www.monitorware.com/Common/en/Articles/performance-optimizing-syslog-server.php">
+ Paper on Syslog Server Optimization</a></li>
+</ul>
+<h2>Revision History</h2>
+<ul>
+ <li>2005-08-02 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> *
+ initial version created</li>
+ <li>2005-08-03 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * added references to demo site</li>
+ <li>2007-06-13 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * removed demo site - was torn down because too expensive for usage count</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2005-2007
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+and <a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p>Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU Free Documentation License, Version 1.2 or any later
+version published by the Free Software Foundation; with no Invariant Sections,
+no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be
+viewed at <a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rsyslog_packages.html b/doc/rsyslog_packages.html
new file mode 100644
index 0000000..32d282f
--- /dev/null
+++ b/doc/rsyslog_packages.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+<title>rsyslog precompiled packages (RPM and such...)</title>
+</head>
+<body>
+<h1>rsyslog packages</h1>
+<p><b>Thanks to some volunteers, rsyslog is also available in package form on
+some distributions.</b> All available packages are listed below. If you would
+like to maintain a package for a new distribution, please mail me at
+<a href="mailto:rgerhards@adiscon.com">rgerhards@adiscon.com</a>. Any help is *deeply*
+appreciated. While I create the core daemon, the package maintainers are really
+filling it with life, making it available to the average user. I am very
+grateful for that!</p>
+<p>This list has last been updated on 2007-07-06 by
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>.
+New packages may appear at any time, so be sure to check this page whenever you
+need a new one.</p>
+<p>Red Hat has recently begun to build RPMs for rsyslog. The URL changes, but a
+good place to look for them is at
+<a href="http://freshmeat.net/projects/rsyslog/">freshmeat's rsyslog info page</a>.
+Please note that the Red Hat RPMs do currently <b>not</b> include MySQL
+functionality. If you need that, you need to compile from the source tarball
+(which honestly is quite easy).</p>
+<h2>BSD</h2>
+<p>Give <a href="http://www.freshports.org/sysutils/rsyslog/">
+http://www.freshports.org/sysutils/rsyslog/</a> a try.</p>
+<h2>CentOS 4.3</h2>
+<a href="http://www.se-community.com/~james/rsyslog/">
+http://www.se-community.com/~james/rsyslog/</a></p>
+<p>Maintained by<b> James Bergamin.</b></p>
+<h2>Almost any Linux</h2>
+<p><b>Bennet Todd</b> maintains packages that should work on almost any Linux.
+He keeps a current i386 tree. There is also a PPC tree, but that one is not paid
+much attention for (anyhow, it is known to typically work well, too).</p>
+<p>Please visit <a href="http://bent.latency.net/bent/">
+http://bent.latency.net/bent/</a>, select the relevant tree and then do a search
+for rsyslog.</p>
+
+</body>
+</html>
diff --git a/doc/rsyslog_php_syslog_ng.html b/doc/rsyslog_php_syslog_ng.html
new file mode 100644
index 0000000..9e72275
--- /dev/null
+++ b/doc/rsyslog_php_syslog_ng.html
@@ -0,0 +1,151 @@
+<html><head>
+<title>Using php-syslog-ng with rsyslog</title>
+<meta name="KEYWORDS" content="syslog, php-syslog-ng, mysql, howto, rsyslog">
+</head>
+<body>
+<h1>Using php-syslog-ng with rsyslog</h1>
+ <P><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a> (2005-08-04)</i></small></P>
+<p><b>Note: it has been reported that this guide is somewhat outdated. Please
+use with care. </b></p>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to use
+<a href="http://www.vermeer.org/projects/php-syslog-ng">php-syslog-ng</a> with
+<a href="http://www.rsyslog.com/">rsyslogd</a>. </b>&nbsp;Php-syslog-ng is a
+popular web interface to syslog data. Its name stem from the fact that it
+usually picks up its data from a database created by
+<a href="http://www.balabit.com/products/syslog_ng/">syslog-ng</a> and some
+helper scripts. However, there is nothing syslog-ng specific in the database.
+With rsyslogd's high customizability, it is easy to write to a syslog-ng like
+schema. I will tell you how to do this, enabling you to use php-syslog-ng as a
+front-end for rsyslogd - or save the hassle with syslog-ng database
+configuration and simply go ahead and use rsyslogd instead.</i></p>
+<h2>Overall System Setup</h2>
+<p>The setup is pretty straightforward. Basically, php-syslog-ng's interface to
+the syslogd is the database. We use the schema that php-syslog-ng expects and
+make rsyslogd write to it in its format. Because of this, php-syslog-ng does not
+even know there is no syslog-ng present.</p>
+<h2>Setting up the system</h2>
+<p>For php-syslog-ng, you can follow its usual setup instructions. Just skip any
+steps refering to configure syslog-ng. Make sure you create the database schema
+in <a href="http://www.mysql.com/">MySQL</a>. As of this writing, the expected schema can be created via this script:</p>
+<blockquote>
+ <code>CREATE DATABASE syslog<br>
+ !<br>
+ USE syslog<br>
+ !<br>
+ CREATE TABLE logs (<br>
+ host varchar(32) default NULL,<br>
+ facility varchar(10) default NULL,<br>
+ priority varchar(10) default NULL,<br>
+ level varchar(10) default NULL,<br>
+ tag varchar(10) default NULL,<br>
+ date date default NULL,<br>
+ time time default NULL,<br>
+ program varchar(15) default NULL,<br>
+ msg text,<br>
+ seq int(10) unsigned NOT NULL auto_increment,<br>
+ PRIMARY KEY (seq),<br>
+ KEY host (host),<br>
+ KEY seq (seq),<br>
+ KEY program (program),<br>
+ KEY time (time),<br>
+ KEY date (date),<br>
+ KEY priority (priority),<br>
+ KEY facility (facility)<br>
+ ) TYPE=MyISAM;</code>
+</blockquote>
+<p>Please note that at the time you are reading this paper, the schema might have changed.
+Check for any differences. As we customize rsyslogd to the schema, it is vital
+to have the correct one. If this paper is outdated,
+<a href="mailto:rgerhards@adiscon.com">let me know</a> so that I can fix it.</p>
+<p>Once this schema is created, we simply instruct rsyslogd to store received
+data in it. I wont go into too much detail here. If you are interested in some
+more details, you might find my paper &quot;<a href="rsyslog_mysql.html">Writing
+syslog messages to MySQL</a>&quot; worth reading. For this article, we simply modify
+<a href="rsyslog_conf.html">rsyslog.conf </a>so that it writes to the database.
+That is easy. Just these two lines are needed:</p>
+<blockquote>
+ <code><font color="green">$template syslog-ng,&quot;insert into logs(host, facility, priority, tag, date,
+ time, msg) values ('%HOSTNAME%', %syslogfacility%, %syslogpriority%,
+ '%syslogtag%',&nbsp; '%timereported:::date-mysql%', '%timereported:::date-mysql%',
+ '%msg%')&quot;, SQL</font> <br>
+ <font color="red">*.*&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&gt;mysql-server,syslog,user,pass;syslog-ng</font>
+ </code>
+</blockquote>
+<p>These are just <b>two</b> lines. I have color-coded them so that you see what
+belongs together (the colors have no other meaning). The green line is the
+actual SQL statement being used to take care of the syslog-ng schema. Rsyslogd
+allows you to fully control the statement sent to the database. This allows you
+to write to any database format, including your homegrown one (if you so desire).
+Please note that there is a small inefficiency in our current usage: the
+ <code><font color="green">'%timereported:::date-mysql%'</font></code>&nbsp;
+property is used for both the time and the date (if you wonder about what all
+these funny characters mean, see the <a href="property_replacer.html">rsyslogd
+property replacer manual</a>) . We could have extracted just the date and time
+parts of the respective properties. However, this is more complicated and also
+adds processing time to rsyslogd's processing (substrings must be extracted). So we take a full mysql-formatted timestamp and supply it to MySQL. The sql engine in turn
+discards the unneeded part. It works pretty well. As of my understanding, the
+inefficiency of discarding the unneeded part in MySQL is lower than the
+effciency gain from using the full timestamp in rsyslogd. So it is most probably
+the best solution.</p>
+<p>Please note that rsyslogd knows two different timestamp properties: one is
+timereported, used here. It is the timestamp from the message itself. Sometimes
+that is a good choice, in other cases not. It depends on your environment. The other one is the timegenerated
+property. This is the time when rsyslogd received the message. For obvious
+reasons, that timestamp is consistent, even when your devices are in multiple
+time zones or their clocks are off. However, it is not &quot;the real thing&quot;. It's
+your choice which one you prefer. If you prefer timegenerated ... simply use it
+;)</p>
+<p>The line in red tells rsyslogd which messages to log and where to store it.
+The &quot;*.*&quot; selects all messages. You can use standard syslog selector line filters here if
+you do not like to see everything in your database. The &quot;&gt;&quot; tells
+rsyslogd that a MySQL connection
+must be established. Then, &quot;mysql-server&quot; is the name or IP address of the
+server machine, &quot;syslog&quot; is the database name (default from the schema) and &quot;user&quot;
+and &quot;pass&quot; are the logon credentials. Use a user with low privileges, insert into the
+logs table is sufficient. &quot;syslog-ng&quot; is the template name and tells rsyslogd to
+use the SQL statement shown above.</p>
+<p>Once you have made the changes, all you need to do is reload (or HUP)
+rsyslogd. Then, you should see syslog messages flow into your database - and
+show up in php-syslog-ng.</p>
+<h2>Conclusion</h2>
+<P>With minumal effort, you can use php-syslog-ng together with rsyslogd. For
+those unfamiliar with syslog-ng, this configuration is probably easier to set up
+then switching to syslog-ng. For existing rsyslogd users, php-syslog-ng might be a nice
+add-on to their logging infrastructure.</P>
+<P>Please note that the <a href="http://www.monitorware.com/en/">MonitorWare family</a> (to which rsyslog belongs) also
+offers a web-interface: <a href="http://www.phplogcon.org/">phpLogCon</a>. At the time of this writing, phpLogCon's code
+is by far not as clean as I would like it to be. Also the user-interface is
+definitely not as intutive as pp-syslog-ng. From a functionality point of view,
+however, I think it already is a bit ahead. So you might
+consider using it. I have set up a <a href="http://demo.rsyslog.com/">demo server</a>.,
+You can have a peek at it
+without installing anything.</P>
+<h2>Feedback Requested</h2>
+<P>I would appreciate feedback on this paper. If you have additional ideas,
+comments or find bugs, please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
+<h2>References and Additional Material</h2>
+<ul>
+ <li><a href="http://www.vermeer.org/projects/php-syslog-ng">php-syslog-ng</a></li>
+</ul>
+<h2>Revision History</h2>
+<ul>
+ <li>2005-08-04 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> *
+ initial version created</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2005
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+and <a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p>Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU Free Documentation License, Version 1.2 or any later
+version published by the Free Software Foundation; with no Invariant Sections,
+no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be
+viewed at <a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rsyslog_recording_pri.html b/doc/rsyslog_recording_pri.html
new file mode 100644
index 0000000..c84d47f
--- /dev/null
+++ b/doc/rsyslog_recording_pri.html
@@ -0,0 +1,134 @@
+<html><head>
+<title>Writing syslog Data to MySQL</title>
+<meta name="KEYWORDS" content="syslog, mysql, syslog to mysql, howto">
+</head>
+<body>
+<h1>Recording the Priority of Syslog Messages</h1>
+ <P><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a> (2007-06-18)</i></small></P>
+<h2>Abstract</h2>
+<p><i><b>The so-called priority (PRI) is very important in syslog messages,
+because almost all filtering in syslog.conf is based on it.</b> However, many
+syslogds (including the Linux stock sysklogd) do not provide a way to record
+that value. In this article, I'll give a brief overview of how PRI can be
+written to a log file.</i></p>
+<h2>Background</h2>
+<p>The PRI value is a combination of so-called severity and facility. The
+facility indicates where the message originated from (e.g. kernel, mail
+subsystem) while the severity provides a glimpse of how important the message
+might be (e.g. error or informational). Be careful with these values: they are
+in no way consistent accross applications (especially severity). However, they
+still form the basis of most filtering in syslog.conf. For example, the
+directive (aka &quot;selector line)</p>
+<p align="center">
+<code>mail.* /var/log/mail.log</code>
+</p>
+<p>means that messages with the mail facility should be stored to
+/var/log/mail.log, no matter which severity indicator they have (that is telling
+us the asterisk). If you set up complex conditions, it can be annoying to find
+out which PRI value a specific syslog message has. Most stock syslogds do not
+provide any way to record them.</p>
+<h2>How is it done?</h2>
+<p>With <a href="http://www.rsyslog.com/">rsyslog</a>, PRI recording is simple.
+All you need is the correct template. Even if you do not use rsyslog on a regular
+basis, it might be a handy tool for finding out the priority.</p>
+<p>Rsyslog provides a flexible system to specify the output formats. It is
+template-based. A template with the traditional syslog format looks as follows:</p>
+<p align="center">
+<code>$template TraditionalFormat,&quot;%timegenerated% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n&quot;</code>
+</p>
+<p>The part in quotes is the output formats. Things between percent-signs are
+so-called <a href="property_replacer.html">messages properties</a>. They are replaced with the respective content
+from the syslog message when output is written. Everything outside of the
+percent signs is literal text, which is simply written as specified.</p>
+<p>Thankfully, rsyslog provides message properties for the priority. These are
+called &quot;PRI&quot;, &quot;syslogfacility&quot; and &quot;syslogpriority&quot; (case is important!). They are numerical
+values. Starting with rsyslog 1.13.4, there is also a property &quot;PRI-text&quot;, which
+contains the priority in friendly text format (e.g. &quot;syslog.info&quot;). For the rest
+of this article, I assume that you run version 1.13.4 or higher.</p>
+<p>Recording the priority is now a simple matter of adding the respective field
+to the template. It now looks like this:</p>
+<p align="center">
+<code>$template TraditionalFormatWithPRI,&quot;%PRI-text%: %timegenerated% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n&quot;</code>
+</p>
+<p>Now we have the right template - but how to write it to a file? You probably
+have a line like this in your syslog.conf:</p>
+<p align="center"><code>*.* -/var/log/messages.log</code></p>
+<p>It does not specify a template. Consequently, rsyslog uses the traditional
+format. In order to use some other format, simply specify the template after the
+semicolon:</p>
+<p align="center"><code>*.* -/var/log/messages.log;TraditionalFormatWithPRI</code></p>
+<p>That's all you need to do. There is one common pitfall: you need to define
+the template before you use it in a selector line. Otherwise, you will receive
+an error.</p>
+<p>Once you have applied the changes, you need to restart or HUP rsyslogd. It
+will then pick the new configuration.</p>
+<h2>What if I do not want rsyslogd to be the standard syslogd?</h2>
+<p>If you do not want to switch to rsyslog, you can still use it as a setup aid.
+A little bit of configuration is required.</p>
+<ol>
+ <li>Download, make and install rsyslog</li>
+ <li>copy your syslog.conf over to rsyslog.conf</li>
+ <li>add the template described above to it; select the file that should use
+ it</li>
+ <li>stop your regular syslog daemon for the time being</li>
+ <li>run rsyslogd (you may even do this interactively by calling it with the
+ -n additional option from a shell)</li>
+ <li>stop rsyslogd (press ctrl-c when running interactively)</li>
+ <li>restart your regular syslogd</li>
+</ol>
+<p>That's it - you can now review the priorities.</p>
+<h2>Some Sample Data</h2>
+<p>Below is some sample data created with the template specified above. Note the
+priority recording at the start of each line.</p>
+<p>
+<code>kern.info&lt;6&gt;: Jun 15 18:10:38 host kernel: PCI: Sharing IRQ 11 with 00:04.0<br>
+kern.info&lt;6&gt;: Jun 15 18:10:38 host kernel: PCI: Sharing IRQ 11 with 01:00.0<br>
+kern.warn&lt;4&gt;: Jun 15 18:10:38 host kernel: Yenta IRQ list 06b8, PCI irq11<br>
+kern.warn&lt;4&gt;: Jun 15 18:10:38 host kernel: Socket status: 30000006<br>
+kern.warn&lt;4&gt;: Jun 15 18:10:38 host kernel: Yenta IRQ list 06b8, PCI irq11<br>
+kern.warn&lt;4&gt;: Jun 15 18:10:38 host kernel: Socket status: 30000010<br>
+kern.info&lt;6&gt;: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0c00-0x0cff: clean.<br>
+kern.info&lt;6&gt;: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0100-0x04ff: excluding 0x100-0x107 0x378-0x37f 0x4d0-0x4d7<br>
+kern.info&lt;6&gt;: Jun 15 18:10:38 host kernel: cs: IO port probe 0x0a00-0x0aff: clean.<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:24 host dd: 1+0 records out<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:24 host random: Saving random seed: succeeded<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:25 host portmap: portmap shutdown succeeded<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:25 host network: Shutting down interface eth1: succeeded<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:25 host network: Shutting down loopback interface: succeeded<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:25 host pcmcia: Shutting down PCMCIA services: cardmgr<br>
+user.notice&lt;13&gt;: Jun 15 18:17:25 host /etc/hotplug/net.agent: NET unregister event not supported<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:27 host pcmcia: modules.<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:29 host rc: Stopping pcmcia: succeeded<br>
+local7.notice&lt;189&gt;: Jun 15 18:17:30 host rc: Starting killall: succeeded<br>
+syslog.info&lt;46&gt;: Jun 15 18:17:33 host [origin software=&quot;rsyslogd&quot; swVersion=&quot;1.13.3&quot; x-pid=&quot;2464&quot;] exiting on signal 15.<br>
+syslog.info&lt;46&gt;: Jun 18 10:55:47 host [origin software=&quot;rsyslogd&quot; swVersion=&quot;1.13.3&quot; x-pid=&quot;2367&quot;][x-configInfo udpReception=&quot;Yes&quot; udpPort=&quot;514&quot; tcpReception=&quot;Yes&quot; tcpPort=&quot;1470&quot;] restart<br>
+user.notice&lt;13&gt;: Jun 18 10:55:50 host rger: test<br>
+syslog.info&lt;46&gt;: Jun 18 10:55:52 host [origin software=&quot;rsyslogd&quot; swVersion=&quot;1.13.3&quot; x-pid=&quot;2367&quot;] exiting on signal 2.</code></p>
+<h2>Feedback Requested</h2>
+<P>I would appreciate feedback on this paper. If you have additional ideas,
+comments or find bugs, please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
+<h2>References and Additional Material</h2>
+<ul>
+ <li><a href="http://www.rsyslog.com">www.rsyslog.com</a> - the rsyslog site</li>
+</ul>
+<h2>Revision History</h2>
+<ul>
+ <li>2007-06-18 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * initial version created</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2007
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+and <a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p>Permission is granted to copy, distribute and/or modify this document under
+the terms of the GNU Free Documentation License, Version 1.2 or any later
+version published by the Free Software Foundation; with no Invariant Sections,
+no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be
+viewed at <a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/doc/rsyslog_stunnel.html b/doc/rsyslog_stunnel.html
new file mode 100644
index 0000000..9d94452
--- /dev/null
+++ b/doc/rsyslog_stunnel.html
@@ -0,0 +1,248 @@
+<html><head>
+<title>SSL Encrypting syslog with stunnel</title>
+<meta name="KEYWORDS" content="syslog encryption, rsyslog, stunnel, secure syslog, tcp, reliable, howto, ssl">
+</head>
+<body>
+<h1>SSL Encrypting Syslog with Stunnel</h1>
+ <P><small><i>Written by
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer
+ Gerhards</a> (2005-07-22)</i></small></P>
+<h2>Abstract</h2>
+<p><i><b>In this paper, I describe how to encrypt <a href="http://www.monitorware.com/en/topics/syslog/">syslog</a>
+messages on the network.</b> Encryption
+is vital to keep the confidiental content of syslog messages secure. I describe the overall
+approach and provide an HOWTO do it with the help of
+<a href="http://www.rsyslog.com">rsyslogd</a> and <a href="http://www.stunnel.org">stunnel</a>.</i></p>
+<h2>Background</h2>
+<P><b>Syslog is a
+clear-text protocol. That means anyone with a sniffer can have
+a peek at your data.</b> In some environments, this is no problem at all. In
+others, it is a huge setback, probably even preventing deployment of syslog
+solutions. Thankfully, there is an easy way to encrypt syslog communication. I
+will describe one approach in this paper.</P>
+<P>The most straigthforward solution would be that the syslogd itself encrypts
+messages. Unfortuantely, encryption is only standardized in
+<a href="http://www.monitorware.com/Common/en/glossary/rfc3195.php">RFC 3195</a>. But there
+is currently no syslogd that implements RFC 3195's encryption features,
+so this route leads to nothing. Another approach would be to use vendor- or
+project-specific syslog extensions. There are a few around, but the problem here
+is that they have compatibility issues. However, there is one surprisingly easy
+and interoperable solution: though not standardized, many vendors and projects
+implement plain tcp syslog. In a nutshell, plain tcp syslog is a mode where
+standard syslog messages are transmitted via tcp and records are separated by
+newline characters. This mode is supported by all major syslogd's (both on Linux/Unix
+and Windows) as well as log sources (for example,
+<a href="http://www.eventreporter.com/en/">EventReporter</a> for Windows
+Event Log forwarding). Plain tcp syslog offers reliability, but it does not
+offer encryption in itself. However, since it operates on a tcp stream, it is now easy
+to add encryption. There are various ways to do that. In this paper, I will
+describe how it is done with stunnel (an
+other alternative would be <a href="http://en.wikipedia.org/wiki/IPSec">IPSec</a>, for example).</P>
+<P>Stunnel is open source and it is available both for Unix/Linux and Windows.
+It provides a way to
+ use ssl communication for any non-ssl aware client and server - in this case,
+ our syslogd.</P>
+ <P>Stunnel works much like a wrapper. Both on the client and on the server machine,
+ tunnel portals are created. The non-ssl aware client and server software is
+ configured to not directly talk to the remote partner, but to the local
+ (s)tunnel portal instead. Stunnel, in turn, takes the data received from the
+ client, encrypts it via ssl, sends it to the remote tunnel portal and that
+ remote portal sends it to the recipient process on the remote machine. The
+ transfer to the portals is done via unencrypted communication. As such,
+ it is vital that
+ the portal and the respective program that is talking to it are on the same
+ machine, otherwise data would travel partly unencrypted. Tunneling, as done by stunnel,
+ requires connection oriented communication. This is why you need to use
+ tcp-based syslog. As a side-note, you can also encrypt a plain-text RFC
+ 3195 session via stunnel, though this definitely is not what the
+ protocol designers had on their mind ;)</P>
+<P>In the rest of this document, I assume that you use rsyslog on both the
+client and the server. For the samples, I use <a href="http://www.debian.org/">Debian</a>.
+Interestingly, there are
+some annoying differences between stunnel implementations. For example, on
+Debian a comment line starts with a semicolon (';'). On
+<a href="http://www.redhat.com">Red Hat</a>, it starts with
+a hash sign ('#'). So you need to watch out for subtle issues when setting up
+your system.</P>
+<h2>Overall System Setup</h2>
+<P>In ths paper, I assume two machines, one named &quot;client&quot; and the other named &quot;server&quot;.
+It is obvious that, in practice, you will probably have multiple clients but
+only one server. Syslog traffic shall be transmitted via stunnel over the
+network. Port 60514 is to be used for that purpose. The machines are set up as
+follows:</P>
+<P><b>Client</b></P>
+<ul>
+ <li>rsyslog forwards&nbsp; message to stunnel local portal at port 61514</li>
+ <li>local stunnel forwards data via the network to port 60514 to its remote
+ peer</li>
+</ul>
+<P><b>Server</b></P>
+<ul>
+ <li>stunnel listens on port 60514 to connections from its client peers</li>
+ <li>all connections are forwarded to the locally-running rsyslog listening
+ at port 61514</li>
+</ul>
+<h2>Setting up the system</h2>
+<P>For Debian, you need the &quot;stunnel4&quot; package. The &quot;stunnel&quot; package is the
+older 3.x release, which will not support the configuration I describe below.
+Other distributions might have other names. For example, on Red Hat it is just &quot;stunnel&quot;.
+Make sure that you install the appropriate package on both the client and the
+server. It is also a good idea to check if there are updates for either stunnel
+or openssl (which stunnel uses) - there are often security fixes available and
+often the latest fixes are not included in the default package.</P>
+<P>In my sample setup, I use only the bare minimum of options. For example, I do
+not make the server check client cerficiates. Also, I do not talk much about
+certificates at all. If you intend to really secure your system, you should
+probably learn about certificates and how to manage and deploy them. This is
+beyond the scope of this paper. For additional information,
+<a href="http://www.stunnel.org/faq/certs.html">
+http://www.stunnel.org/faq/certs.html</a> is a good starting point.</P>
+<P>You also need to install rsyslogd on both machines. Do this before starting
+with the configuration. You should also familarize yourself with its
+configuration file syntax, so that you know which actions you can trigger with
+it. Rsyslogd can work as a drop-in replacement for stock
+<a href="http://www.infodrom.org/projects/sysklogd/">sysklogd</a>. So if you know
+the standard syslog.conf syntax, you do not need to learn any more to follow
+this paper.</P>
+<h3>Server Setup</h3>
+<P>At the server, you need to have a digital certificate. That certificate
+enables SSL operation, as it provides the necessary crypto keys being used to
+secure the connection. Many versions of stunnel come with a default certificate,
+often found in /etc/stunnel/stunnel.pem. If you have it, it is good for testing
+only. If you use it in production, it is very easy to break into your secure
+channel as everybody is able to get hold of your private key. I didn't find an
+stunnel.pem on my Debian machine. I guess the Debian folks removed it because of
+its insecurity.</P>
+<P>You can create your own certificate with a simple openssl tool - you need to
+do it if you have none and I highly recommend to create one in any case. To
+create it, cd to /etc/stunnel and type:</P>
+<p><blockquote><code>openssl req -new -x509 -days 3650 -nodes -out
+stunnel.pem -keyout stunnel.pem</code></blockquote></p>
+<P>That command will ask you a number of questions. Provide some answer for
+them. If you are unsure, read
+<a href="http://www.stunnel.org/faq/certs.html">
+http://www.stunnel.org/faq/certs.html</a>. After the command has finished, you
+should have a usable stunnel.pem in your working directory.</P>
+<P>Next is to create a configuration file for stunnel. It will direct stunnel
+what to do. You can used the following basic file:</P>
+<P><blockquote><code><pre>; Certificate/key is needed in server mode
+cert = /etc/stunnel/stunnel.pem
+
+<i>; Some debugging stuff useful for troubleshooting
+debug = 7
+foreground=yes</i>
+
+[ssyslog]
+accept = 60514
+connect = 61514</pre>
+</code></blockquote></P>
+<p>Save this file to e.g. /etc/stunnel/syslog-server.conf. Please note that the
+settings in <i>italics</i> are for debugging only. They run stunnel
+with a lot of debug information in the foreground. This is very valuable while
+you setup the system - and very useless once everything works well. So be sure
+to remove these lines when going to production.</p>
+<p>Finally, you need to start the stunnel daemon. Under Debian, this is done via
+&quot;stunnel /etc/stunnel/syslog.server.conf&quot;. If you have enabled the debug
+settings, you will immediately see a lot of nice messages.</p>
+<p>Now you have stunnel running, but it obviously unable to talk to rsyslog -
+because it is not yet running. If not already done, configure it so that it does
+everything you want. If in doubt, you can simply copy /etc/syslog.conf to /etc/rsyslog.conf
+and you probably have what you want. The really important thing in rsyslogd
+configuration is that you must make it listen to tcp port 61514 (remember: this
+is where stunnel send the messages to). Thankfully, this is easy to achive: just
+add &quot;-t 61514&quot; to the rsyslogd startup options in your system startup script.
+After done so, start (or restart) rsyslogd.</p>
+<p>The server should now be fully operational.</p>
+<h3>Client Setup</h3>
+<P>The client setup is simpler. Most importantly, you do not need a certificate
+(of course, you can use one if you would like to authenticate the client, but
+this is beyond the scope of this paper). So the basic thing you need to do is
+create the stunnel configuration file.</P>
+<P><blockquote><code><pre><i>; Some debugging stuff useful for troubleshooting
+debug = 7
+foreground=yes</i>
+
+<b>client=yes</b>
+
+[ssyslog]
+accept = 127.0.0.1:61514
+connect = <font color="#FF0000">192.0.2.1</font>:60514
+</pre>
+</code></blockquote></P>
+<P>Again, the text in <i>italics</i> is for debugging purposes only. I suggest
+you leave it in during your initial testing and then remove it. The most
+important difference to the server configuration outlined above is the &quot;client=yes&quot;
+directive. It is what makes this stunnel behave like a client. The accept
+directive binds stunnel only to the local host, so that it is protected from
+receiving messages from the network (somebody might fake to be the local sender).
+The address &quot;192.0.2.1&quot; is the address of the server machine. You must change it
+to match your configuration. Save this file to /etc/stunnel/syslog-client.conf.</P>
+<P>Then, start stunnel via &quot;stunnel4 /etc/stunnel/syslog-client.conf&quot;.&nbsp; Now
+you should see some startup messages. If no errors appear, you have a running
+client stunnel instance.</P>
+<P>Finally, you need to tell rsyslogd to send data to the remote host. In stock
+syslogd, you do this via the &quot;@host&quot; forwarding directive. The same works with
+rsyslog, but it suppports extensions to use tcp. Add the following line to your
+/etc/rsyslog.conf:</P>
+<P><blockquote><code><pre>*.* @<font color="#FF0000">@</font>127.0.0.1:61514
+</pre>
+</code></blockquote><i></P>
+
+</i>
+
+<P>Please note the double at-sign (@@). This is no typo. It tells rsyslog to use
+tcp instead of udp delivery. In this sample, all messages are forwarded to the
+remote host. Obviously, you may want to limit this via the usual rsyslog.conf
+settings (if in doubt, use man rsyslog.con).</P>
+<P>You do not need to add any special startup settings to rsyslog on the client.
+Start or restart rsyslog so that the new configuration setting takes place.</P>
+<h3>Done</h3>
+<P>After following these steps, you should have a working secure syslog
+forwarding system. To verify, you can type &quot;logger test&quot; or a similar smart
+command on the client. It should show up in the respective server log file. If
+you dig out you sniffer, you should see that the traffic on the wire is actually
+protected. In the configuration use above, the two stunnel endpoints should be
+quite chatty, so that you can follow the action going on on your system.</P>
+<P>If you have only basic security needs, you can probably just remove the debug
+settings and take the rest of the configuration to production. If you are
+security-sensitve, you should have a look at the various stunnel settings that
+help you further secure the system.</P>
+<h2>Preventing Systems from talking directly to the rsyslog Server</h2>
+<P>It is possible that remote systems (or attackers) talk to the rsyslog server
+by directly connecting to its port 61514. Currently (July of 2005), rsyslog does
+not offer the ability to bind to the local host, only. This feature is planned,
+but as long as it is missing, rsyslog must be protected via a firewall. This can
+easily be done via e.g iptables. Just be sure not to forget it.</P>
+<h2>Conclusion</h2>
+<P>With minumal effort, you can set up a secure logging infrastructure employing
+ssl encrypted syslog message transmission. As a side note, you also have the
+benefit of reliable tcp delivery which is far less prone to message loss than
+udp.</P>
+<h3>Feedback requested</h3>
+<P>I would appreciate feedback on this tutorial. If you have additional ideas,
+comments or find bugs (I *do* bugs - no way... ;)), please
+<a href="mailto:rgerhards@adiscon.com">let me know</a>.</P>
+<h2>Revision History</h2>
+<ul>
+ <li>2005-07-22 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Initial Version created</li>
+ <li>2005-07-26 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> * Some text brush-up, hyperlinks added</li>
+ <li>2005-08-03 *
+ <a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a>
+ * license added</li>
+</ul>
+<h2>Copyright</h2>
+<p>Copyright (c) 2005
+<a href="http://www.adiscon.com/en/people/rainer-gerhards.php">Rainer Gerhards</a> and
+<a href="http://www.adiscon.com/en/">Adiscon</a>.</p>
+<p> Permission is granted to copy, distribute and/or modify this document
+ under the terms of the GNU Free Documentation License, Version 1.2
+ or any later version published by the Free Software Foundation;
+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+ Texts. A copy of the license can be viewed at
+<a href="http://www.gnu.org/copyleft/fdl.html">
+http://www.gnu.org/copyleft/fdl.html</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/doc/status.html b/doc/status.html
new file mode 100644
index 0000000..4037f61
--- /dev/null
+++ b/doc/status.html
@@ -0,0 +1,43 @@
+<html>
+<head>
+<title>rsyslog status page</title>
+</head>
+<body>
+<h2>rsyslog status page</h2>
+<p>This page reflects the status as of 2007-08-13.</p>
+<h2>Current Releases</h2>
+<p><b>development:</b> 1.18.2 -
+<a href="http://www.rsyslog.com/Article112.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-index-req-getit-lid-51.phtml">download</a></p>
+<p><b>stable:</b> 1.0.5 - <a href="http://www.rsyslog.com/Article85.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-index-req-getit-lid-39.phtml">download</a></p>
+<p>&nbsp;(<a href="version_naming.html">How are versions named?</a>)</p>
+<p><font color="#FF0000"><b>Do NOT use versions prior to 1.10.1 or 1.0.1,
+because they contain a SQL injection vulnerability</b></font> (<a href="http://www.rsyslog.com/Article35.phtml">read
+security advisory</a>).</p>
+<h2>Platforms</h2>
+<p>Thankfully, a number of folks have begin to build packages and help port
+rsyslog to other platforms. As such,
+<a href="http://wiki.rsyslog.com/index.php/Platforms">the platform list is now
+maintened inside the rsyslog wiki</a>. Platform maintainers perhaps have posted
+extra information there. If you do platform-specific work, feel free to add
+information to the wiki.</p>
+<h2>Additional information</h2>
+<p><b>Currently supported features are listed on the <a href="features.html">rsyslog features page</a>.</b></p>
+<ul>
+ <li>The rsyslog home page is <a href="http://www.rsyslog.com">www.rsyslog.com</a>.</li>
+ <li>Mailing list info can be found at
+ <a href="http://lists.adiscon.net/mailman/listinfo/rsyslog">http://lists.adiscon.com/rsyslog</a>.</li>
+ <li>The change log can be found at
+ <a href="http://www.rsyslog.com/Topic4.phtml">
+ http://www.rsyslog.com/Topic4.phtml</a>. </li>
+ <li>Online documentation is available at
+ <a href="http://www.rsyslog.com/doc">http://www.rsyslog.com/doc</a>.</li>
+ <li>You may also find <a href="http://rgerhards.blogspot.com/">Rainer's blog</a> an interesting read.</li>
+</ul>
+<p>The project was initiated in 2004 by
+<a href="http://www.gerhards.net/rainer">Rainer Gerhards</a>
+and is currently being maintained by him. See the <a href="history.html">history
+page</a> for more background information.</p>
+</body>
+</html>
diff --git a/doc/syslog-protocol.html b/doc/syslog-protocol.html
new file mode 100644
index 0000000..5305d81
--- /dev/null
+++ b/doc/syslog-protocol.html
@@ -0,0 +1,196 @@
+<html>
+<head>
+<title>syslog-protocol support in rsyslog</title>
+</head>
+<body>
+<h1>syslog-protocol support in rsyslog</h1>
+<p><b><a href="http://www.rsyslog.com/">Rsyslog</a>&nbsp; provides a trial
+implementation of the proposed
+<a href="http://www.monitorware.com/Common/en/glossary/syslog-protocol.php">
+syslog-protocol</a> standard.</b> The intention of this implementation is to
+find out what inside syslog-protocol is causing problems during implementation.
+As syslog-protocol is a standard under development, its support in rsyslog is
+highly volatile. It may change from release to release. So while it provides
+some advantages in the real world, users are cautioned against using it right
+now. If you do, be prepared that you will probably need to update all of your
+rsyslogds with each new release. If you try it anyhow, please provide feedback
+as that would be most benefitial for us.</p>
+<h2>Currently supported message format</h2>
+<p>Due to recent discussion on syslog-protocol, we do not follow any specific
+revision of the draft but rather the candidate ideas. The format supported
+currently is:</p>
+<p><b><code>&lt;PRI&gt;VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s
+SP MSG</code></b></p>
+<p>Field syntax and semantics are as defined in IETF I-D syslog-protocol-15.</p>
+<h2>Capabilities Implemented</h2>
+<ul>
+ <li>receiving message in the supported format (see above)</li>
+ <li>sending messages in the supported format</li>
+ <li>relaying messages</li>
+ <li>receiving messages in either legacy or -protocol format and transforming
+ them into the other one</li>
+ <li>virtual availability of TAG, PROCID, APP-NAME, MSGID, SD-ID no matter if
+ the message was received via legacy format, API or syslog-protocol format (non-present
+ fields are being emulated with great success)</li>
+ <li>maximum message size is set via preprocessor #define</li>
+ <li>syslog-protocol messages can be transmitted both over UDP and plain TCP
+ with some restrictions on compliance in the case of TCP</li>
+</ul>
+<h2>Findings</h2>
+<p>This lists what has been found during implementation:</p>
+<ul>
+ <li>The same receiver must be able to support both legacy and
+ syslog-protocol syslog messages. Anything else would be a big inconvenience
+ to users and would make deployment much harder. The detection must be done
+ automatically (see below on how easy that is).</li>
+ <li><b>NUL characters inside MSG</b> cause the message to be truncated at
+ that point. This is probably a major point for many C-based implementations.
+ No measures have yet been taken against this. Modifying the code to &quot;cleanly&quot;
+ support NUL characters is non-trivial, even though rsyslogd already has some
+ byte-counted string library (but this is new and not yet available
+ everywhere).</li>
+ <li><b>character encoding in MSG</b>: is is problematic to do the right
+ UTF-8 encoding. The reason is that we pick up the MSG from the local domain
+ socket (which got it from the syslog(3) API). The text obtained does not
+ include any encoding information, but it does include non US-ASCII
+ characters. It may also include any other encoding. Other than by guessing
+ based on the provided text, I have no way to find out what it is. In order
+ to make the syslogd do anything useful, I have now simply taken the message
+ as is and stuffed it into the MSG part. Please note that I think this will
+ be a route that other implementors would take, too.</li>
+ <li>A minimal parser is easy to implement. It took me roughly 2 hours to add
+ it to rsyslogd. This includes the time for restructering the code to be able
+ to parse both legacy syslog as well as syslog-protocol. The parser has some
+ restrictions, though<ul>
+ <li>STRUCTURED-DATA field is extracted, but not validated. Structured data
+ &quot;[test ]]&quot; is not caught as an error. Nor are any other errors caught. For
+ my needs with this syslogd, that level of structued data processing is
+ probably sufficient. I do not want to parse/validate it in all cases. This
+ is also a performance issue. I think other implementors could have the same
+ view. As such, we should not make validation a requirement.</li>
+ <li>MSG is not further processed (e.g. Unicode not being validated)</li>
+ <li>the other header fields are also extracted, but no validation is
+ performed right now. At least some validation should be easy to add (not
+ done this because it is a proof-of-concept and scheduled to change).</li>
+</ul>
+ </li>
+ <li>Universal access to all syslog fields (missing ones being emulated) was
+ also quite easy. It took me around another 2 hours to integrate emulation of
+ non-present fields into the code base.</li>
+ <li>The version at the start of the message makes it easy to detect if we
+ have legacy syslog or syslog-protocol. Do NOT move it to somewhere inside
+ the middle of the message, that would complicate things. It might not be
+ totally fail-safe to just rely on &quot;1 &quot; as the &quot;cookie&quot; for a syslog-protocol.
+ Eventually, it would be good to add some more uniqueness, e.g. &quot;@#1 &quot;.</li>
+ <li>I have no (easy) way to detect truncation if that happens on the UDP
+ stack. All I see is that I receive e.g. a 4K message. If the message was e.g.
+ 6K, I received two chunks. The first chunk (4K) is correctly detected as a
+ syslog-protocol message, the second (2K) as legacy syslog. I do not see what
+ we could do against this. This questions the usefulness of the TRUNCATE bit.
+ Eventually, I could look at the UDP headers and see that it is a fragment. I
+ have looked at a network sniffer log of the conversation. This looks like
+ two totally-independant messages were sent by the sender stack.</li>
+ <li>The maximum message size is currently being configured via a
+ preprocessor #define. It can easily be set to 2K or 4K, but more than 4K is
+ not possible because of UDP stack limitations. Eventually, this can be
+ worked around, but I have not done this yet.</li>
+ <li>rsyslogd can accept syslog-protocol formatted messages but is able to
+ relay them in legacy format. I find this a must in real-life deployments.
+ For this, I needed to do some field mapping so that APP-NAME/PROCID are
+ mapped into a TAG.</li>
+ <li>rsyslogd can also accept legacy syslog message and relay them in
+ syslog-protocol format. For this, I needed to apply some sub-parsing of the
+ TAG, which on most occasions provides correct results. There might be some
+ misinterpretations but I consider these to be mostly non-intrusive. </li>
+ <li>Messages received from the syslog API (the normal case under *nix) also
+ do not have APP-NAME and PROCID and I must parse them out of TAG as
+ described directly above. As such, this algorithm is absolutely vital to
+ make things work on *nix.</li>
+ <li>I have an issue with messages received via the syslog(3) API (or, to be
+ more precise, via the local domain socket this API writes to): These
+ messages contain a timestamp, but that timestamp does neither have the year
+ nor the high-resolution time. The year is no real issue, I just take the
+ year of the reception of that message. There is a very small window of
+ exposure for messages read from the log immediately after midnight Jan 1st.
+ The message in the domain socket might have been written immediately before
+ midnight in the old year. I think this is acceptable. However, I can not
+ assign a high-precision timestamp, at least it is somewhat off if I take the
+ timestamp from message reception on the local socket. An alternative might
+ be to ígnore the timestamp present and instead use that one when the message
+ is pulled from the local socket (I am talking about IPC, not the network -
+ just a reminder...). This is doable, but eventually not advisable. It looks
+ like this needs to be resolved via a configuration option.</li>
+ <li>rsyslogd already advertised its origin information on application
+ startup (in a syslog-protocol-14 compatible format). It is fairly easy to
+ include that with any message if desired (not currently done).</li>
+ <li>A big problem I noticed are malformed messages. In -syslog-protocol, we
+ recommend/require to discard malformed messages. However, in practice users
+ would like to see everything that the syslogd receives, even if it is in
+ error. For the first version, I have not included any error handling at all.
+ However, I think I would deliberately ignore any &quot;discard&quot; requirement. My
+ current point of view is that in my code I would eventually flag a message
+ as being invalid and allow the user to filter on this invalidness. So these
+ invalid messages could be redirected into special bins.</li>
+ <li>The error logging recommendations (those I insisted on;)) are not really
+ practical. My application has its own error logging philosophy and I will
+ not change this to follow a draft.</li>
+ <li>Relevance of support for leap seconds and senders without knowledge of
+ time is questionable. I have not made any specific provisions in the code
+ nor would I know how to handle that differently. I could, however, pull the
+ local reception timestamp in this case, so it might be useful to have this
+ feature. I do not think any more about this for the initial proof-of-concept.
+ Note it as a potential problem area, especially when logging to databases.</li>
+ <li>The HOSTNAME field for internally generated messages currently contains
+ the hostname part only, not the FQDN. This can be changed inside the code
+ base, but it requires some thinking so that thinks are kept compatible with
+ legacy syslog. I have not done this for the proof-of-concept, but I think it
+ is not really bad. Maybe an hour or half a day of thinking.</li>
+ <li>It is possible that I did not receive a TAG with legacy syslog or via
+ the syslog API. In this case, I can not generate the APP-NAME. For
+ consistency, I have used &quot;-&quot; in such cases (just like in PROCID, MSGID and
+ STRUCTURED-DATA).</li>
+ <li>As an architectural side-effect, syslog-protocol formatted messages can
+ also be transmitted over non-standard syslog/raw tcp. This implementation
+ uses the industry-standard LF termination of tcp syslog records. As such,
+ syslog-protocol messages containing a LF will be broken invalidly. There is
+ nothing that can be done against this without specifying a TCP transport.
+ This issue might be more important than one thinks on first thought. The
+ reason is the wide deployment of syslog/tcp via industry standard.</li>
+</ul>
+<p><b>Some notes on syslog-transport-udp-06</b></p>
+<ul>
+ <li>I did not make any low-level modifications to the UDP code and think I
+ am still basically covered with this I-D.</li>
+ <li>I deliberately violate section 3.3 insofar as that I do not necessarily
+ accept messages destined to port 514. This feature is user-required and a
+ must. The same applies to the destination port. I am not sure if the &quot;MUST&quot;
+ in section 3.3 was meant that this MUST be an option, but not necessarily be
+ active. The wording should be clarified.</li>
+ <li>section 3.6: I do not check checksums. See the issue with discarding
+ messages above. The same solution will probably be applied in my code.</li>
+</ul>
+<p>&nbsp;</p>
+<h2>Conlusions/Suggestions</h2>
+<p>These are my personal conclusions and suggestions. Obviously, they must be
+discussed ;)</p>
+<ul>
+ <li>NUL should be disallowd in MSG</li>
+ <li>As it is not possible to definitely know the character encoding of the
+ application-provided message, MSG should <b>not</b> be specified to use UTF-8
+ exclusively. Instead, it is suggested that any encoding may be used but
+ UTF-8 is preferred. To detect UTF-8, the MSG should start with the UTF-8
+ byte order mask of &quot;EF BB BF&quot; if it is UTF-8 encoded (see section 155.9 of
+ <a href="http://www.unicode.org/versions/Unicode4.0.0/ch15.pdf">
+ http://www.unicode.org/versions/Unicode4.0.0/ch15.pdf</a>) </li>
+ <li>Requirements to drop messages should be reconsidered. I guess I would
+ not be the only implementor ignoring them.</li>
+ <li>Logging requirements should be reconsidered and probably be removed.</li>
+ <li>It would be advisable to specify &quot;-&quot; for APP-NAME is the name is not
+ known to the sender.</li>
+ <li>The implications of the current syslog/tcp industry standard on
+ syslog-protocol should be further evaluated and be fully understood</li>
+</ul>
+<p>&nbsp;</p>
+</body>
+</html>
+
diff --git a/doc/version_naming.html b/doc/version_naming.html
new file mode 100644
index 0000000..a1923fc
--- /dev/null
+++ b/doc/version_naming.html
@@ -0,0 +1,30 @@
+<html>
+<head>
+<title>rsyslog bugs and annoyances</title>
+</head>
+<body>
+<h1>Version Naming</h1>
+<p>This document briefly outlines the strategy for naming versions. It applies
+to versions 1.0.0 and above. Versions below that are all instable and have a
+different naming schema.</p>
+<p>The major version is incremented whenever a considerate, major features have
+been added. This is expected to happen quite infrequently.</p>
+<p>The minor version number is incremented whenever there is &quot;sufficient need&quot;
+(at the discretion of the developers). There is a notable difference between
+stable and instable branches. The <b>stable branch</b> always has a minor
+version number in the range from 0 to 9. It is expected that the stable branch
+will receive bug and security fixes only. So the range of minor version numbers
+should be quite sufficient.</p>
+<p>For the <b>instable branch</b>, minor version numbers always start at 10 and
+are incremented as needed (again, at the discretion of the developers). Here,
+new minor versions include both fixes as well as new features (hopefully most of
+the time). They are expected to be released quite often.</p>
+<p>The patch level (third number) is incremented whenever a really minor thing
+must be added to an existing version. This is expected to happen quite
+infrequently.</p>
+<p>In general, the instable branch carries all new development. Once it
+concludes with a sufficiently-enhanced, quite stable version, a new major stable
+version is assigned.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/freebsd/rsyslogd b/freebsd/rsyslogd
new file mode 100755
index 0000000..1cbcb6f
--- /dev/null
+++ b/freebsd/rsyslogd
@@ -0,0 +1,83 @@
+#!/bin/sh
+# Sample startup script for rsyslogd on FreeBSD.
+# It worked on my machine, but this does not necessarily
+# mean it works on all machines - it's not thouroughly
+# tested. Please note that it may also work on other
+# BSD variants, too.
+#
+# As of this writing, there was an issue with the mysql client
+# library on startup. If compiled with MySQL support, rsyslogd
+# would not necessarily start correctly but could eventually
+# die with a "mysql client libary not found" (or similar)
+# message. I do not know its cause neither the cure. If you
+# have one, let me know.
+#
+# ATTENTION: you need also to change the /etc/rc.config file
+# and disable stock syslogd and then enable rsyslogd!
+#
+# rgerhards 2005-08-09 <rgehards@adiscon.com>
+#
+
+# PROVIDE: rsyslogd
+# REQUIRE: mountcritremote cleanvar
+# BEFORE: SERVERS
+
+. /etc/rc.subr
+
+name="rsyslogd"
+rcvar=`set_rcvar`
+pidfile="/var/run/rsyslogd.pid"
+command="/usr/sbin/${name}"
+required_files="/etc/rsyslog.conf"
+start_precmd="rsyslogd_precmd"
+extra_commands="reload"
+
+_sockfile="/var/run/rsyslogd.sockets"
+evalargs="rc_flags=\"\`set_socketlist\` \$rc_flags\""
+altlog_proglist="named"
+
+rsyslogd_precmd()
+{
+ # Transitional symlink for old binaries
+ #
+ if [ ! -L /dev/log ]; then
+ ln -sf /var/run/log /dev/log
+ fi
+ rm -f /var/run/log
+
+ # Create default list of syslog sockets to watch
+ #
+ ( umask 022 ; > $_sockfile )
+
+ # If running named(8) or ntpd(8) chrooted, added appropriate
+ # syslog socket to list of sockets to watch.
+ #
+ for _l in $altlog_proglist; do
+ eval _ldir=\$${_l}_chrootdir
+ if checkyesno `set_rcvar $_l` && [ -n "$_ldir" ]; then
+ echo "${_ldir}/var/run/log" >> $_sockfile
+ fi
+ done
+
+ # If other sockets have been provided, change run_rc_command()'s
+ # internal copy of $rsyslogd_flags to force use of specific
+ # rsyslogd sockets.
+ #
+ if [ -s $_sockfile ]; then
+ echo "/var/run/log" >> $_sockfile
+ eval $evalargs
+ fi
+
+ return 0
+}
+
+set_socketlist()
+{
+ _socketargs=
+ for _s in `cat $_sockfile | tr '\n' ' '` ; do
+ _socketargs="-l $_s $_socketargs"
+ done
+ echo $_socketargs
+}
+load_rc_config $name
+run_rc_command "$1"
diff --git a/iminternal.c b/iminternal.c
new file mode 100644
index 0000000..9fce41a
--- /dev/null
+++ b/iminternal.c
@@ -0,0 +1,189 @@
+/* iminternal.c
+ * This file set implements the internal messages input module for rsyslog.
+ * Note: we currently do not have an input module spec, but
+ * we will have one in the future. This module needs then to be
+ * adapted.
+ *
+ * File begun on 2007-08-03 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "syslogd.h"
+#include "linkedlist.h"
+#include "iminternal.h"
+
+static linkedList_t llMsgs;
+
+
+/* destructs an iminternal object
+ */
+static rsRetVal iminternalDestruct(iminternal_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ if(pThis->pMsg != NULL)
+ MsgDestruct(pThis->pMsg);
+
+ free(pThis);
+
+ return iRet;
+}
+
+
+/* Construct an iminternal object
+ */
+static rsRetVal iminternalConstruct(iminternal_t **ppThis)
+{
+ DEFiRet;
+ iminternal_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (iminternal_t*) calloc(1, sizeof(iminternal_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis != NULL)
+ iminternalDestruct(pThis);
+ }
+
+ *ppThis = pThis;
+
+ return iRet;
+};
+
+
+/* add a message to the linked list
+ * Note: the pMsg reference counter is not incremented. Consequently,
+ * the caller must NOT decrement it. The caller actually hands over
+ * full ownership of the pMsg object.
+ * The interface of this function is modelled after syslogd/logmsg(),
+ * for which it is an "replacement".
+ */
+rsRetVal iminternalAddMsg(int pri, msg_t *pMsg, int flags)
+{
+ DEFiRet;
+ iminternal_t *pThis;
+
+ assert(pMsg != NULL);
+
+ CHKiRet(iminternalConstruct(&pThis));
+
+ pThis->pri = pri;
+ pThis->pMsg = pMsg;
+ pThis->flags = flags;
+
+ CHKiRet(llAppend(&llMsgs, NULL, (void*) pThis));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ dbgprintf("iminternalAddMsg() error %d - can not otherwise report this error, message lost\n", iRet);
+ if(pThis != NULL)
+ iminternalDestruct(pThis);
+ }
+
+ return iRet;
+}
+
+
+/* pull the first error message from the linked list, remove it
+ * from the list and return it to the caller. The caller is
+ * responsible for freeing the message!
+ */
+rsRetVal iminternalRemoveMsg(int *pPri, msg_t **ppMsg, int *pFlags)
+{
+ DEFiRet;
+ iminternal_t *pThis;
+ linkedListCookie_t llCookie = NULL;
+
+ assert(pPri != NULL);
+ assert(ppMsg != NULL);
+ assert(pFlags != NULL);
+
+ CHKiRet(llGetNextElt(&llMsgs, &llCookie, (void**) &pThis));
+ *pPri = pThis->pri;
+ *pFlags = pThis->flags;
+ *ppMsg = pThis->pMsg;
+ pThis->pMsg = NULL; /* we do no longer own it - important for destructor */
+
+ if(llDestroyRootElt(&llMsgs) != RS_RET_OK) {
+ dbgprintf("Root element of iminternal linked list could not be destroyed - there is "
+ "nothing we can do against it, we ignore it for now. Things may go wild "
+ "from here on. This is most probably a program logic error.\n");
+ }
+
+finalize_it:
+ return iRet;
+}
+
+/* tell the caller if we have any messages ready for processing.
+ * 0 means we have none, everything else means there is at least
+ * one message ready.
+ */
+rsRetVal iminternalHaveMsgReady(int* pbHaveOne)
+{
+ assert(pbHaveOne != NULL);
+
+ return llGetNumElts(&llMsgs, pbHaveOne);
+}
+
+
+/* initialize the iminternal subsystem
+ * must be called once at the start of the program
+ */
+rsRetVal modInitIminternal(void)
+{
+ DEFiRet;
+
+ iRet = llInit(&llMsgs, iminternalDestruct, NULL, NULL);
+
+ return iRet;
+}
+
+
+/* de-initialize the iminternal subsystem
+ * must be called once at the end of the program
+ * Note: the error list must have been pulled first. We do
+ * NOT care if there are any errors left - we simply destroy
+ * them.
+ */
+rsRetVal modExitIminternal(void)
+{
+ DEFiRet;
+
+ iRet = llDestroy(&llMsgs);
+
+ return iRet;
+}
+
+/*
+ * vi:set ai:
+ */
diff --git a/iminternal.h b/iminternal.h
new file mode 100644
index 0000000..0677f81
--- /dev/null
+++ b/iminternal.h
@@ -0,0 +1,48 @@
+/* Definition of the internal messages input module.
+ *
+ * Note: we currently do not have an input module spec, but
+ * we will have one in the future. This module needs then to be
+ * adapted.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#ifndef IMINTERNAL_H_INCLUDED
+#define IMINTERNAL_H_INCLUDED
+#include "template.h"
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct iminternal_s { /* config file sysline parse entry */
+ int pri;
+ msg_t *pMsg; /* the message (in all its glory) */
+ int flags;
+};
+typedef struct iminternal_s iminternal_t;
+
+/* prototypes */
+rsRetVal modInitIminternal(void);
+rsRetVal modExitIminternal(void);
+rsRetVal iminternalAddMsg(int pri, msg_t *pMsg, int flags);
+rsRetVal iminternalHaveMsgReady(int* pbHaveOne);
+rsRetVal iminternalRemoveMsg(int *pPri, msg_t **ppMsg, int *pFlags);
+
+#endif /* #ifndef IMINTERNAL_H_INCLUDED */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..4fbbae7
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,507 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-10-14.15
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+posix_glob=
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chmodcmd=$chmodprog
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c (ignored)
+-d create directories instead of installing files.
+-g GROUP $chgrpprog installed files to GROUP.
+-m MODE $chmodprog installed files to MODE.
+-o USER $chownprog installed files to USER.
+-s $stripprog installed files.
+-t DIRECTORY install into DIRECTORY.
+-T report an error if DSTFILE is a directory.
+--help display this help and exit.
+--version display version info and exit.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ shift
+ shift
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd=$stripprog
+ shift
+ continue;;
+
+ -t) dstarg=$2
+ shift
+ shift
+ continue;;
+
+ -T) no_target_directory=true
+ shift
+ continue;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dstarg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dstarg"
+ shift # fnord
+ fi
+ shift # arg
+ dstarg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src ;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dstarg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dstarg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst ;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dstarg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix=/ ;;
+ -*) prefix=./ ;;
+ *) prefix= ;;
+ esac
+
+ case $posix_glob in
+ '')
+ if (set -f) 2>/dev/null; then
+ posix_glob=true
+ else
+ posix_glob=false
+ fi ;;
+ esac
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob && set -f
+ set fnord $dstdir
+ shift
+ $posix_glob && set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # Now rename the file to the real destination.
+ { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
+ || {
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ if test -f "$dst"; then
+ $doit $rmcmd -f "$dst" 2>/dev/null \
+ || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
+ && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
+ || {
+ echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ else
+ :
+ fi
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ } || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/klogd.c b/klogd.c
new file mode 100644
index 0000000..d32610e
--- /dev/null
+++ b/klogd.c
@@ -0,0 +1,1200 @@
+/*
+ klogd.c - main program for Linux kernel log daemon.
+ Copyright (c) 1995 Dr. G.W. Wettstein <greg@wind.rmcc.com>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "config.h"
+
+#ifdef FEATURE_KLOGD
+/*
+ * Steve Lord (lord@cray.com) 7th Nov 92
+ *
+ * Modified to check for kernel info by Dr. G.W. Wettstein 02/17/93.
+ *
+ * Fri Mar 12 16:53:56 CST 1993: Dr. Wettstein
+ * Modified LogLine to use a newline as the line separator in
+ * the kernel message buffer.
+ *
+ * Added debugging code to dump the contents of the kernel message
+ * buffer at the start of the LogLine function.
+ *
+ * Thu Jul 29 11:40:32 CDT 1993: Dr. Wettstein
+ * Added syscalls to turn off logging of kernel messages to the
+ * console when klogd becomes responsible for kernel messages.
+ *
+ * klogd now catches SIGTERM and SIGKILL signals. Receipt of these
+ * signals cases the clean_up function to be called which shuts down
+ * kernel logging and re-enables logging of messages to the console.
+ *
+ * Sat Dec 11 11:54:22 CST 1993: Dr. Wettstein
+ * Added fixes to allow compilation with no complaints with -Wall.
+ *
+ * When the daemon catches a fatal signal (SIGTERM, SIGKILL) a
+ * message is output to the logfile advising that the daemon is
+ * going to terminate.
+ *
+ * Thu Jan 6 11:54:10 CST 1994: Dr. Wettstein
+ * Major re-write/re-organization of the code.
+ *
+ * Klogd now assigns kernel messages to priority levels when output
+ * to the syslog facility is requested. The priority level is
+ * determined by decoding the prioritization sequence which is
+ * tagged onto the start of the kernel messages.
+ *
+ * Added the following program options: -f arg -c arg -s -o -d
+ *
+ * The -f switch can be used to specify that output should
+ * be written to the named file.
+ *
+ * The -c switch is used to specify the level of kernel
+ * messages which are to be directed to the console.
+ *
+ * The -s switch causes the program to use the syscall
+ * interface to the kernel message facility. This can be
+ * used to override the presence of the /proc filesystem.
+ *
+ * The -o switch causes the program to operate in 'one-shot'
+ * mode. A single call will be made to read the complete
+ * kernel buffer. The contents of the buffer will be
+ * output and the program will terminate.
+ *
+ * The -d switch causes 'debug' mode to be activated. This
+ * will cause the daemon to generate LOTS of output to stderr.
+ *
+ * The buffer decomposition function (LogLine) was re-written to
+ * squash a bug which was causing only partial kernel messages to
+ * be written to the syslog facility.
+ *
+ * The signal handling code was modified to properly differentiate
+ * between the STOP and TSTP signals.
+ *
+ * Added pid saving when the daemon detaches into the background. Thank
+ * you to Juha Virtanen (jiivee@hut.fi) for providing this patch.
+ *
+ * Mon Feb 6 07:31:29 CST 1995: Dr. Wettstein
+ * Significant re-organization of the signal handling code. The
+ * signal handlers now only set variables. Not earth shaking by any
+ * means but aesthetically pleasing to the code purists in the group.
+ *
+ * Patch to make things more compliant with the file system standards.
+ * Thanks to Chris Metcalf for prompting this helpful change.
+ *
+ * The routines responsible for reading the kernel log sources now
+ * initialize the buffers before reading. I think that this will
+ * solve problems with non-terminated kernel messages producing
+ * output of the form: new old old old
+ *
+ * This may also help influence the occassional reports of klogd
+ * failing under significant load. I think that the jury may still
+ * be out on this one though. My thanks to Joerg Ahrens for initially
+ * tipping me off to the source of this problem. Also thanks to
+ * Michael O'Reilly for tipping me off to the best fix for this problem.
+ * And last but not least Mark Lord for prompting me to try this as
+ * a means of attacking the stability problem.
+ *
+ * Specifying a - as the arguement to the -f switch will cause output
+ * to be directed to stdout rather than a filename of -. Thanks to
+ * Randy Appleton for a patch which prompted me to do this.
+ *
+ * Wed Feb 22 15:37:37 CST 1995: Dr. Wettstein
+ * Added version information to logging startup messages.
+ *
+ * Wed Jul 26 18:57:23 MET DST 1995: Martin Schulze
+ * Added an commandline argument "-n" to avoid forking. This obsoletes
+ * the compiler define NO_FORK. It's more useful to have this as an
+ * argument as there are many binary versions and one doesn't need to
+ * recompile the daemon.
+ *
+ * Thu Aug 10 19:01:08 MET DST 1995: Martin Schulze
+ * Added my pidfile.[ch] to it to perform a better handling with pidfiles.
+ * Now both, syslogd and klogd, can only be started once. They check the
+ * pidfile.
+ *
+ * Fri Nov 17 15:05:43 CST 1995: Dr. Wettstein
+ * Added support for kernel address translation. This required moving
+ * some definitions and includes to the new klogd.h file. Some small
+ * code cleanups and modifications.
+ *
+ * Mon Nov 20 10:03:39 MET 1995
+ * Added -v option to print the version and exit.
+ *
+ * Thu Jan 18 11:19:46 CST 1996: Dr. Wettstein
+ * Added suggested patches from beta-testers. These address two
+ * two problems. The first is segmentation faults which occur with
+ * the ELF libraries. This was caused by passing a null pointer to
+ * the strcmp function.
+ *
+ * Added a second patch to remove the pidfile as part of the
+ * termination cleanup sequence. This minimizes the potential for
+ * conflicting pidfiles causing immediate termination at boot time.
+ *
+ * Wed Aug 21 09:13:03 CDT 1996: Dr. Wettstein
+ * Added ability to reload static symbols and kernel module symbols
+ * under control of SIGUSR1 and SIGUSR2 signals.
+ *
+ * Added -p switch to select 'paranoid' behavior with respect to the
+ * loading of kernel module symbols.
+ *
+ * Informative line now printed whenever a state change occurs due
+ * to signal reception by the daemon.
+ *
+ * Added the -i and -I command line switches to signal the currently
+ * executing daemon.
+ *
+ * Tue Nov 19 10:15:36 PST 1996: Leland Olds <olds@eskimo.com>
+ * Corrected vulnerability to buffer overruns by rewriting LogLine
+ * routine. Obscenely long kernel messages will now be broken up
+ * into lines no longer than LOG_LINE_LENGTH.
+ *
+ * The last version of LogLine was vulnerable to buffer overruns:
+ * - Kernel messages longer than LOG_LINE_LENGTH caused a buffer
+ * overrun.
+ * - If a line was determined to be shorter than LOG_LINE_LENGTH,
+ * the routine "ExpandKadds" could cause the line grow by
+ * an unknown amount and overrun a buffer.
+ * I turned these routines into a little parsing state machine that
+ * should not have these problems.
+ *
+ * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
+ * Some more glibc patches made by <mdorman@debian.org>.
+ *
+ * Thu Aug 21 12:11:27 MET DST 1997: Martin Schulze <joey@infodrom.north.de>
+ * Fixed little mistake which prevented klogd from accepting a
+ * console log
+ *
+ * Fri Jan 9 00:39:52 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Changed the behaviour of klogd when receiving a terminate
+ * signal. Now the program terminates immediately instead of
+ * completing the receipt of a kernel message, i.e the read()
+ * call. The old behaveiour could result in klogd being
+ * recognized as being undead, because it'll only die after a
+ * message has been received.
+ *
+ * Fri Jan 9 11:03:48 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Corrected some code that caused klogd to dump core when
+ * receiving messages containing '%', some of them exist in
+ * 2.1.78. Thanks to Chu-yeon Park <kokids@doit.ajou.ac.kr> for
+ * informing me.
+ *
+ * Fri Jan 9 23:38:19 CET 1998: Florian La Roche <florian@knorke.saar.de>
+ * Added -x switch to omit EIP translation and System.map evaluation.
+ *
+ * Sun Jan 25 20:47:46 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * As the bug covering the %'s introduced a problem with
+ * unevaluated priorities I've worked out a real fix that strips
+ * %'s to an even number which is harmless for printf.
+ *
+ * Sat Oct 10 20:01:48 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Added support for TESTING define which will turn klogd into
+ * stdio-mode used for debugging.
+ *
+ * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified System.map read function to try all possible map
+ * files until a file with matching version is found. Added support for
+ * Debian release.
+ *
+ * Mon Oct 12 13:01:27 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Used unsigned long and strtoul() to resolve kernel oops symbols.
+ *
+ * Sun Jan 3 18:38:03 CET 1999: Martin Schulze <joey@infodrom.north.de>
+ * Shortened LOG_LINE_LENGTH in order to get long lines splitted
+ * up earlier and syslogd has a better chance concatenating them
+ * together again.
+ *
+ * Sat Aug 21 12:27:02 CEST 1999: Martin Schulze <joey@infodrom.north.de>
+ * Skip newline when reading in messages.
+ *
+ * Tue Sep 12 22:14:33 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Don't feed a buffer directly to a printf-type routine, use
+ * "%s" as format string instead. Thanks to Jouko Pynnönen
+ * <jouko@solutions.fi> for pointing this out.
+ *
+ * Tue Sep 12 22:44:57 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Commandline option `-2': When symbols are expanded, print the
+ * line twice. Once with addresses converted to symbols, once with the
+ * raw text. Allows external programs such as ksymoops do their own
+ * processing on the original data. Thanks to Keith Owens
+ * <kaos@ocs.com.au> for the patch.
+ *
+ * Mon Sep 18 09:32:27 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Added patch to fix priority decoding after moving kernel
+ * messgages into "%s". Thanks to Solar Designer
+ * <solar@false.com> for the patch.
+ *
+ * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de>
+ * Stop LogLine() from being called with wrong argument when a
+ * former calculation failed already. Thanks to Thomas Roessler
+ * <roessler@does-not-exist.org> for providing a patch.
+ *
+ * Ignore zero bytes, no busy loop is entered anymore. Several
+ * people have submitted patches: Troels Walsted Hansen
+ * <troels@thule.no>, Wolfgang Oertl <Wolfgang.Oertl@uibk.ac.at>
+ * and Thomas Roessler.
+ */
+
+
+/* Includes. */
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#if !defined(__GLIBC__)
+#include <linux/time.h>
+#endif /* __GLIBC__ */
+#include <stdarg.h>
+#include <paths.h>
+#include <stdlib.h>
+#include "klogd.h"
+#include "ksyms.h"
+#ifndef TESTING
+#include "pidfile.h"
+#endif
+
+#define __LIBRARY__
+#include <linux/unistd.h>
+#if !defined(__GLIBC__)
+# define __NR_ksyslog __NR_syslog
+_syscall3(int,ksyslog,int, type, char *, buf, int, len);
+#else
+#include <sys/klog.h>
+#define ksyslog klogctl
+#endif
+extern int writeSyslogV(int pri, const char *szFmt, va_list va);
+extern int writeSyslog(int iPri, const char *szFmt, ...);
+
+#ifndef _PATH_KLOG
+#define _PATH_KLOG "/proc/kmsg"
+#endif
+
+#define LOG_BUFFER_SIZE 4096
+#define LOG_LINE_LENGTH 1000
+
+#ifndef TESTING
+#if defined(FSSTND)
+static char *PidFile = _PATH_VARRUN "rklogd.pid";
+#else
+static char *PidFile = "/etc/rklogd.pid";
+#endif
+#endif
+
+static int kmsg,
+ change_state = 0,
+ terminate = 0,
+ caught_TSTP = 0,
+ reload_symbols = 0,
+ console_log_level = -1;
+
+static int use_syscall = 0,
+ one_shot = 0,
+ symbol_lookup = 1,
+ no_fork = 0; /* don't fork - don't run in daemon mode */
+
+static char *symfile = (char *) 0,
+ log_buffer[LOG_BUFFER_SIZE];
+
+static FILE *output_file = (FILE *) 0;
+
+static enum LOGSRC {none, proc, kernel} logsrc;
+
+int debugging = 0;
+int symbols_twice = 0;
+
+
+/* Function prototypes. */
+extern int ksyslog(int type, char *buf, int len);
+static void CloseLogSrc(void);
+extern void restart(int sig);
+extern void stop_logging(int sig);
+extern void stop_daemon(int sig);
+extern void reload_daemon(int sig);
+static void Terminate(void);
+static void SignalDaemon(int);
+static void ReloadSymbols(void);
+static void ChangeLogging(void);
+static enum LOGSRC GetKernelLogSrc(void);
+static void LogLine(char *ptr, int len);
+static void LogKernelLine(void);
+static void LogProcLine(void);
+extern int main(int argc, char *argv[]);
+
+
+extern void Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
+extern void Syslog(int priority, char *fmt, ...)
+{
+ va_list ap;
+ char *argl;
+
+ if(debugging)
+ {
+ fputs("Logging line:\n", stderr);
+ fprintf(stderr, "\tLine: %s\n", fmt);
+ fprintf(stderr, "\tPriority: %d\n", priority);
+ }
+
+ /* Handle output to a file. */
+ if ( output_file != (FILE *) 0 ) {
+ va_start(ap, fmt);
+ vfprintf(output_file, fmt, ap);
+ va_end(ap);
+ fputc('\n', output_file);
+ fflush(output_file);
+ if (!one_shot)
+ fsync(fileno(output_file));
+ return;
+ }
+
+ /* Output using syslog. */
+ if (!strcmp(fmt, "%s")) {
+ va_start(ap, fmt);
+ argl = va_arg(ap, char *);
+ if (argl[0] == '<' && argl[1] && argl[2] == '>') {
+ switch ( argl[1] )
+ {
+ case '0':
+ priority = LOG_EMERG;
+ break;
+ case '1':
+ priority = LOG_ALERT;
+ break;
+ case '2':
+ priority = LOG_CRIT;
+ break;
+ case '3':
+ priority = LOG_ERR;
+ break;
+ case '4':
+ priority = LOG_WARNING;
+ break;
+ case '5':
+ priority = LOG_NOTICE;
+ break;
+ case '6':
+ priority = LOG_INFO;
+ break;
+ case '7':
+ default:
+ priority = LOG_DEBUG;
+ }
+ argl += 3;
+ }
+ writeSyslog(priority, fmt, argl);
+ va_end(ap);
+#ifdef TESTING
+ putchar('\n');
+#endif
+ return;
+ }
+
+ va_start(ap, fmt);
+ writeSyslogV(priority, fmt, ap);
+ va_end(ap);
+#ifdef TESTING
+ printf ("\n");
+#endif
+
+ return;
+}
+
+
+static void CloseLogSrc(void)
+{
+ /* Turn on logging of messages to console, but only if we had the -c
+ * option -- rgerhards, 2007-08-01
+ */
+ if (console_log_level != -1)
+ ksyslog(7, NULL, 0);
+
+ /* Shutdown the log sources. */
+ switch ( logsrc )
+ {
+ case kernel:
+ ksyslog(0, 0, 0);
+ Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped.");
+ break;
+ case proc:
+ close(kmsg);
+ Syslog(LOG_INFO, "Kernel logging (proc) stopped.");
+ break;
+ case none:
+ break;
+ }
+
+ if ( output_file != (FILE *) 0 )
+ fflush(output_file);
+ return;
+}
+
+
+void restart(int __attribute__((unused)) sig)
+{
+ change_state = 1;
+ caught_TSTP = 0;
+ return;
+}
+
+
+void stop_logging(int __attribute__((unused)) sig)
+{
+ change_state = 1;
+ caught_TSTP = 1;
+ return;
+}
+
+
+void stop_daemon(int __attribute__((unused)) sig)
+{
+ change_state = 1;
+ terminate = 1;
+ return;
+}
+
+
+void reload_daemon(int sig)
+{
+ change_state = 1;
+ reload_symbols = 1;
+
+ if ( sig == SIGUSR2 )
+ {
+ ++reload_symbols;
+ }
+
+ return;
+}
+
+
+static void Terminate(void)
+{
+ CloseLogSrc();
+ Syslog(LOG_INFO, "Kernel log daemon terminating.");
+ sleep(1);
+ if ( output_file != (FILE *) 0 )
+ fclose(output_file);
+ closelog();
+#ifndef TESTING
+ (void) remove_pid(PidFile);
+#endif
+ exit(1);
+}
+
+static void SignalDaemon(int sig)
+{
+#ifndef TESTING
+ auto int pid = check_pid(PidFile);
+
+ kill(pid, sig);
+#else
+ kill(getpid(), sig);
+#endif
+ return;
+}
+
+
+static void ReloadSymbols(void)
+{
+ if (symbol_lookup) {
+ if ( reload_symbols > 1 )
+ InitKsyms(symfile);
+ InitMsyms();
+ }
+ reload_symbols = change_state = 0;
+ return;
+}
+
+
+static void ChangeLogging(void)
+{
+ /* Terminate kernel logging. */
+ if ( terminate == 1 )
+ Terminate();
+
+ /* Indicate that something is happening. */
+ Syslog(LOG_INFO, "rklogd %s, ---------- state change ----------\n", \
+ VERSION);
+
+ /* Reload symbols. */
+ if ( reload_symbols > 0 )
+ {
+ ReloadSymbols();
+ return;
+ }
+
+ /* Stop kernel logging. */
+ if ( caught_TSTP == 1 )
+ {
+ CloseLogSrc();
+ logsrc = none;
+ change_state = 0;
+ return;
+ }
+
+ /*
+ * The rest of this function is responsible for restarting
+ * kernel logging after it was stopped.
+ *
+ * In the following section we make a decision based on the
+ * kernel log state as to what is causing us to restart. Somewhat
+ * groady but it keeps us from creating another static variable.
+ */
+ if ( logsrc != none )
+ {
+ Syslog(LOG_INFO, "Kernel logging re-started after SIGSTOP.");
+ change_state = 0;
+ return;
+ }
+
+ /* Restart logging. */
+ logsrc = GetKernelLogSrc();
+ change_state = 0;
+ return;
+}
+
+
+static enum LOGSRC GetKernelLogSrc(void)
+{
+ auto struct stat sb;
+
+ /* Set level of kernel console messaging.. */
+ if ( (console_log_level != -1) &&
+ (ksyslog(8, NULL, console_log_level) < 0) &&
+ (errno == EINVAL) )
+ {
+ /*
+ * An invalid arguement error probably indicates that
+ * a pre-0.14 kernel is being run. At this point we
+ * issue an error message and simply shut-off console
+ * logging completely.
+ */
+ Syslog(LOG_WARNING, "Cannot set console log level - disabling "
+ "console output.");
+ }
+
+ /*
+ * First do a stat to determine whether or not the proc based
+ * file system is available to get kernel messages from.
+ */
+ if ( use_syscall ||
+ ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
+ {
+ /* Initialize kernel logging. */
+ ksyslog(1, NULL, 0);
+#ifdef DEBRELEASE
+ Syslog(LOG_INFO, "rklogd %s#%s, log source = ksyslog "
+ "started.", VERSION, DEBRELEASE);
+#else
+ Syslog(LOG_INFO, "rklogd %s, log source = ksyslog "
+ "started.", VERSION);
+#endif
+ return(kernel);
+ }
+
+#ifndef TESTING
+ if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
+ {
+ fprintf(stderr, "rklogd: Cannot open proc file system, " \
+ "%d - %s.\n", errno, strerror(errno));
+ ksyslog(7, NULL, 0);
+ exit(1);
+ }
+#else
+ kmsg = fileno(stdin);
+#endif
+
+#ifdef DEBRELEASE
+ Syslog(LOG_INFO, "rklogd %ss#%s, log source = %s started.", \
+ VERSION, DEBRELEASE, _PATH_KLOG);
+#else
+ Syslog(LOG_INFO, "rklogd %s, log source = %s started.", \
+ VERSION, _PATH_KLOG);
+#endif
+ return(proc);
+}
+
+
+/*
+ * Copy characters from ptr to line until a char in the delim
+ * string is encountered or until min( space, len ) chars have
+ * been copied.
+ *
+ * Returns the actual number of chars copied.
+ */
+static int copyin( char *line, int space,
+ const char *ptr, int len,
+ const char *delim )
+{
+ auto int i;
+ auto int count;
+
+ count = len < space ? len : space;
+
+ for(i=0; i<count && !strchr(delim, *ptr); i++ ) {
+ *line++ = *ptr++;
+ }
+
+ return( i );
+}
+
+/*
+ * Messages are separated by "\n". Messages longer than
+ * LOG_LINE_LENGTH are broken up.
+ *
+ * Kernel symbols show up in the input buffer as : "[<aaaaaa>]",
+ * where "aaaaaa" is the address. These are replaced with
+ * "[symbolname+offset/size]" in the output line - symbolname,
+ * offset, and size come from the kernel symbol table.
+ *
+ * If a kernel symbol happens to fall at the end of a message close
+ * in length to LOG_LINE_LENGTH, the symbol will not be expanded.
+ * (This should never happen, since the kernel should never generate
+ * messages that long.
+ *
+ * To preserve the original addresses, lines containing kernel symbols
+ * are output twice. Once with the symbols converted and again with the
+ * original text. Just in case somebody wants to run their own Oops
+ * analysis on the syslog, e.g. ksymoops.
+ */
+static void LogLine(char *ptr, int len)
+{
+ enum parse_state_enum {
+ PARSING_TEXT,
+ PARSING_SYMSTART, /* at < */
+ PARSING_SYMBOL,
+ PARSING_SYMEND /* at ] */
+ };
+
+ static char line_buff[LOG_LINE_LENGTH];
+
+ static char *line =line_buff;
+ static enum parse_state_enum parse_state = PARSING_TEXT;
+ static int space = sizeof(line_buff)-1;
+
+ static char *sym_start; /* points at the '<' of a symbol */
+
+ auto int delta = 0; /* number of chars copied */
+ auto int symbols_expanded = 0; /* 1 if symbols were expanded */
+ auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */
+ auto char *save_ptr = ptr; /* save start of input line */
+ auto int save_len = len; /* save length at start of input line */
+
+ while( len > 0 )
+ {
+ if( space == 0 ) /* line buffer is full */
+ {
+ /*
+ ** Line too long. Start a new line.
+ */
+ *line = 0; /* force null terminator */
+
+ if ( debugging )
+ {
+ fputs("Line buffer full:\n", stderr);
+ fprintf(stderr, "\tLine: %s\n", line);
+ }
+
+ Syslog( LOG_INFO, "%s", line_buff );
+ line = line_buff;
+ space = sizeof(line_buff)-1;
+ parse_state = PARSING_TEXT;
+ symbols_expanded = 0;
+ skip_symbol_lookup = 0;
+ save_ptr = ptr;
+ save_len = len;
+ }
+
+ switch( parse_state )
+ {
+ case PARSING_TEXT:
+ delta = copyin( line, space, ptr, len, "\n[" );
+ line += delta;
+ ptr += delta;
+ space -= delta;
+ len -= delta;
+
+ if( space == 0 || len == 0 )
+ {
+ break; /* full line_buff or end of input buffer */
+ }
+
+ if( *ptr == '\0' ) /* zero byte */
+ {
+ ptr++; /* skip zero byte */
+ space -= 1;
+ len -= 1;
+
+ break;
+ }
+
+ if( *ptr == '\n' ) /* newline */
+ {
+ ptr++; /* skip newline */
+ space -= 1;
+ len -= 1;
+
+ *line = 0; /* force null terminator */
+ Syslog( LOG_INFO, "%s", line_buff );
+ line = line_buff;
+ space = sizeof(line_buff)-1;
+ if (symbols_twice) {
+ if (symbols_expanded) {
+ /* reprint this line without symbol lookup */
+ symbols_expanded = 0;
+ skip_symbol_lookup = 1;
+ ptr = save_ptr;
+ len = save_len;
+ }
+ else
+ {
+ skip_symbol_lookup = 0;
+ save_ptr = ptr;
+ save_len = len;
+ }
+ }
+ break;
+ }
+ if( *ptr == '[' ) /* possible kernel symbol */
+ {
+ *line++ = *ptr++;
+ space -= 1;
+ len -= 1;
+ if (!skip_symbol_lookup)
+ parse_state = PARSING_SYMSTART; /* at < */
+ break;
+ }
+ /* Now that line_buff is no longer fed to *printf as format
+ * string, '%'s are no longer "dangerous".
+ */
+ break;
+
+ case PARSING_SYMSTART:
+ if( *ptr != '<' )
+ {
+ parse_state = PARSING_TEXT; /* not a symbol */
+ break;
+ }
+
+ /*
+ ** Save this character for now. If this turns out to
+ ** be a valid symbol, this char will be replaced later.
+ ** If not, we'll just leave it there.
+ */
+
+ sym_start = line; /* this will point at the '<' */
+
+ *line++ = *ptr++;
+ space -= 1;
+ len -= 1;
+ parse_state = PARSING_SYMBOL; /* symbol... */
+ break;
+
+ case PARSING_SYMBOL:
+ delta = copyin( line, space, ptr, len, ">\n[" );
+ line += delta;
+ ptr += delta;
+ space -= delta;
+ len -= delta;
+ if( space == 0 || len == 0 )
+ {
+ break; /* full line_buff or end of input buffer */
+ }
+ if( *ptr != '>' )
+ {
+ parse_state = PARSING_TEXT;
+ break;
+ }
+
+ *line++ = *ptr++; /* copy the '>' */
+ space -= 1;
+ len -= 1;
+
+ parse_state = PARSING_SYMEND;
+
+ break;
+
+ case PARSING_SYMEND:
+ if( *ptr != ']' )
+ {
+ parse_state = PARSING_TEXT; /* not a symbol */
+ break;
+ }
+
+ /*
+ ** It's really a symbol! Replace address with the
+ ** symbol text.
+ */
+ {
+ auto int sym_space;
+
+ unsigned long value;
+ auto struct symbol sym;
+ auto char *symbol;
+
+ *(line-1) = 0; /* null terminate the address string */
+ value = strtoul(sym_start+1, (char **) 0, 16);
+ *(line-1) = '>'; /* put back delim */
+
+ if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 )
+ {
+ parse_state = PARSING_TEXT;
+ break;
+ }
+
+ /*
+ ** verify there is room in the line buffer
+ */
+ sym_space = space + ( line - sym_start );
+ if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/
+ {
+ parse_state = PARSING_TEXT; /* not enough space */
+ break;
+ }
+
+ delta = sprintf( sym_start, "%s+%d/%d]",
+ symbol, sym.offset, sym.size );
+
+ space = sym_space + delta;
+ line = sym_start + delta;
+ symbols_expanded = 1;
+ }
+ ptr++;
+ len--;
+ parse_state = PARSING_TEXT;
+ break;
+
+ default: /* Can't get here! */
+ parse_state = PARSING_TEXT;
+
+ }
+ }
+
+ return;
+}
+
+
+static void LogKernelLine(void)
+{
+ auto int rdcnt;
+
+ /*
+ * Zero-fill the log buffer. This should cure a multitude of
+ * problems with klogd logging the tail end of the message buffer
+ * which will contain old messages. Then read the kernel log
+ * messages into this fresh buffer.
+ */
+ memset(log_buffer, '\0', sizeof(log_buffer));
+ if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 )
+ {
+ if ( errno == EINTR )
+ return;
+ fprintf(stderr, "rklogd: Error return from sys_sycall: " \
+ "%d - %s\n", errno, strerror(errno));
+ }
+ else
+ LogLine(log_buffer, rdcnt);
+ return;
+}
+
+
+static void LogProcLine(void)
+{
+ auto int rdcnt;
+
+ /*
+ * Zero-fill the log buffer. This should cure a multitude of
+ * problems with klogd logging the tail end of the message buffer
+ * which will contain old messages. Then read the kernel messages
+ * from the message pseudo-file into this fresh buffer.
+ */
+ memset(log_buffer, '\0', sizeof(log_buffer));
+ if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 )
+ {
+ if ( errno == EINTR )
+ return;
+ Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", \
+ errno, strerror(errno));
+ }
+ else
+ LogLine(log_buffer, rdcnt);
+
+ return;
+}
+
+
+/* helper routine to spit out an error message and terminate
+ * klogd when setting a signal error fails.
+ */
+void sigactionErrAbort()
+{
+ fprintf(stderr, "rklogd: could net set a signal handler - terminating. Error: %s\n",
+ strerror(errno));
+ exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int ch,
+ use_output = 0;
+
+ char *log_level = (char *) 0,
+ *output = (char *) 0;
+ struct sigaction sigAct;
+
+#ifndef TESTING
+ chdir ("/");
+#endif
+ /* Parse the command-line. */
+ while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF)
+ switch((char)ch)
+ {
+ case '2': /* Print lines with symbols twice. */
+ symbols_twice = 1;
+ break;
+ case 'c': /* Set console message level. */
+ log_level = optarg;
+ break;
+ case 'd': /* Activity debug mode. */
+ debugging = 1;
+ break;
+ case 'f': /* Define an output file. */
+ output = optarg;
+ use_output++;
+ break;
+ case 'i': /* Reload module symbols. */
+ SignalDaemon(SIGUSR1);
+ return(0);
+ case 'I':
+ SignalDaemon(SIGUSR2);
+ return(0);
+ case 'k': /* Kernel symbol file. */
+ symfile = optarg;
+ break;
+ case 'n': /* don't fork */
+ no_fork++;
+ break;
+ case 'o': /* One-shot mode. */
+ one_shot = 1;
+ break;
+ case 'p':
+ SetParanoiaLevel(1); /* Load symbols on oops. */
+ break;
+ case 's': /* Use syscall interface. */
+ use_syscall = 1;
+ break;
+ case 'v':
+ printf("rklogd %s\n", VERSION);
+ exit (1);
+ case 'x':
+ symbol_lookup = 0;
+ break;
+ }
+
+
+ /* Set console logging level. */
+ if ( log_level != (char *) 0 )
+ {
+ if ( (strlen(log_level) > 1) || \
+ (strchr("12345678", *log_level) == (char *) 0) )
+ {
+ fprintf(stderr, "rklogd: Invalid console logging "
+ "level <%s> specified.\n", log_level);
+ return(1);
+ }
+ console_log_level = *log_level - '0';
+ }
+
+
+#ifndef TESTING
+ /*
+ * The following code allows klogd to auto-background itself.
+ * What happens is that the program forks and the parent quits.
+ * The child closes all its open file descriptors, and issues a
+ * call to setsid to establish itself as an independent session
+ * immune from control signals.
+ *
+ * fork() is only called if it should run in daemon mode, fork is
+ * not disabled with the command line argument and there's no
+ * such process running.
+ */
+ if ( (!one_shot) && (!no_fork) )
+ {
+ if (!check_pid(PidFile))
+ {
+ if ( fork() == 0 )
+ {
+ auto int fl;
+ int num_fds = getdtablesize();
+
+ /* This is the child closing its file descriptors. */
+ for (fl= 0; fl <= num_fds; ++fl)
+ {
+ if ( fileno(stdout) == fl && use_output )
+ if ( strcmp(output, "-") == 0 )
+ continue;
+ close(fl);
+ }
+
+ setsid();
+ }
+ else
+ exit(0);
+ }
+ else
+ {
+ fputs("rklogd: Already running.\n", stderr);
+ exit(1);
+ }
+ }
+
+
+ /* tuck my process id away */
+ if (!check_pid(PidFile))
+ {
+ if (!write_pid(PidFile))
+ Terminate();
+ }
+ else
+ {
+ fputs("rklogd: Already running.\n", stderr);
+ Terminate();
+ }
+#endif
+
+ /* Signal setups.
+ * Please note that the "original" klogd in sysklogd tries to
+ * handle SIGKILL and SIGSTOP. That does not work - but as the
+ * original klogd had no error checking, nobody ever noticed. We
+ * do now have error checking and consequently those ever-failing
+ * calls are now removed.
+ */
+ sigemptyset(&sigAct.sa_mask);
+ sigAct.sa_flags = 0;
+
+ /* first, set all signals to ignore
+ * In this loop, we try blindly to ignore all signals. I am leaving
+ * intentionally out all error checking. If we can ignore the signal,
+ * that's nice, but if we can't ... well, so be it ;)
+ * RGerhards, 2007-06-15
+ */
+ sigAct.sa_handler = SIG_IGN;
+ for (ch= 1; ch < NSIG ; ++ch)
+ {
+ if(ch != SIGKILL && ch != SIGSTOP)
+ sigaction(ch, &sigAct, NULL);
+ }
+
+ /* Now specific handlers (one after another) */
+ sigAct.sa_handler = stop_daemon;
+ if(sigaction(SIGINT, &sigAct, NULL) != 0) sigactionErrAbort();
+ if(sigaction(SIGTERM, &sigAct, NULL) != 0) sigactionErrAbort();
+ if(sigaction(SIGHUP, &sigAct, NULL) != 0) sigactionErrAbort();
+
+ sigAct.sa_handler = stop_daemon;
+ if(sigaction(SIGTSTP, &sigAct, NULL) != 0) sigactionErrAbort();
+
+ sigAct.sa_handler = restart;
+ if(sigaction(SIGCONT, &sigAct, NULL) != 0) sigactionErrAbort();
+
+ sigAct.sa_handler = reload_daemon;
+ if(sigaction(SIGUSR1, &sigAct, NULL) != 0) sigactionErrAbort();
+ if(sigaction(SIGUSR2, &sigAct, NULL) != 0) sigactionErrAbort();
+
+
+ /* Open outputs. */
+ if ( use_output )
+ {
+ if ( strcmp(output, "-") == 0 )
+ output_file = stdout;
+ else if ( (output_file = fopen(output, "w")) == (FILE *) 0 )
+ {
+ fprintf(stderr, "rklogd: Cannot open output file " \
+ "%s - %s\n", output, strerror(errno));
+ return(1);
+ }
+ }
+
+ /* Handle one-shot logging. */
+ if ( one_shot )
+ {
+ if (symbol_lookup) {
+ symbol_lookup = (InitKsyms(symfile) == 1);
+ symbol_lookup |= InitMsyms();
+ if (symbol_lookup == 0) {
+ Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n");
+ }
+ }
+ if ( (logsrc = GetKernelLogSrc()) == kernel )
+ LogKernelLine();
+ else
+ LogProcLine();
+ Terminate();
+ }
+
+ /* Determine where kernel logging information is to come from. */
+#if defined(KLOGD_DELAY)
+ sleep(KLOGD_DELAY);
+#endif
+ logsrc = GetKernelLogSrc();
+ if (symbol_lookup) {
+ symbol_lookup = (InitKsyms(symfile) == 1);
+ symbol_lookup |= InitMsyms();
+ if (symbol_lookup == 0) {
+ Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n");
+ }
+ }
+
+ /* The main loop. */
+ /* The main loop will be broken by a signal handler which set the
+ * terminate variable. That is then cheked in ChangeLogging(), which
+ * will then terminate klogd.
+ * RGerhards, 2007-06-15
+ */
+ while(1)
+ {
+ if ( change_state )
+ ChangeLogging();
+ switch ( logsrc )
+ {
+ case kernel:
+ LogKernelLine();
+ break;
+ case proc:
+ LogProcLine();
+ break;
+ case none:
+ pause();
+ break;
+ }
+ }
+}
+#else /* #ifdef FEATURE_KLOGD */
+#include <stdio.h>
+int main()
+{
+ fprintf(stderr, "FEATURE_KLOGD was disabled during make, so rklogd is not available.\n");
+ return(1);
+}
+#endif /* #ifdef WITH_KLOGD */
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/klogd.h b/klogd.h
new file mode 100644
index 0000000..1343f40
--- /dev/null
+++ b/klogd.h
@@ -0,0 +1,44 @@
+/*
+ klogd.h - main header file for Linux kernel log daemon.
+ Copyright (c) 1995 Dr. G.W. Wettstein <greg@wind.rmcc.com>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * Symbols and definitions needed by klogd.
+ *
+ * Thu Nov 16 12:45:06 CST 1995: Dr. Wettstein
+ * Initial version.
+ */
+
+/* Useful include files. */
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdarg.h>
+#undef syslog
+#undef vsyslog
+
+/* Function prototypes. */
+extern int InitKsyms(char *);
+extern int InitMsyms(void);
+extern char * ExpandKadds(char *, char *);
+extern void SetParanoiaLevel(int);
+extern void Syslog(int priority, char *fmt, ...);
+extern void vsyslog(int pri, const char *fmt, va_list ap);
+extern void openlog(const char *ident, int logstat, int logfac);
diff --git a/ksym.c b/ksym.c
new file mode 100644
index 0000000..8dff9ac
--- /dev/null
+++ b/ksym.c
@@ -0,0 +1,985 @@
+#include "config.h"
+
+#ifdef FEATURE_KLOGD
+/*
+ ksym.c - functions for kernel address->symbol translation
+ Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
+ Copyright (c) 1996 Enjellic Systems Development
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * This file contains functions which handle the translation of kernel
+ * numeric addresses into symbols for the klogd utility.
+ *
+ * Sat Oct 28 09:00:14 CDT 1995: Dr. Wettstein
+ * Initial Version.
+ *
+ * Fri Nov 24 12:50:52 CST 1995: Dr. Wettstein
+ * Added VERBOSE_DEBUGGING define to make debugging output more
+ * manageable.
+ *
+ * Added support for verification of the loaded kernel symbols. If
+ * no version information can be be found in the mapfile a warning
+ * message is issued but translation will still take place. This
+ * will be the default case if kernel versions < 1.3.43 are used.
+ *
+ * If the symbols in the mapfile are of the same version as the kernel
+ * that is running an informative message is issued. If the symbols
+ * in the mapfile do not match the current kernel version a warning
+ * message is issued and translation is disabled.
+ *
+ * Wed Dec 6 16:14:11 CST 1995: Dr. Wettstein
+ * Added /boot/System.map to the list of symbol maps to search for.
+ * Also made this map the first item in the search list. I am open
+ * to CONSTRUCTIVE suggestions for any additions or corrections to
+ * the list of symbol maps to search for. Be forewarned that the
+ * list in use is the consensus agreement between myself, Linus and
+ * some package distributers. It is a given that no list will suit
+ * everyone's taste. If you have rabid concerns about the list
+ * please feel free to edit the system_maps array and compile your
+ * own binaries.
+ *
+ * Added support for searching of the list of symbol maps. This
+ * allows support for access to multiple symbol maps. The theory
+ * behind this is that a production kernel may have a system map in
+ * /boot/System.map. If a test kernel is booted this system map
+ * would be skipped in favor of one found in /usr/src/linux.
+ *
+ * Thu Jan 18 11:18:31 CST 1996: Dr. Wettstein
+ * Added patch from beta-testers to allow for reading of both
+ * ELF and a.out map files.
+ *
+ * Wed Aug 21 09:15:49 CDT 1996: Dr. Wettstein
+ * Reloading of kernel module symbols is now turned on by the
+ * SetParanoiaLevel function. The default behavior is to NOT reload
+ * the kernel module symbols when a protection fault is detected.
+ *
+ * Added support for freeing of the current kernel module symbols.
+ * This was necessary to support reloading of the kernel module symbols.
+ *
+ * When a matching static symbol table is loaded the kernel version
+ * number is printed.
+ *
+ * Mon Jun 9 17:12:42 CST 1997: Martin Schulze
+ * Added #1 and #2 to some error messages in order to being able
+ * to divide them (ulmo@Q.Net)
+ *
+ * Fri Jun 13 10:50:23 CST 1997: Martin Schulze
+ * Changed definition of LookupSymbol to non-static because it is
+ * used in klogd.c, too.
+ *
+ * Fri Jan 9 23:00:08 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed bug that caused klogd to die if there is no System.map available.
+ *
+ * Sun 29 Mar 18:14:07 BST 1998: Mark Simon Phillips <M.S.Phillips@nortel.co.uk>
+ * Switched to fgets() as gets() is not buffer overrun secure.
+ *
+ * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified loop for detecting the correct system map. Now it won't
+ * stop if a file has been found but doesn't contain the correct map.
+ * Special thanks go go Mark Simon Phillips for the hint.
+ *
+ * Mon Oct 12 00:42:30 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Modified CheckVersion()
+ * . Use shift to decode the kernel version
+ * . Compare integers of kernel version
+ * . extract major.minor.patch from utsname.release via sscanf()
+ * The reason lays in possible use of kernel flavours which
+ * modify utsname.release but no the Version_ symbol.
+ *
+ * Sun Feb 21 22:27:49 EST 1999: Keith Owens <kaos@ocs.com.au>
+ * Fixed bug that caused klogd to die if there is no sym_array available.
+ *
+ * Tue Sep 12 23:48:12 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Close symbol file in InitKsyms() when an error occurred.
+ */
+
+
+/* Includes. */
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <ctype.h>
+#include "klogd.h"
+#include "ksyms.h"
+
+#define VERBOSE_DEBUGGING 0
+
+
+/* Variables static to this module. */
+struct sym_table
+{
+ unsigned long value;
+ char *name;
+};
+
+static int num_syms = 0;
+static int i_am_paranoid = 0;
+static char vstring[12];
+static struct sym_table *sym_array = (struct sym_table *) 0;
+
+static char *system_maps[] =
+{
+ "/boot/System.map",
+ "/System.map",
+#if defined(TEST)
+ "./System.map",
+#endif
+ (char *) 0
+};
+
+
+#if defined(TEST)
+int debugging;
+#else
+extern int debugging;
+#endif
+
+
+/* Function prototypes. */
+static char * FindSymbolFile(void);
+static int AddSymbol(unsigned long, char*);
+static void FreeSymbols(void);
+static int CheckVersion(char *);
+static int CheckMapVersion(char *);
+
+
+/**************************************************************************
+ * Function: InitKsyms
+ *
+ * Purpose: This function is responsible for initializing and loading
+ * the data tables used by the kernel address translations.
+ *
+ * Arguements: (char *) mapfile
+ *
+ * mapfile:-> A pointer to a complete path
+ * specification of the file containing
+ * the kernel map to use.
+ *
+ * Return: int
+ *
+ * A boolean style context is returned. The return value will
+ * be true if initialization was successful. False if not.
+ **************************************************************************/
+
+extern int InitKsyms(mapfile)
+
+ char *mapfile;
+
+{
+ auto char type,
+ sym[512];
+
+ auto int version = 0;
+
+ auto unsigned long int address;
+
+ auto FILE *sym_file;
+
+
+ /* Check and make sure that we are starting with a clean slate. */
+ if ( num_syms > 0 )
+ FreeSymbols();
+
+
+ /*
+ * Search for and open the file containing the kernel symbols.
+ */
+ if ( mapfile != (char *) 0 )
+ {
+ if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 )
+ {
+ Syslog(LOG_WARNING, "Cannot open map file: %s.", \
+ mapfile);
+ return(0);
+ }
+ }
+ else
+ {
+ if ( (mapfile = FindSymbolFile()) == (char *) 0 )
+ {
+ Syslog(LOG_WARNING, "Cannot find map file.");
+ if ( debugging )
+ fputs("Cannot find map file.\n", stderr);
+ return(0);
+ }
+
+ if ( (sym_file = fopen(mapfile, "r")) == (FILE *) 0 )
+ {
+ Syslog(LOG_WARNING, "Cannot open map file.");
+ if ( debugging )
+ fputs("Cannot open map file.\n", stderr);
+ return(0);
+ }
+ }
+
+
+ /*
+ * Read the kernel symbol table file and add entries for each
+ * line. I suspect that the use of fscanf is not really in vogue
+ * but it was quick and dirty and IMHO suitable for fixed format
+ * data such as this. If anybody doesn't agree with this please
+ * e-mail me a diff containing a parser with suitable political
+ * correctness -- GW.
+ */
+ while ( !feof(sym_file) )
+ {
+ if ( fscanf(sym_file, "%lx %c %s\n", &address, &type, sym)
+ != 3 )
+ {
+ Syslog(LOG_ERR, "Error in symbol table input (#1).");
+ fclose(sym_file);
+ return(0);
+ }
+ if ( VERBOSE_DEBUGGING && debugging )
+ fprintf(stderr, "Address: %lx, Type: %c, Symbol: %s\n",
+ address, type, sym);
+
+ if ( AddSymbol(address, sym) == 0 )
+ {
+ Syslog(LOG_ERR, "Error adding symbol - %s.", sym);
+ fclose(sym_file);
+ return(0);
+ }
+
+ if ( version == 0 )
+ version = CheckVersion(sym);
+ }
+
+
+ Syslog(LOG_INFO, "Loaded %d symbols from %s.", num_syms, mapfile);
+ switch ( version )
+ {
+ case -1:
+ Syslog(LOG_WARNING, "Symbols do not match kernel version.");
+ num_syms = 0;
+ break;
+
+ case 0:
+ Syslog(LOG_WARNING, "Cannot verify that symbols match " \
+ "kernel version.");
+ break;
+
+ case 1:
+ Syslog(LOG_INFO, "Symbols match kernel version %s.", vstring);
+ break;
+ }
+
+ fclose(sym_file);
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: FindSymbolFile
+ *
+ * Purpose: This function is responsible for encapsulating the search
+ * for a valid symbol file. Encapsulating the search for
+ * the map file in this function allows an intelligent search
+ * process to be implemented.
+ *
+ * The list of symbol files will be searched until either a
+ * symbol file is found whose version matches the currently
+ * executing kernel or the end of the list is encountered. If
+ * the end of the list is encountered the first available
+ * symbol file is returned to the caller.
+ *
+ * This strategy allows klogd to locate valid symbol files
+ * for both a production and an experimental kernel. For
+ * example a map for a production kernel could be installed
+ * in /boot. If an experimental kernel is loaded the map
+ * in /boot will be skipped and the map in /usr/src/linux would
+ * be used if its version number matches the executing kernel.
+ *
+ * Arguements: None specified.
+ *
+ * Return: char *
+ *
+ * If a valid system map cannot be located a null pointer
+ * is returned to the caller.
+ *
+ * If the search is succesful a pointer is returned to the
+ * caller which points to the name of the file containing
+ * the symbol table to be used.
+ **************************************************************************/
+
+static char * FindSymbolFile()
+
+{
+ auto char *file = (char *) 0,
+ **mf = system_maps;
+
+ auto struct utsname utsname;
+ static char symfile[100];
+
+ auto FILE *sym_file = (FILE *) 0;
+
+ if ( uname(&utsname) < 0 )
+ {
+ Syslog(LOG_ERR, "Cannot get kernel version information.");
+ return(0);
+ }
+
+ if ( debugging )
+ fputs("Searching for symbol map.\n", stderr);
+
+ for (mf = system_maps; *mf != (char *) 0 && file == (char *) 0; ++mf)
+ {
+
+ sprintf (symfile, "%s-%s", *mf, utsname.release);
+ if ( debugging )
+ fprintf(stderr, "Trying %s.\n", symfile);
+ if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) {
+ if (CheckMapVersion(symfile) == 1)
+ file = symfile;
+ fclose(sym_file);
+ }
+ if (sym_file == (FILE *) 0 || file == (char *) 0) {
+ sprintf (symfile, "%s", *mf);
+ if ( debugging )
+ fprintf(stderr, "Trying %s.\n", symfile);
+ if ( (sym_file = fopen(symfile, "r")) != (FILE *) 0 ) {
+ if (CheckMapVersion(symfile) == 1)
+ file = symfile;
+ fclose(sym_file);
+ }
+ }
+
+ }
+
+ /*
+ * At this stage of the game we are at the end of the symbol
+ * tables.
+ */
+ if ( debugging )
+ fprintf(stderr, "End of search list encountered.\n");
+ return(file);
+}
+
+
+/**************************************************************************
+ * Function: CheckVersion
+ *
+ * Purpose: This function is responsible for determining whether or
+ * the system map being loaded matches the version of the
+ * currently running kernel.
+ *
+ * The kernel version is checked by examing a variable which
+ * is of the form: _Version_66347 (a.out) or Version_66437 (ELF).
+ *
+ * The suffix of this variable is the current kernel version
+ * of the kernel encoded in base 256. For example the
+ * above variable would be decoded as:
+ *
+ * (66347 = 1*65536 + 3*256 + 43 = 1.3.43)
+ *
+ * (Insert appropriate deities here) help us if Linus ever
+ * needs more than 255 patch levels to get a kernel out the
+ * door... :-)
+ *
+ * Arguements: (char *) version
+ *
+ * version:-> A pointer to the string which
+ * is to be decoded as a kernel
+ * version variable.
+ *
+ * Return: int
+ *
+ * -1:-> The currently running kernel version does
+ * not match this version string.
+ *
+ * 0:-> The string is not a kernel version variable.
+ *
+ * 1:-> The executing kernel is of the same version
+ * as the version string.
+ **************************************************************************/
+
+static int CheckVersion(version)
+
+ char *version;
+
+
+{
+ auto int vnum,
+ major,
+ minor,
+ patch;
+
+#ifndef TESTING
+ int kvnum;
+ auto struct utsname utsname;
+#endif
+
+ static char *prefix = { "Version_" };
+
+
+ /* Early return if there is no hope. */
+ if ( strncmp(version, prefix, strlen(prefix)) == 0 /* ELF */ ||
+ (*version == '_' &&
+ strncmp(++version, prefix, strlen(prefix)) == 0 ) /* a.out */ )
+ ;
+ else
+ return(0);
+
+
+ /*
+ * Since the symbol looks like a kernel version we can start
+ * things out by decoding the version string into its component
+ * parts.
+ */
+ vnum = atoi(version + strlen(prefix));
+ patch = vnum & 0x000000FF;
+ minor = (vnum >> 8) & 0x000000FF;
+ major = (vnum >> 16) & 0x000000FF;
+ if ( debugging )
+ fprintf(stderr, "Version string = %s, Major = %d, " \
+ "Minor = %d, Patch = %d.\n", version +
+ strlen(prefix), major, minor, \
+ patch);
+ sprintf(vstring, "%d.%d.%d", major, minor, patch);
+
+#ifndef TESTING
+ /*
+ * We should now have the version string in the vstring variable in
+ * the same format that it is stored in by the kernel. We now
+ * ask the kernel for its version information and compare the two
+ * values to determine if our system map matches the kernel
+ * version level.
+ */
+ if ( uname(&utsname) < 0 )
+ {
+ Syslog(LOG_ERR, "Cannot get kernel version information.");
+ return(0);
+ }
+ if ( debugging )
+ fprintf(stderr, "Comparing kernel %s with symbol table %s.\n",\
+ utsname.release, vstring);
+
+ if ( sscanf (utsname.release, "%d.%d.%d", &major, &minor, &patch) < 3 )
+ {
+ Syslog(LOG_ERR, "Kernel send bogus release string `%s'.",
+ utsname.release);
+ return(0);
+ }
+
+ /* Compute the version code from data sent by the kernel */
+ kvnum = (major << 16) | (minor << 8) | patch;
+
+ /* Failure. */
+ if ( vnum != kvnum )
+ return(-1);
+
+ /* Success. */
+#endif
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: CheckMapVersion
+ *
+ * Purpose: This function is responsible for determining whether or
+ * the system map being loaded matches the version of the
+ * currently running kernel. It uses CheckVersion as
+ * backend.
+ *
+ * Arguements: (char *) fname
+ *
+ * fname:-> A pointer to the string which
+ * references the system map file to
+ * be used.
+ *
+ * Return: int
+ *
+ * -1:-> The currently running kernel version does
+ * not match the version in the given file.
+ *
+ * 0:-> No system map file or no version information.
+ *
+ * 1:-> The executing kernel is of the same version
+ * as the version of the map file.
+ **************************************************************************/
+
+static int CheckMapVersion(fname)
+
+ char *fname;
+
+
+{
+ int version;
+ FILE *sym_file;
+ auto unsigned long int address;
+ auto char type,
+ sym[512];
+
+ if ( (sym_file = fopen(fname, "r")) != (FILE *) 0 ) {
+ /*
+ * At this point a map file was successfully opened. We
+ * now need to search this file and look for version
+ * information.
+ */
+ Syslog(LOG_INFO, "Inspecting %s", fname);
+
+ version = 0;
+ while ( !feof(sym_file) && (version == 0) )
+ {
+ if ( fscanf(sym_file, "%lx %c %s\n", &address, \
+ &type, sym) != 3 )
+ {
+ Syslog(LOG_ERR, "Error in symbol table input (#2).");
+ fclose(sym_file);
+ return(0);
+ }
+ if ( VERBOSE_DEBUGGING && debugging )
+ fprintf(stderr, "Address: %lx, Type: %c, " \
+ "Symbol: %s\n", address, type, sym);
+
+ version = CheckVersion(sym);
+ }
+ fclose(sym_file);
+
+ switch ( version )
+ {
+ case -1:
+ Syslog(LOG_ERR, "Symbol table has incorrect " \
+ "version number.\n");
+ break;
+
+ case 0:
+ if ( debugging )
+ fprintf(stderr, "No version information " \
+ "found.\n");
+ break;
+ case 1:
+ if ( debugging )
+ fprintf(stderr, "Found table with " \
+ "matching version number.\n");
+ break;
+ }
+
+ return(version);
+ }
+
+ return(0);
+}
+
+
+/**************************************************************************
+ * Function: AddSymbol
+ *
+ * Purpose: This function is responsible for adding a symbol name
+ * and its address to the symbol table.
+ *
+ * Arguements: (unsigned long) address, (char *) symbol
+ *
+ * Return: int
+ *
+ * A boolean value is assumed. True if the addition is
+ * successful. False if not.
+ **************************************************************************/
+
+static int AddSymbol(address, symbol)
+
+ unsigned long address;
+
+ char *symbol;
+
+{
+ /* Allocate the the symbol table entry. */
+ sym_array = (struct sym_table *) realloc(sym_array, (num_syms+1) * \
+ sizeof(struct sym_table));
+ if ( sym_array == (struct sym_table *) 0 )
+ return(0);
+
+ /* Then the space for the symbol. */
+ sym_array[num_syms].name = (char *) malloc(strlen(symbol)*sizeof(char)\
+ + 1);
+ if ( sym_array[num_syms].name == (char *) 0 )
+ return(0);
+
+ sym_array[num_syms].value = address;
+ strcpy(sym_array[num_syms].name, symbol);
+ ++num_syms;
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: LookupSymbol
+ *
+ * Purpose: Find the symbol which is related to the given kernel
+ * address.
+ *
+ * Arguements: (long int) value, (struct symbol *) sym
+ *
+ * value:-> The address to be located.
+ *
+ * sym:-> A pointer to a structure which will be
+ * loaded with the symbol's parameters.
+ *
+ * Return: (char *)
+ *
+ * If a match cannot be found a diagnostic string is printed.
+ * If a match is found the pointer to the symbolic name most
+ * closely matching the address is returned.
+ **************************************************************************/
+
+char * LookupSymbol(value, sym)
+
+ unsigned long value;
+
+ struct symbol *sym;
+
+{
+ auto int lp;
+
+ auto char *last;
+
+ if (!sym_array)
+ return((char *) 0);
+
+ last = sym_array[0].name;
+ sym->offset = 0;
+ sym->size = 0;
+ if ( value < sym_array[0].value )
+ return((char *) 0);
+
+ for(lp= 0; lp <= num_syms; ++lp)
+ {
+ if ( sym_array[lp].value > value )
+ {
+ sym->offset = value - sym_array[lp-1].value;
+ sym->size = sym_array[lp].value - \
+ sym_array[lp-1].value;
+ return(last);
+ }
+ last = sym_array[lp].name;
+ }
+
+ if ( (last = LookupModuleSymbol(value, sym)) != (char *) 0 )
+ return(last);
+
+ return((char *) 0);
+}
+
+
+/**************************************************************************
+ * Function: FreeSymbols
+ *
+ * Purpose: This function is responsible for freeing all memory which
+ * has been allocated to hold the static symbol table. It
+ * also initializes the symbol count and in general prepares
+ * for a re-read of a static symbol table.
+ *
+ * Arguements: void
+ *
+ * Return: void
+ **************************************************************************/
+
+static void FreeSymbols()
+
+{
+ auto int lp;
+
+ /* Free each piece of memory allocated for symbol names. */
+ for(lp= 0; lp < num_syms; ++lp)
+ free(sym_array[lp].name);
+
+ /* Whack the entire array and initialize everything. */
+ free(sym_array);
+ sym_array = (struct sym_table *) 0;
+ num_syms = 0;
+
+ return;
+}
+
+
+/**************************************************************************
+ * Function: LogExpanded
+ *
+ * Purpose: This function is responsible for logging a kernel message
+ * line after all potential numeric kernel addresses have
+ * been resolved symolically.
+ *
+ * Arguements: (char *) line, (char *) el
+ *
+ * line:-> A pointer to the buffer containing the kernel
+ * message to be expanded and logged.
+ *
+ * el:-> A pointer to the buffer into which the expanded
+ * kernel line will be written.
+ *
+ * Return: void
+ **************************************************************************/
+
+extern char * ExpandKadds(line, el)
+
+ char *line;
+
+ char *el;
+
+{
+ auto char dlm,
+ *kp,
+ *sl = line,
+ *elp = el,
+ *symbol;
+
+ char num[15];
+ auto unsigned long int value;
+
+ auto struct symbol sym;
+
+
+ /*
+ * This is as handy a place to put this as anyplace.
+ *
+ * Since the insertion of kernel modules can occur in a somewhat
+ * dynamic fashion we need some mechanism to insure that the
+ * kernel symbol tables get read just prior to when they are
+ * needed.
+ *
+ * To accomplish this we look for the Oops string and use its
+ * presence as a signal to load the module symbols.
+ *
+ * This is not the best solution of course, especially if the
+ * kernel is rapidly going out to lunch. What really needs to
+ * be done is to somehow generate a callback from the
+ * kernel whenever a module is loaded or unloaded. I am
+ * open for patches.
+ */
+ if ( i_am_paranoid &&
+ (strstr(line, "Oops:") != (char *) 0) && !InitMsyms() )
+ Syslog(LOG_WARNING, "Cannot load kernel module symbols.\n");
+
+
+ /*
+ * Early return if there do not appear to be any kernel
+ * messages in this line.
+ */
+ if ( (num_syms == 0) ||
+ (kp = strstr(line, "[<")) == (char *) 0 )
+ {
+#ifdef __sparc__
+ if (num_syms) {
+ /*
+ * On SPARC, register dumps do not have the [< >] characters in it.
+ */
+ static struct sparc_tests {
+ char *str;
+ int len;
+ } tests[] = { { "PC: ", 4 },
+ { " o7: ", 5 },
+ { " ret_pc: ", 9 },
+ { " i7: ", 5 },
+ { "Caller[", 7 }
+ };
+ int i, j, ndigits;
+ char *kp2;
+ for (i = 0; i < 5; i++) {
+ kp = strstr(line, tests[i].str);
+ if (!kp) continue;
+ kp2 = kp + tests[i].len;
+ if (!isxdigit(*kp2)) continue;
+ for (ndigits = 1; isxdigit(kp2[ndigits]); ndigits++);
+ if (ndigits != 8 && ndigits != 16) continue;
+ /* On sparc64, all kernel addresses are in first 4GB */
+ if (ndigits == 16) {
+ if (strncmp (kp2, "00000000", 8)) continue;
+ kp2 += 8;
+ }
+ if (!i) {
+ char *kp3;
+ if (ndigits == 16 && kp > line && kp[-1L] != 'T') continue;
+ kp3 = kp2 + 8;
+ if (ndigits == 16) {
+ if (strncmp (kp3, " TNPC: 00000000", 15) || !isxdigit(kp3[15]))
+ continue;
+ kp3 += 15;
+ } else {
+ if (strncmp (kp3, " NPC: ", 6) || !isxdigit(kp3[6]))
+ continue;
+ kp3 += 6;
+ }
+ for (j = 0; isxdigit(kp3[j]); j++);
+ if (j != 8) continue;
+ strncpy(elp, line, kp2 + 8 - line);
+ elp += kp2 + 8 - line;
+ value = strtol(kp2, (char **) 0, 16);
+ if ( (symbol = LookupSymbol(value, &sym)) ) {
+ if (sym.size)
+ elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size);
+ else
+ elp += sprintf(elp, " (%s)", symbol);
+ }
+ strncpy(elp, kp2 + 8, kp3 - kp2);
+ elp += kp3 - kp2;
+ value = strtol(kp3, (char **) 0, 16);
+ if ( (symbol = LookupSymbol(value, &sym)) ) {
+ if (sym.size)
+ elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size);
+ else
+ elp += sprintf(elp, " (%s)", symbol);
+ }
+ strcpy(elp, kp3 + 8);
+ } else {
+ strncpy(elp, line, kp2 + 8 - line);
+ elp += kp2 + 8 - line;
+ value = strtol(kp2, (char **) 0, 16);
+ if ( (symbol = LookupSymbol(value, &sym)) ) {
+ if (sym.size)
+ elp += sprintf(elp, " (%s+%d/%d)", symbol, sym.offset, sym.size);
+ else
+ elp += sprintf(elp, " (%s)", symbol);
+ }
+ strcpy(elp, kp2 + 8);
+ }
+ return el;
+ }
+ }
+#endif
+ strcpy(el, line);
+ return(el);
+ }
+
+ /* Loop through and expand all kernel messages. */
+ do
+ {
+ while ( sl < kp+1 )
+ *elp++ = *sl++;
+
+ /* Now poised at a kernel delimiter. */
+ if ( (kp = strstr(sl, ">]")) == (char *) 0 )
+ {
+ strcpy(el, sl);
+ return(el);
+ }
+ dlm = *kp;
+ strncpy(num,sl+1,kp-sl-1);
+ num[kp-sl-1] = '\0';
+ value = strtoul(num, (char **) 0, 16);
+ if ( (symbol = LookupSymbol(value, &sym)) == (char *) 0 )
+ symbol = sl;
+
+ strcat(elp, symbol);
+ elp += strlen(symbol);
+ if ( debugging )
+ fprintf(stderr, "Symbol: %s = %lx = %s, %x/%d\n", \
+ sl+1, value, \
+ (sym.size==0) ? symbol+1 : symbol, \
+ sym.offset, sym.size);
+
+ value = 2;
+ if ( sym.size != 0 )
+ {
+ --value;
+ ++kp;
+ elp += sprintf(elp, "+%x/%d", sym.offset, sym.size);
+ }
+ strncat(elp, kp, value);
+ elp += value;
+ sl = kp + value;
+ if ( (kp = strstr(sl, "[<")) == (char *) 0 )
+ strcat(elp, sl);
+ }
+ while ( kp != (char *) 0);
+
+ if ( debugging )
+ fprintf(stderr, "Expanded line: %s\n", el);
+ return(el);
+}
+
+
+/**************************************************************************
+ * Function: SetParanoiaLevel
+ *
+ * Purpose: This function is an interface function for setting the
+ * mode of loadable module symbol lookups. Probably overkill
+ * but it does slay another global variable.
+ *
+ * Arguements: (int) level
+ *
+ * level:-> The amount of paranoia which is to be
+ * present when resolving kernel exceptions.
+ * Return: void
+ **************************************************************************/
+
+extern void SetParanoiaLevel(level)
+
+ int level;
+
+{
+ i_am_paranoid = level;
+ return;
+}
+
+
+/*
+ * Setting the -DTEST define enables the following code fragment to
+ * be compiled. This produces a small standalone program which will
+ * echo the standard input of the process to stdout while translating
+ * all numeric kernel addresses into their symbolic equivalent.
+ */
+#if defined(TEST)
+
+#include <stdarg.h>
+
+extern int main(int, char **);
+
+
+extern int main(int argc, char *argv[])
+{
+ auto char line[1024], eline[2048];
+
+ debugging = 1;
+
+
+ if ( !InitKsyms((char *) 0) )
+ {
+ fputs("ksym: Error loading system map.\n", stderr);
+ return(1);
+ }
+
+ while ( !feof(stdin) )
+ {
+ fgets(line, sizeof(line), stdin);
+ if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = '\0'; /* Trash NL char */
+ memset(eline, '\0', sizeof(eline));
+ ExpandKadds(line, eline);
+ fprintf(stdout, "%s\n", eline);
+ }
+
+
+ return(0);
+}
+
+extern void Syslog(int priority, char *fmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stdout, "Pr: %d, ", priority);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fputc('\n', stdout);
+
+ return;
+}
+#endif
+#endif /* #ifdef FEATURE_KLOGD */
diff --git a/ksym_mod.c b/ksym_mod.c
new file mode 100644
index 0000000..d84140e
--- /dev/null
+++ b/ksym_mod.c
@@ -0,0 +1,703 @@
+#include "config.h"
+
+#ifdef FEATURE_KLOGD
+/*
+ ksym_mod.c - functions for building symbol lookup tables for klogd
+ Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
+ Copyright (c) 1996 Enjellic Systems Development
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * This file implements functions which are useful for building
+ * a symbol lookup table based on the in kernel symbol table
+ * maintained by the Linux kernel.
+ *
+ * Proper logging of kernel panics generated by loadable modules
+ * tends to be difficult. Since the modules are loaded dynamically
+ * their addresses are not known at kernel load time. A general
+ * protection fault (Oops) cannot be properly deciphered with
+ * classic methods using the static symbol map produced at link time.
+ *
+ * One solution to this problem is to have klogd attempt to translate
+ * addresses from module when the fault occurs. By referencing the
+ * the kernel symbol table proper resolution of these symbols is made
+ * possible.
+ *
+ * At least that is the plan.
+ *
+ * Wed Aug 21 09:20:09 CDT 1996: Dr. Wettstein
+ * The situation where no module support has been compiled into a
+ * kernel is now detected. An informative message is output indicating
+ * that the kernel has no loadable module support whenever kernel
+ * module symbols are loaded.
+ *
+ * An informative message is printed indicating the number of kernel
+ * modules and the number of symbols loaded from these modules.
+ *
+ * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
+ * Some more glibc patches made by <mdorman@debian.org>.
+ *
+ * Sat Jan 10 15:00:18 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Fixed problem with klogd not being able to be built on a kernel
+ * newer than 2.1.18. It was caused by modified structures
+ * inside the kernel that were included. I have worked in a
+ * patch from Alessandro Suardi <asuardi@uninetcom.it>.
+ *
+ * Sun Jan 25 20:57:34 CET 1998: Martin Schulze <joey@infodrom.north.de>
+ * Another patch for Linux/alpha by Christopher C Chimelis
+ * <chris@classnet.med.miami.edu>.
+ *
+ * Thu Mar 19 23:39:29 CET 1998: Manuel Rodrigues <pmanuel@cindy.fe.up.pt>
+ * Changed lseek() to llseek() in order to support > 2GB address
+ * space which provided by kernels > 2.1.70.
+ *
+ * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de>
+ * Removed <sys/module.h> as it's no longer part of recent glibc
+ * versions. Added prototyp for llseek() which has been
+ * forgotton in <unistd.h> from glibc. Added more log
+ * information if problems occurred while reading a system map
+ * file, by submission from Mark Simon Phillips <M.S.Phillips@nortel.co.uk>.
+ *
+ * Sun Jan 3 18:38:03 CET 1999: Martin Schulze <joey@infodrom.north.de>
+ * Corrected return value of AddModule if /dev/kmem can't be
+ * loaded. This will prevent klogd from segfaulting if /dev/kmem
+ * is not available. Patch from Topi Miettinen <tom@medialab.sonera.net>.
+ *
+ * Tue Sep 12 23:11:13 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
+ * Changed llseek() to lseek64() in order to skip a libc warning.
+ */
+
+
+/* Includes. */
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#if !defined(__GLIBC__)
+#include <linux/time.h>
+#include <linux/module.h>
+#else /* __GLIBC__ */
+#include "module.h"
+extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
+extern int get_kernel_syms __P ((struct kernel_sym *__table));
+#endif /* __GLIBC__ */
+#include <stdarg.h>
+#include <paths.h>
+#include <linux/version.h>
+
+#include "klogd.h"
+#include "ksyms.h"
+
+
+#if !defined(__GLIBC__)
+/*
+ * The following bit uses some kernel/library magic to product what
+ * looks like a function call to user level code. This function is
+ * actually a system call in disguise. The purpose of the getsyms
+ * call is to return a current copy of the in-kernel symbol table.
+ */
+#define __LIBRARY__
+#include <linux/unistd.h>
+#define __NR_getsyms __NR_get_kernel_syms
+_syscall1(int, getsyms, struct kernel_sym *, syms);
+#undef __LIBRARY__
+extern int getsyms(struct kernel_sym *);
+#else /* __GLIBC__ */
+#define getsyms get_kernel_syms
+#endif /* __GLIBC__ */
+
+/* Variables static to this module. */
+struct sym_table
+{
+ unsigned long value;
+ char *name;
+};
+
+struct Module
+{
+ struct sym_table *sym_array;
+ int num_syms;
+
+ char *name;
+ struct module module;
+#if LINUX_VERSION_CODE >= 0x20112
+ struct module_info module_info;
+#endif
+};
+
+static int num_modules = 0;
+struct Module *sym_array_modules = (struct Module *) 0;
+
+static int have_modules = 0;
+
+#if defined(TEST)
+static int debugging = 1;
+#else
+extern int debugging;
+#endif
+
+
+/* Function prototypes. */
+static void FreeModules(void);
+static int AddSymbol(struct Module *mp, unsigned long, char *);
+static int AddModule(unsigned long, char *);
+static int symsort(const void *, const void *);
+
+
+/**************************************************************************
+ * Function: InitMsyms
+ *
+ * Purpose: This function is responsible for building a symbol
+ * table which can be used to resolve addresses for
+ * loadable modules.
+ *
+ * Arguements: Void
+ *
+ * Return: A boolean return value is assumed.
+ *
+ * A false value indicates that something went wrong.
+ *
+ * True if loading is successful.
+ **************************************************************************/
+
+extern int InitMsyms()
+
+{
+ auto int rtn,
+ tmp;
+
+ auto struct kernel_sym *ksym_table,
+ *p;
+
+
+ /* Initialize the kernel module symbol table. */
+ FreeModules();
+
+
+ /*
+ * The system call which returns the kernel symbol table has
+ * essentialy two modes of operation. Called with a null pointer
+ * the system call returns the number of symbols defined in the
+ * the table.
+ *
+ * The second mode of operation is to pass a valid pointer to
+ * the call which will then load the current symbol table into
+ * the memory provided.
+ *
+ * Returning the symbol table is essentially an all or nothing
+ * proposition so we need to pre-allocate enough memory for the
+ * complete table regardless of how many symbols we need.
+ *
+ * Bummer.
+ */
+ if ( (rtn = getsyms((struct kernel_sym *) 0)) < 0 )
+ {
+ if ( errno == ENOSYS )
+ Syslog(LOG_INFO, "No module symbols loaded - "
+ "kernel modules not enabled.\n");
+ else
+ Syslog(LOG_ERR, "Error loading kernel symbols " \
+ "- %s\n", strerror(errno));
+ return(0);
+ }
+ if ( debugging )
+ fprintf(stderr, "Loading kernel module symbols - "
+ "Size of table: %d\n", rtn);
+
+ ksym_table = (struct kernel_sym *) malloc(rtn * \
+ sizeof(struct kernel_sym));
+ if ( ksym_table == (struct kernel_sym *) 0 )
+ {
+ Syslog(LOG_WARNING, " Failed memory allocation for kernel " \
+ "symbol table.\n");
+ return(0);
+ }
+ if ( (rtn = getsyms(ksym_table)) < 0 )
+ {
+ Syslog(LOG_WARNING, "Error reading kernel symbols - %s\n", \
+ strerror(errno));
+ return(0);
+ }
+
+
+ /*
+ * Build a symbol table compatible with the other one used by
+ * klogd.
+ */
+ tmp = rtn;
+ p = ksym_table;
+ while ( tmp-- )
+ {
+ if ( !AddModule(p->value, p->name) )
+ {
+ Syslog(LOG_WARNING, "Error adding kernel module table "
+ "entry.\n");
+ free(ksym_table);
+ return(0);
+ }
+ ++p;
+ }
+
+ /* Sort the symbol tables in each module. */
+ for (rtn = tmp= 0; tmp < num_modules; ++tmp)
+ {
+ rtn += sym_array_modules[tmp].num_syms;
+ if ( sym_array_modules[tmp].num_syms < 2 )
+ continue;
+ qsort(sym_array_modules[tmp].sym_array, \
+ sym_array_modules[tmp].num_syms, \
+ sizeof(struct sym_table), symsort);
+ }
+
+ if ( rtn == 0 )
+ Syslog(LOG_INFO, "No module symbols loaded.");
+ else
+ Syslog(LOG_INFO, "Loaded %d %s from %d module%s", rtn, \
+ (rtn == 1) ? "symbol" : "symbols", \
+ num_modules, (num_modules == 1) ? "." : "s.");
+ free(ksym_table);
+ return(1);
+}
+
+
+static int symsort(p1, p2)
+
+ const void *p1;
+
+ const void *p2;
+
+{
+ auto const struct sym_table *sym1 = p1,
+ *sym2 = p2;
+
+ if ( sym1->value < sym2->value )
+ return(-1);
+ if ( sym1->value == sym2->value )
+ return(0);
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: FreeModules
+ *
+ * Purpose: This function is used to free all memory which has been
+ * allocated for the modules and their symbols.
+ *
+ * Arguements: None specified.
+ *
+ * Return: void
+ **************************************************************************/
+
+static void FreeModules()
+
+{
+ auto int nmods,
+ nsyms;
+
+ auto struct Module *mp;
+
+
+ /* Check to see if the module symbol tables need to be cleared. */
+ have_modules = 0;
+ if ( num_modules == 0 )
+ return;
+
+
+ for (nmods= 0; nmods < num_modules; ++nmods)
+ {
+ mp = &sym_array_modules[nmods];
+ if ( mp->num_syms == 0 )
+ continue;
+
+ for (nsyms= 0; nsyms < mp->num_syms; ++nsyms)
+ free(mp->sym_array[nsyms].name);
+ free(mp->sym_array);
+ }
+
+ free(sym_array_modules);
+ sym_array_modules = (struct Module *) 0;
+ num_modules = 0;
+ return;
+}
+
+
+/**************************************************************************
+ * Function: AddModule
+ *
+ * Purpose: This function is responsible for adding a module to
+ * the list of currently loaded modules.
+ *
+ * Arguements: (unsigned long) address, (char *) symbol
+ *
+ * address:-> The address of the module.
+ *
+ * symbol:-> The name of the module.
+ *
+ * Return: int
+ **************************************************************************/
+
+static int AddModule(address, symbol)
+
+ unsigned long address;
+
+ char *symbol;
+
+{
+ auto int memfd;
+
+ auto struct Module *mp;
+
+
+ /* Return if we have loaded the modules. */
+ if ( have_modules )
+ return(1);
+
+ /*
+ * The following section of code is responsible for determining
+ * whether or not we are done reading the list of modules.
+ */
+ if ( symbol[0] == '#' )
+ {
+
+ if ( symbol[1] == '\0' )
+ {
+ /*
+ * A symbol which consists of a # sign only
+ * signifies a a resident kernel segment. When we
+ * hit one of these we are done reading the
+ * module list.
+ */
+ have_modules = 1;
+ return(1);
+ }
+ /* Allocate space for the module. */
+ sym_array_modules = (struct Module *) \
+ realloc(sym_array_modules, \
+ (num_modules+1) * sizeof(struct Module));
+ if ( sym_array_modules == (struct Module *) 0 )
+ {
+ Syslog(LOG_WARNING, "Cannot allocate Module array.\n");
+ return(0);
+ }
+ mp = &sym_array_modules[num_modules];
+
+ if ( (memfd = open("/dev/kmem", O_RDONLY)) < 0 )
+ {
+ Syslog(LOG_WARNING, "Error opening /dev/kmem\n");
+ return(0);
+ }
+ if ( lseek64(memfd, address, SEEK_SET) < 0 )
+ {
+ Syslog(LOG_WARNING, "Error seeking in /dev/kmem\n");
+ Syslog(LOG_WARNING, "Symbol %s, value %08x\n", symbol, address);
+ return(0);
+ }
+ if ( read(memfd, \
+ (char *)&sym_array_modules[num_modules].module, \
+ sizeof(struct module)) < 0 )
+ {
+ Syslog(LOG_WARNING, "Error reading module "
+ "descriptor.\n");
+ return(0);
+ }
+ close(memfd);
+
+ /* Save the module name. */
+ mp->name = (char *) malloc(strlen(&symbol[1]) + 1);
+ if ( mp->name == (char *) 0 )
+ return(0);
+ strcpy(mp->name, &symbol[1]);
+
+ mp->num_syms = 0;
+ mp->sym_array = (struct sym_table *) 0;
+ ++num_modules;
+ return(1);
+ }
+ else
+ {
+ if (num_modules > 0)
+ mp = &sym_array_modules[num_modules - 1];
+ else
+ mp = &sym_array_modules[0];
+ AddSymbol(mp, address, symbol);
+ }
+
+
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: AddSymbol
+ *
+ * Purpose: This function is responsible for adding a symbol name
+ * and its address to the symbol table.
+ *
+ * Arguements: (struct Module *) mp, (unsigned long) address, (char *) symbol
+ *
+ * mp:-> A pointer to the module which the symbol is
+ * to be added to.
+ *
+ * address:-> The address of the symbol.
+ *
+ * symbol:-> The name of the symbol.
+ *
+ * Return: int
+ *
+ * A boolean value is assumed. True if the addition is
+ * successful. False if not.
+ **************************************************************************/
+
+static int AddSymbol(mp, address, symbol)
+
+ struct Module *mp;
+
+ unsigned long address;
+
+ char *symbol;
+
+{
+ auto int tmp;
+
+
+ /* Allocate space for the symbol table entry. */
+ mp->sym_array = (struct sym_table *) realloc(mp->sym_array, \
+ (mp->num_syms+1) * sizeof(struct sym_table));
+ if ( mp->sym_array == (struct sym_table *) 0 )
+ return(0);
+
+ /* Then the space for the symbol. */
+ tmp = strlen(symbol);
+ tmp += (strlen(mp->name) + 1);
+ mp->sym_array[mp->num_syms].name = (char *) malloc(tmp + 1);
+ if ( mp->sym_array[mp->num_syms].name == (char *) 0 )
+ return(0);
+ memset(mp->sym_array[mp->num_syms].name, '\0', tmp + 1);
+
+ /* Stuff interesting information into the module. */
+ mp->sym_array[mp->num_syms].value = address;
+ strcpy(mp->sym_array[mp->num_syms].name, mp->name);
+ strcat(mp->sym_array[mp->num_syms].name, ":");
+ strcat(mp->sym_array[mp->num_syms].name, symbol);
+ ++mp->num_syms;
+
+ return(1);
+}
+
+
+/**************************************************************************
+ * Function: LookupModuleSymbol
+ *
+ * Purpose: Find the symbol which is related to the given address from
+ * a kernel module.
+ *
+ * Arguements: (long int) value, (struct symbol *) sym
+ *
+ * value:-> The address to be located.
+ *
+ * sym:-> A pointer to a structure which will be
+ * loaded with the symbol's parameters.
+ *
+ * Return: (char *)
+ *
+ * If a match cannot be found a diagnostic string is printed.
+ * If a match is found the pointer to the symbolic name most
+ * closely matching the address is returned.
+ **************************************************************************/
+
+extern char * LookupModuleSymbol(value, sym)
+
+ unsigned long value;
+
+ struct symbol *sym;
+
+{
+ auto int nmod,
+ nsym;
+
+ auto struct sym_table *last;
+
+ auto struct Module *mp;
+
+
+ sym->size = 0;
+ sym->offset = 0;
+ if ( num_modules == 0 )
+ return((char *) 0);
+
+ for(nmod= 0; nmod < num_modules; ++nmod)
+ {
+ mp = &sym_array_modules[nmod];
+
+ /*
+ * Run through the list of symbols in this module and
+ * see if the address can be resolved.
+ */
+ for(nsym= 1, last = &mp->sym_array[0];
+ nsym < mp->num_syms;
+ ++nsym)
+ {
+ if ( mp->sym_array[nsym].value > value )
+ {
+ sym->offset = value - last->value;
+ sym->size = mp->sym_array[nsym].value - \
+ last->value;
+ return(last->name);
+ }
+ last = &mp->sym_array[nsym];
+ }
+
+
+ /*
+ * At this stage of the game we still cannot give up the
+ * ghost. There is the possibility that the address is
+ * from a module which has no symbols registered with
+ * the kernel. The solution is to compare the address
+ * against the starting address and extant of the module
+ * If it is in this range we can at least return the
+ * name of the module.
+ */
+#if LINUX_VERSION_CODE < 0x20112
+ if ( (void *) value >= mp->module.addr &&
+ (void *) value <= (mp->module.addr + \
+ mp->module.size * 4096) )
+#else
+ if ( value >= mp->module_info.addr &&
+ value <= (mp->module_info.addr + \
+ mp->module.size * 4096) )
+#endif
+ {
+ /*
+ * A special case needs to be checked for. The above
+ * conditional tells us that we are within the
+ * extant of this module but symbol lookup has
+ * failed.
+ *
+ * We need to check to see if any symbols have
+ * been defined in this module. If there have been
+ * symbols defined the assumption must be made that
+ * the faulting address lies somewhere beyond the
+ * last symbol. About the only thing we can do
+ * at this point is use an offset from this
+ * symbol.
+ */
+ if ( mp->num_syms > 0 )
+ {
+ last = &mp->sym_array[mp->num_syms - 1];
+#if LINUX_VERSION_CODE < 0x20112
+ sym->size = (int) mp->module.addr + \
+ (mp->module.size * 4096) - value;
+#else
+ sym->size = (int) mp->module_info.addr + \
+ (mp->module.size * 4096) - value;
+#endif
+ sym->offset = value - last->value;
+ return(last->name);
+ }
+
+ /*
+ * There were no symbols defined for this module.
+ * Return the module name and the offset of the
+ * faulting address in the module.
+ */
+ sym->size = mp->module.size * 4096;
+#if LINUX_VERSION_CODE < 0x20112
+ sym->offset = (void *) value - mp->module.addr;
+#else
+ sym->offset = value - mp->module_info.addr;
+#endif
+ return(mp->name);
+ }
+ }
+
+ /* It has been a hopeless exercise. */
+ return((char *) 0);
+}
+
+
+/*
+ * Setting the -DTEST define enables the following code fragment to
+ * be compiled. This produces a small standalone program which will
+ * dump the current kernel symbol table.
+ */
+#if defined(TEST)
+
+#include <stdarg.h>
+
+
+extern int main(int, char **);
+
+
+int main(argc, argv)
+
+ int argc;
+
+ char *argv[];
+
+{
+ auto int lp, syms;
+
+
+ if ( !InitMsyms() )
+ {
+ fprintf(stderr, "Cannot load module symbols.\n");
+ return(1);
+ }
+
+ printf("Number of modules: %d\n\n", num_modules);
+
+ for(lp= 0; lp < num_modules; ++lp)
+ {
+ printf("Module #%d = %s, Number of symbols = %d\n", lp + 1, \
+ sym_array_modules[lp].name, \
+ sym_array_modules[lp].num_syms);
+
+ for (syms= 0; syms < sym_array_modules[lp].num_syms; ++syms)
+ {
+ printf("\tSymbol #%d\n", syms + 1);
+ printf("\tName: %s\n", \
+ sym_array_modules[lp].sym_array[syms].name);
+ printf("\tAddress: %lx\n\n", \
+ sym_array_modules[lp].sym_array[syms].value);
+ }
+ }
+
+ FreeModules();
+ return(0);
+}
+
+extern void Syslog(int priority, char *fmt, ...)
+
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stdout, "Pr: %d, ", priority);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ fputc('\n', stdout);
+
+ return;
+}
+
+#endif
+#endif /* #ifdef FEATURE_KLOGD */
diff --git a/ksyms.h b/ksyms.h
new file mode 100644
index 0000000..4e70ba0
--- /dev/null
+++ b/ksyms.h
@@ -0,0 +1,35 @@
+/*
+ ksym.h - Definitions for symbol table utilities.
+ Copyright (c) 1995, 1996 Dr. G.W. Wettstein <greg@wind.rmcc.com>
+ Copyright (c) 1996 Enjellic Systems Development
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Variables, structures and type definitions static to this module. */
+
+struct symbol
+{
+ char *name;
+ int size;
+ int offset;
+};
+
+
+/* Function prototypes. */
+extern char * LookupSymbol(unsigned long, struct symbol *);
+extern char * LookupModuleSymbol(unsigned long int, struct symbol *);
diff --git a/liblogging-stub.h b/liblogging-stub.h
new file mode 100755
index 0000000..644762c
--- /dev/null
+++ b/liblogging-stub.h
@@ -0,0 +1,7 @@
+/* This is a (now *very slim*) stub for some liblogging
+ * code we use in rsyslog.
+ */
+#ifndef __LIB3195_LIBLOGGINGSTUB_H_INCLUDED__
+#define __LIB3195_LIBLOGGINGSTUB_H_INCLUDED__ 1
+#include <stdio.h>
+#endif
diff --git a/linkedlist.c b/linkedlist.c
new file mode 100644
index 0000000..7ebadf5
--- /dev/null
+++ b/linkedlist.c
@@ -0,0 +1,304 @@
+/* linkedlist.c
+ * This file set implements a generic linked list object. It can be used
+ * wherever a linke list is required.
+ *
+ * NOTE: we do not currently provide a constructor and destructor for the
+ * object itself as we assume it will always be part of another strucuture.
+ * Having a pointer to it, I think, does not really make sense but costs
+ * performance. Consequently, there is is llInit() and llDestroy() and they
+ * do what a constructor and destructur do, except for creating the
+ * linkedList_t structure itself.
+ *
+ * File begun on 2007-07-31 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "rsyslog.h"
+#include "linkedlist.h"
+
+
+/* Initialize an existing linkedList_t structure
+ * pKey destructor may be zero to take care of non-keyed lists.
+ */
+rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(), rsRetVal (*pKeyDestructor)(void*), int (*pCmpOp)())
+{
+ assert(pThis != NULL);
+ assert(pEltDestructor != NULL);
+
+ pThis->pEltDestruct = pEltDestructor;
+ pThis->pKeyDestruct = pKeyDestructor;
+ pThis->cmpOp = pCmpOp;
+ pThis->pKey = NULL;
+ pThis->iNumElts = 0;
+ pThis->pRoot = NULL;
+ pThis->pLast = NULL;
+
+ return RS_RET_OK;
+};
+
+
+/* llDestroyEltData - destroys a list element
+ * It is a separate function as the
+ * functionality is needed in multiple code-pathes.
+ */
+static rsRetVal llDestroyElt(linkedList_t *pList, llElt_t *pElt)
+{
+ DEFiRet;
+
+ assert(pList != NULL);
+ assert(pElt != NULL);
+
+ /* we ignore errors during destruction, as we need to try
+ * free the element in any case.
+ */
+ if(pElt->pData != NULL)
+ pList->pEltDestruct(pElt->pData);
+ if(pElt->pKey != NULL)
+ pList->pKeyDestruct(pElt->pKey);
+ free(pElt);
+ pList->iNumElts--; /* one less */
+
+ return iRet;
+}
+
+
+/* llDestroy - destroys a COMPLETE linkedList
+ */
+rsRetVal llDestroy(linkedList_t *pThis)
+{
+ DEFiRet;
+ llElt_t *pElt;
+ llElt_t *pEltPrev;
+
+ assert(pThis != NULL);
+
+ pElt = pThis->pRoot;
+ while(pElt != NULL) {
+ pEltPrev = pElt;
+ pElt = pElt->pNext;
+ /* we ignore errors during destruction, as we need to try
+ * finish the linked list in any case.
+ */
+ llDestroyElt(pThis, pEltPrev);
+ }
+
+ return iRet;
+}
+
+/* llDestroyRootElt - destroy the root element but otherwise
+ * keeps this list intact. -- rgerhards, 2007-08-03
+ */
+rsRetVal llDestroyRootElt(linkedList_t *pThis)
+{
+ DEFiRet;
+ llElt_t *pPrev;
+
+ if(pThis->pRoot == NULL) {
+ ABORT_FINALIZE(RS_RET_EMPTY_LIST);
+ }
+
+ pPrev = pThis->pRoot;
+ if(pPrev->pNext == NULL) {
+ /* it was the only list element */
+ pThis->pLast = NULL;
+ pThis->pRoot = NULL;
+ } else {
+ /* there are other list elements */
+ pThis->pRoot = pPrev->pNext;
+ }
+
+ CHKiRet(llDestroyElt(pThis, pPrev));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* get next user data element of a linked list. The caller must also
+ * provide a "cookie" to the function. On initial call, it must be
+ * NULL. Other than that, the caller is not allowed to to modify the
+ * cookie. In the current implementation, the cookie is an actual
+ * pointer to the current list element, but this is nothing that the
+ * caller should rely on.
+ */
+rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr)
+{
+ llElt_t *pElt;
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(ppElt != NULL);
+ assert(ppUsr != NULL);
+
+ pElt = *ppElt;
+
+ pElt = (pElt == NULL) ? pThis->pRoot : pElt->pNext;
+
+ if(pElt == NULL) {
+ iRet = RS_RET_END_OF_LINKEDLIST;
+ } else {
+ *ppUsr = pElt->pData;
+ }
+
+ *ppElt = pElt;
+
+ return iRet;
+}
+
+
+/* return the key of an Elt
+ */
+rsRetVal llGetKey(llElt_t *pThis, void **ppData)
+{
+ assert(pThis != NULL);
+ assert(ppData != NULL);
+
+ *ppData = pThis->pKey;
+
+ return RS_RET_OK;
+}
+
+
+/* construct a new llElt_t
+ */
+static rsRetVal llEltConstruct(llElt_t **ppThis, void *pKey, void *pData)
+{
+ DEFiRet;
+ llElt_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (llElt_t*) calloc(1, sizeof(llElt_t))) == NULL) {
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+
+ pThis->pKey = pKey;
+ pThis->pData = pData;
+
+finalize_it:
+ *ppThis = pThis;
+ return iRet;
+}
+
+
+/* append a user element to the end of the linked list. This includes setting a key. If no
+ * key is desired, simply pass in a NULL pointer for it.
+ */
+rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData)
+{
+ llElt_t *pElt;
+ DEFiRet;
+
+ CHKiRet(llEltConstruct(&pElt, pKey, pData));
+
+ pThis->iNumElts++; /* one more */
+ if(pThis->pLast == NULL) {
+ pThis->pRoot = pElt;
+ } else {
+ pThis->pLast->pNext = pElt;
+ }
+ pThis->pLast = pElt;
+
+finalize_it:
+ return iRet;
+}
+
+
+/* find a user element based on the provided key
+ */
+rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData)
+{
+ DEFiRet;
+ llElt_t *pElt;
+ int bFound = 0;
+
+ assert(pThis != NULL);
+ assert(pKey != NULL);
+ assert(ppData != NULL);
+
+ pElt = pThis->pRoot;
+ while(pElt != NULL && bFound == 0) {
+ if(pThis->cmpOp(pKey, pElt->pKey) == 0)
+ bFound = 1;
+ else
+ pElt = pElt->pNext;
+ }
+
+ if(bFound == 1) {
+ *ppData = pElt->pData;
+ } else {
+ iRet = RS_RET_NOT_FOUND;
+ }
+
+ return iRet;
+}
+
+
+/* provide the count of linked list elements
+ */
+rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(piCnt != NULL);
+
+ *piCnt = pThis->iNumElts;
+
+ return iRet;
+}
+
+
+/* execute a function on all list members. The functions receives a
+ * user-supplied parameter, which may be either a simple value
+ * or a pointer to a structure with more data. If the user-supplied
+ * function does not return RS_RET_OK, this function here terminates.
+ * rgerhards, 2007-08-02
+ */
+rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam)
+{
+ DEFiRet;
+ rsRetVal iRetLL;
+ void *pData;
+ linkedListCookie_t llCookie = NULL;
+
+ assert(pThis != NULL);
+ assert(pFunc != NULL);
+
+ while((iRetLL = llGetNextElt(pThis, &llCookie, (void**)&pData)) == RS_RET_OK) {
+ CHKiRet(pFunc(pData, pParam));
+ }
+
+ if(iRetLL != RS_RET_END_OF_LINKEDLIST)
+ iRet = iRetLL;
+
+finalize_it:
+ return iRet;
+}
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/linkedlist.h b/linkedlist.h
new file mode 100644
index 0000000..0b5b36e
--- /dev/null
+++ b/linkedlist.h
@@ -0,0 +1,70 @@
+/* Definition of the linkedlist object.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#ifndef LINKEDLIST_H_INCLUDED
+#define LINKEDLIST_H_INCLUDED
+
+/* this is a single entry for a parse routine. It describes exactly
+ * one entry point/handler.
+ * The short name is cslch (Configfile SysLine CommandHandler)
+ */
+struct llElt_s { /* config file sysline parse entry */
+ struct llElt_s *pNext;
+ void *pKey; /* key for this element */
+ void *pData; /* user-supplied data pointer */
+};
+typedef struct llElt_s llElt_t;
+
+
+/* this is the list of known configuration commands with pointers to
+ * their handlers.
+ * The short name is cslc (Configfile SysLine Command)
+ */
+struct linkedList_s { /* config file sysline parse entry */
+ int iNumElts; /* number of elements in list */
+ rsRetVal (*pEltDestruct)(void*pData); /* destructor for user pointer in llElt_t's */
+ rsRetVal (*pKeyDestruct)(void*pKey); /* destructor for key pointer in llElt_t's */
+ int (*cmpOp)(void*, void*); /* pointer to key compare operation function, retval like strcmp */
+ void *pKey; /* the list key (searchable, if set) */
+ llElt_t *pRoot; /* list root */
+ llElt_t *pLast; /* list tail */
+};
+typedef struct linkedList_s linkedList_t;
+
+typedef llElt_t* linkedListCookie_t; /* this type avoids exposing internals and keeps us flexible */
+
+/* prototypes */
+rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(), rsRetVal (*pKeyDestructor)(void*), int (*pCmpOp)());
+rsRetVal llDestroy(linkedList_t *pThis);
+rsRetVal llDestroyRootElt(linkedList_t *pThis);
+rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr);
+rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData);
+rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData);
+rsRetVal llGetKey(llElt_t *pThis, void **ppData);
+rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt);
+rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam);
+/* use the macro below to define a function that will be executed by
+ * llExecFunc()
+ */
+#define DEFFUNC_llExecFunc(funcName)\
+ static rsRetVal funcName(void __attribute__((unused)) *pData, void __attribute__((unused)) *pParam)
+
+#endif /* #ifndef LINKEDLIST_H_INCLUDED */
diff --git a/missing b/missing
new file mode 100755
index 0000000..1c8ff70
--- /dev/null
+++ b/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program 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 2, or (at your option)
+# any later version.
+
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/module-template.h b/module-template.h
new file mode 100644
index 0000000..ce13bce
--- /dev/null
+++ b/module-template.h
@@ -0,0 +1,344 @@
+/* module-template.h
+ * This header contains macros that can be used to implement the
+ * plumbing of modules.
+ *
+ * File begun on 2007-07-25 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef MODULE_TEMPLATE_H_INCLUDED
+#define MODULE_TEMPLATE_H_INCLUDED 1
+
+#include "objomsr.h"
+
+/* macro to define standard output-module static data members
+ */
+#define DEF_OMOD_STATIC_DATA \
+ static rsRetVal (*omsdRegCFSLineHdlr)();
+
+/* to following macros are used to generate function headers and standard
+ * functionality. It works as follows (described on the sample case of
+ * createInstance()):
+ *
+ * BEGINcreateInstance
+ * ... custom variable definitions (on stack) ... (if any)
+ * CODESTARTcreateInstance
+ * ... custom code ... (if any)
+ * ENDcreateInstance
+ */
+
+/* createInstance()
+ */
+#define BEGINcreateInstance \
+static rsRetVal createInstance(instanceData **ppData)\
+ {\
+ DEFiRet; /* store error code here */\
+ instanceData *pData; /* use this to point to data elements */
+
+#define CODESTARTcreateInstance \
+ if((pData = calloc(1, sizeof(instanceData))) == NULL) {\
+ *ppData = NULL;\
+ return RS_RET_OUT_OF_MEMORY;\
+ }
+
+#define ENDcreateInstance \
+ *ppData = pData;\
+ return iRet;\
+}
+
+/* freeInstance()
+ */
+#define BEGINfreeInstance \
+static rsRetVal freeInstance(void* pModData)\
+{\
+ DEFiRet;\
+ instanceData *pData;
+
+#define CODESTARTfreeInstance \
+ pData = (instanceData*) pModData;
+
+#define ENDfreeInstance \
+ if(pData != NULL)\
+ free(pData); /* we need to free this in any case */\
+ return iRet;\
+}
+
+/* isCompatibleWithFeature()
+ */
+#define BEGINisCompatibleWithFeature \
+static rsRetVal isCompatibleWithFeature(syslogFeature __attribute__((unused)) eFeat)\
+{\
+ rsRetVal iRet = RS_RET_INCOMPATIBLE;
+
+#define CODESTARTisCompatibleWithFeature
+
+#define ENDisCompatibleWithFeature \
+ return iRet;\
+}
+
+/* doAction()
+ */
+#define BEGINdoAction \
+static rsRetVal doAction(uchar __attribute__((unused)) **ppString, unsigned __attribute__((unused)) iMsgOpts, instanceData __attribute__((unused)) *pData)\
+{\
+ DEFiRet;
+
+#define CODESTARTdoAction \
+ assert(ppString != NULL);
+
+#define ENDdoAction \
+ return iRet;\
+}
+
+
+/* dbgPrintInstInfo()
+ * Extra comments:
+ * Print debug information about this instance.
+ */
+#define BEGINdbgPrintInstInfo \
+static rsRetVal dbgPrintInstInfo(void *pModData)\
+{\
+ DEFiRet;\
+ instanceData *pData = NULL;
+
+#define CODESTARTdbgPrintInstInfo \
+ pData = (instanceData*) pModData;
+
+#define ENDdbgPrintInstInfo \
+ return iRet;\
+}
+
+
+/* needUDPSocket()
+ * Talks back to syslogd if the global UDP syslog socket is needed for
+ * sending. Returns 0 if not, 1 if needed. This interface hopefully goes
+ * away at some time, because it is kind of a hack. However, currently
+ * there is no way around it, so we need to support it.
+ * rgerhards, 2007-07-26
+ */
+#define BEGINneedUDPSocket \
+static rsRetVal needUDPSocket(void *pModData)\
+{\
+ rsRetVal iRet = RS_RET_FALSE;\
+ instanceData *pData = NULL;
+
+#define CODESTARTneedUDPSocket \
+ pData = (instanceData*) pModData;
+
+#define ENDneedUDPSocket \
+ return iRet;\
+}
+
+
+/* onSelectReadyWrite()
+ * Extra comments:
+ * This is called when select() returned with a writable file descriptor
+ * for this module. The fd was most probably obtained by getWriteFDForSelect()
+ * before.
+ */
+#define BEGINonSelectReadyWrite \
+static rsRetVal onSelectReadyWrite(void *pModData)\
+{\
+ rsRetVal iRet = RS_RET_NONE;\
+ instanceData *pData = NULL;
+
+#define CODESTARTonSelectReadyWrite \
+ pData = (instanceData*) pModData;
+
+#define ENDonSelectReadyWrite \
+ return iRet;\
+}
+
+
+/* getWriteFDForSelect()
+ * Extra comments:
+ * Gets writefd for select call. Must only be returned when the selector must
+ * be written to. If the module has no such fds, it must return RS_RET_NONE.
+ * In this case, the default implementation is sufficient.
+ * This interface will probably go away over time, but we need it now to
+ * continue modularization.
+ */
+#define BEGINgetWriteFDForSelect \
+static rsRetVal getWriteFDForSelect(void *pModData, short *fd)\
+{\
+ rsRetVal iRet = RS_RET_NONE;\
+ instanceData *pData = NULL;
+
+#define CODESTARTgetWriteFDForSelect \
+ assert(fd != NULL);\
+ pData = (instanceData*) pModData;
+
+#define ENDgetWriteFDForSelect \
+ return iRet;\
+}
+
+
+/* parseSelectorAct()
+ * Extra comments:
+ * try to process a selector action line. Checks if the action
+ * applies to this module and, if so, processed it. If not, it
+ * is left untouched. The driver will then call another module.
+ * On exit, ppModData must point to instance data. Also, a string
+ * request object must be created and filled. A macro is defined
+ * for that.
+ * For the most usual case, we have defined a macro below.
+ * If more than one string is requested, the macro can be used together
+ * with own code that overwrites the entry count. In this case, the
+ * macro must come before the own code. It is recommended to be
+ * placed right after CODESTARTparseSelectorAct.
+ */
+#define BEGINparseSelectorAct \
+static rsRetVal parseSelectorAct(uchar **pp, void **ppModData, omodStringRequest_t **ppOMSR)\
+{\
+ DEFiRet;\
+ uchar *p;\
+ instanceData *pData = NULL;
+
+#define CODESTARTparseSelectorAct \
+ assert(pp != NULL);\
+ assert(ppModData != NULL);\
+ assert(ppOMSR != NULL);\
+ p = *pp;
+
+#define CODE_STD_STRING_REQUESTparseSelectorAct(NumStrReqEntries) \
+ CHKiRet(OMSRconstruct(ppOMSR, NumStrReqEntries));
+
+#define CODE_STD_FINALIZERparseSelectorAct \
+finalize_it:\
+ if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {\
+ *ppModData = pData;\
+ *pp = p;\
+ } else {\
+ /* cleanup, we failed */\
+ if(*ppOMSR != NULL)\
+ OMSRdestruct(*ppOMSR);\
+ *ppOMSR = NULL;\
+ }
+
+#define ENDparseSelectorAct \
+ return iRet;\
+}
+
+
+/* tryResume()
+ * This entry point is called to check if a module can resume operations. This
+ * happens when a module requested that it be suspended. In suspended state,
+ * the engine periodically tries to resume the module. If that succeeds, normal
+ * processing continues. If not, the module will not be called unless a
+ * tryResume() call succeeds.
+ * Returns RS_RET_OK, if resumption succeeded, RS_RET_SUSPENDED otherwise
+ * rgerhard, 2007-08-02
+ */
+#define BEGINtryResume \
+static rsRetVal tryResume(instanceData __attribute__((unused)) *pData)\
+{\
+ DEFiRet;
+
+#define CODESTARTtryResume \
+ assert(pData != NULL);
+
+#define ENDtryResume \
+ return iRet;\
+}
+
+
+
+/* queryEtryPt()
+ */
+#define BEGINqueryEtryPt \
+static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\
+{\
+ DEFiRet;
+
+#define CODESTARTqueryEtryPt \
+ if((name == NULL) || (pEtryPoint == NULL))\
+ return RS_RET_PARAM_ERROR;\
+ *pEtryPoint = NULL;
+
+#define ENDqueryEtryPt \
+ if(iRet == RS_RET_OK)\
+ iRet = (*pEtryPoint == NULL) ? RS_RET_NOT_FOUND : RS_RET_OK;\
+ return iRet;\
+}
+
+/* the following definition is the standard block for queryEtryPt for output
+ * modules. This can be used if no specific handling (e.g. to cover version
+ * differences) is needed.
+ */
+#define CODEqueryEtryPt_STD_OMOD_QUERIES\
+ if(!strcmp((char*) name, "doAction")) {\
+ *pEtryPoint = doAction;\
+ } else if(!strcmp((char*) name, "parseSelectorAct")) {\
+ *pEtryPoint = parseSelectorAct;\
+ } else if(!strcmp((char*) name, "isCompatibleWithFeature")) {\
+ *pEtryPoint = isCompatibleWithFeature;\
+ } else if(!strcmp((char*) name, "dbgPrintInstInfo")) {\
+ *pEtryPoint = dbgPrintInstInfo;\
+ } else if(!strcmp((char*) name, "freeInstance")) {\
+ *pEtryPoint = freeInstance;\
+ } else if(!strcmp((char*) name, "getWriteFDForSelect")) {\
+ *pEtryPoint = getWriteFDForSelect;\
+ } else if(!strcmp((char*) name, "onSelectReadyWrite")) {\
+ *pEtryPoint = onSelectReadyWrite;\
+ } else if(!strcmp((char*) name, "needUDPSocket")) {\
+ *pEtryPoint = needUDPSocket;\
+ } else if(!strcmp((char*) name, "tryResume")) {\
+ *pEtryPoint = tryResume;\
+ }
+
+/* modInit()
+ * This has an extra parameter, which is the specific name of the modInit
+ * function. That is needed for built-in modules, which must have unique
+ * names in order to link statically.
+ *
+ * Extra Comments:
+ * initialize the module
+ *
+ * Later, much more must be done. So far, we only return a pointer
+ * to the queryEtryPt() function
+ * TODO: do interface version checking & handshaking
+ * iIfVersRequeted is the version of the interface specification that the
+ * caller would like to see being used. ipIFVersProvided is what we
+ * decide to provide.
+ */
+#define BEGINmodInit(uniqName) \
+rsRetVal modInit##uniqName(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()))\
+{\
+ DEFiRet;
+
+#define CODESTARTmodInit \
+ assert(pHostQueryEtryPt != NULL);\
+ if((pQueryEtryPt == NULL) || (ipIFVersProvided == NULL))\
+ return RS_RET_PARAM_ERROR;
+
+#define ENDmodInit \
+finalize_it:\
+ *pQueryEtryPt = queryEtryPt;\
+ return iRet;\
+}
+
+
+/* definitions for host API queries */
+#define CODEmodInit_QueryRegCFSLineHdlr \
+ CHKiRet(pHostQueryEtryPt((uchar*)"regCfSysLineHdlr", &omsdRegCFSLineHdlr));
+
+#endif /* #ifndef MODULE_TEMPLATE_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/module.h b/module.h
new file mode 100644
index 0000000..cb8e243
--- /dev/null
+++ b/module.h
@@ -0,0 +1,61 @@
+/* Module definitions for klogd's module support */
+struct kernel_sym
+{
+ unsigned long value;
+ char name[60];
+};
+
+struct module_symbol
+{
+ unsigned long value;
+ const char *name;
+};
+
+struct module_ref
+{
+ struct module *dep; /* "parent" pointer */
+ struct module *ref; /* "child" pointer */
+ struct module_ref *next_ref;
+};
+
+struct module_info
+{
+ unsigned long addr;
+ unsigned long size;
+ unsigned long flags;
+ long usecount;
+};
+
+
+typedef struct { volatile int counter; } atomic_t;
+
+struct module
+{
+ unsigned long size_of_struct; /* == sizeof(module) */
+ struct module *next;
+ const char *name;
+ unsigned long size;
+
+ union
+ {
+ atomic_t usecount;
+ long pad;
+ } uc; /* Needs to keep its size - so says rth */
+
+ unsigned long flags; /* AUTOCLEAN et al */
+
+ unsigned nsyms;
+ unsigned ndeps;
+
+ struct module_symbol *syms;
+ struct module_ref *deps;
+ struct module_ref *refs;
+ int (*init)(void);
+ void (*cleanup)(void);
+ const struct exception_table_entry *ex_table_start;
+ const struct exception_table_entry *ex_table_end;
+#ifdef __alpha__
+ unsigned long gp;
+#endif
+};
+
diff --git a/modules.c b/modules.c
new file mode 100644
index 0000000..5ecceec
--- /dev/null
+++ b/modules.c
@@ -0,0 +1,334 @@
+/* modules.c
+ * This is the implementation of syslogd modules object.
+ * This object handles plug-ins and buil-in modules of all kind.
+ *
+ * File begun on 2007-07-22 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <sys/file.h>
+
+#include "syslogd.h"
+#include "cfsysline.h"
+#include "modules.h"
+
+static modInfo_t *pLoadedModules = NULL; /* list of currently-loaded modules */
+static modInfo_t *pLoadedModulesLast = NULL; /* tail-pointer */
+static int bCfsyslineInitialized = 0;
+
+
+/* Construct a new module object
+ */
+static rsRetVal moduleConstruct(modInfo_t **pThis)
+{
+ modInfo_t *pNew;
+
+ if((pNew = calloc(1, sizeof(modInfo_t))) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ /* OK, we got the element, now initialize members that should
+ * not be zero-filled.
+ */
+
+ *pThis = pNew;
+ return RS_RET_OK;
+}
+
+
+/* Destructs a module objects. The object must not be linked to the
+ * linked list of modules.
+ */
+static void moduleDestruct(modInfo_t *pThis)
+{
+ if(pThis->pszName != NULL)
+ free(pThis->pszName);
+ free(pThis);
+}
+
+
+/* The followind function is the queryEntryPoint for host-based entry points.
+ * Modules may call it to get access to core interface functions. Please note
+ * that utility functions can be accessed via shared libraries - at least this
+ * is my current shool of thinking.
+ * Please note that the implementation as a query interface allows to take
+ * care of plug-in interface version differences. -- rgerhards, 2007-07-31
+ */
+rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)())
+{
+ DEFiRet;
+
+ if((name == NULL) || (pEtryPoint == NULL))
+ return RS_RET_PARAM_ERROR;
+
+ if(!strcmp((char*) name, "regCfSysLineHdlr")) {
+ *pEtryPoint = regCfSysLineHdlr;
+ }
+
+ if(iRet == RS_RET_OK)
+ iRet = (*pEtryPoint == NULL) ? RS_RET_NOT_FOUND : RS_RET_OK;
+ return iRet;
+}
+
+
+/* get the state-name of a module. The state name is its name
+ * together with a short description of the module state (which
+ * is pulled from the module itself.
+ * rgerhards, 2007-07-24
+ * TODO: the actual state name is not yet pulled
+ */
+uchar *modGetStateName(modInfo_t *pThis)
+{
+ return(modGetName(pThis));
+}
+
+
+/* get the name of a module
+ */
+uchar *modGetName(modInfo_t *pThis)
+{
+ return((pThis->pszName == NULL) ? (uchar*) "" : pThis->pszName);
+}
+
+
+/* Add a module to the loaded module linked list
+ */
+static inline void addModToList(modInfo_t *pThis)
+{
+ assert(pThis != NULL);
+
+ if(pLoadedModules == NULL) {
+ pLoadedModules = pLoadedModulesLast = pThis;
+ } else {
+ /* there already exist entries */
+ pLoadedModulesLast->pNext = pThis;
+ pLoadedModulesLast = pThis;
+ }
+}
+
+
+/* Get the next module pointer - this is used to traverse the list.
+ * The function returns the next pointer or NULL, if there is no next one.
+ * The last object must be provided to the function. If NULL is provided,
+ * it starts at the root of the list. Even in this case, NULL may be
+ * returned - then, the list is empty.
+ * rgerhards, 2007-07-23
+ */
+modInfo_t *modGetNxt(modInfo_t *pThis)
+{
+ modInfo_t *pNew;
+
+ if(pThis == NULL)
+ pNew = pLoadedModules;
+ else
+ pNew = pThis->pNext;
+
+ return(pNew);
+}
+
+
+/* this function is like modGetNxt(), but it returns pointers to
+ * output modules only. As we currently deal just with output modules,
+ * it is a dummy, to be filled with real code later.
+ * rgerhards, 2007-07-24
+ */
+modInfo_t *omodGetNxt(modInfo_t *pThis)
+{
+ return(modGetNxt(pThis));
+}
+
+
+/* unload a module. If this is called with a statically-linked
+ * (builtin) module, nothing happens.
+ * The module handle is invalid after this function call and
+ * MUST NOT be used any more.
+ * This is currently a dummy, to be filled when we have a plug-in interface
+ * rgerhards, 2007-08-09
+ */
+static rsRetVal modUnload(modInfo_t *pThis)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+
+ if(pThis->eLinkType == eMOD_LINK_STATIC) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* TODO: implement code */
+ ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Add an already-loaded module to the module linked list. This function does
+ * everything needed to fully initialize the module.
+ */
+rsRetVal doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)()), uchar *name)
+{
+ DEFiRet;
+ modInfo_t *pNew;
+
+ assert(modInit != NULL);
+
+ if(bCfsyslineInitialized == 0) {
+ /* we need to initialize the cfsysline subsystem first */
+ CHKiRet(cfsyslineInit());
+ bCfsyslineInitialized = 1;
+ }
+
+ if((iRet = moduleConstruct(&pNew)) != RS_RET_OK)
+ return iRet;
+
+ if((iRet = (*modInit)(1, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+
+ if(pNew->iIFVers != 1) {
+ moduleDestruct(pNew);
+ return RS_RET_MISSING_INTERFACE;
+ }
+
+ /* OK, we know we can successfully work with the module. So we now fill the
+ * rest of the data elements.
+ */
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"doAction", &pNew->mod.om.doAction)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"isCompatibleWithFeature",
+ &pNew->isCompatibleWithFeature)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"dbgPrintInstInfo",
+ &pNew->dbgPrintInstInfo)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"getWriteFDForSelect", &pNew->getWriteFDForSelect)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"onSelectReadyWrite", &pNew->onSelectReadyWrite)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"needUDPSocket", &pNew->needUDPSocket)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+ if((iRet = (*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance)) != RS_RET_OK) {
+ moduleDestruct(pNew);
+ return iRet;
+ }
+
+ pNew->pszName = (uchar*) strdup((char*)name); /* we do not care if strdup() fails, we can accept that */
+ pNew->eType = eMOD_OUT; /* TODO: take this from module */
+ pNew->eLinkType = eMOD_LINK_STATIC; /* TODO: take this from module */
+
+ /* we initialized the structure, now let's add it to the linked list of modules */
+ addModToList(pNew);
+
+finalize_it:
+ return iRet;
+}
+
+/* Print loaded modules. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ * This only works if the dbgprintf() subsystem is initialized.
+ */
+void modPrintList(void)
+{
+ modInfo_t *pMod;
+
+ pMod = modGetNxt(NULL);
+ while(pMod != NULL) {
+ dbgprintf("Loaded Module: Name='%s', IFVersion=%d, ",
+ (char*) modGetName(pMod), pMod->iIFVers);
+ dbgprintf("type=");
+ switch(pMod->eType) {
+ case eMOD_OUT:
+ dbgprintf("output");
+ break;
+ case eMOD_IN:
+ dbgprintf("input");
+ break;
+ case eMOD_FILTER:
+ dbgprintf("filter");
+ break;
+ }
+ dbgprintf(" module.\n");
+ dbgprintf("Entry points:\n");
+ dbgprintf("\tqueryEtryPt: 0x%x\n", (unsigned) pMod->modQueryEtryPt);
+ dbgprintf("\tdoAction: 0x%x\n", (unsigned) pMod->mod.om.doAction);
+ dbgprintf("\tparseSelectorAct: 0x%x\n", (unsigned) pMod->mod.om.parseSelectorAct);
+ dbgprintf("\tdbgPrintInstInfo: 0x%x\n", (unsigned) pMod->dbgPrintInstInfo);
+ dbgprintf("\tfreeInstance: 0x%x\n", (unsigned) pMod->freeInstance);
+ dbgprintf("\n");
+ pMod = modGetNxt(pMod); /* done, go next */
+ }
+}
+
+
+/* unload all modules and free module linked list
+ * rgerhards, 2007-08-09
+ */
+rsRetVal modUnloadAndDestructAll(void)
+{
+ DEFiRet;
+ modInfo_t *pMod;
+ modInfo_t *pModPrev;
+
+ pMod = modGetNxt(NULL);
+ while(pMod != NULL) {
+ pModPrev = pMod;
+ pMod = modGetNxt(pModPrev); /* get next */
+ /* now we can destroy the previous module */
+ dbgprintf("Unloading module %s\n", modGetName(pModPrev));
+ modUnload(pModPrev);
+ moduleDestruct(pModPrev);
+ }
+
+ return iRet;
+}
+/*
+ * vi:set ai:
+ */
diff --git a/modules.h b/modules.h
new file mode 100644
index 0000000..0fda461
--- /dev/null
+++ b/modules.h
@@ -0,0 +1,100 @@
+/* modules.h
+ * Definition for build-in and plug-ins module handler.
+ *
+ * The following definitions are to be used for modularization. Currently,
+ * the code is NOT complete. I am just adding pieces to it as I
+ * go along in designing the interface.
+ * rgerhards, 2007-07-19
+ *
+ *
+ * File begun on 2007-07-22 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef MODULES_H_INCLUDED
+#define MODULES_H_INCLUDED 1
+
+#include "objomsr.h"
+
+typedef enum eModType_ {
+ eMOD_IN, /* input module */
+ eMOD_OUT, /* output module */
+ eMOD_FILTER /* filter module (not know yet if we will once have such at all...) */
+} eModType_t;
+
+/* how is this module linked? */
+typedef enum eModLinkType_ {
+ eMOD_LINK_STATIC,
+ eMOD_LINK_DYNAMIC_UNLOADED, /* dynalink module, currently not loaded */
+ eMOD_LINK_DYNAMIC_LOADED /* dynalink module, currently loaded */
+} eModLinkType_t;
+
+typedef struct moduleInfo {
+ struct moduleInfo *pNext; /* support for creating a linked module list */
+ int iIFVers; /* Interface version of module */
+ eModType_t eType; /* type of this module */
+ eModLinkType_t eLinkType;
+ uchar* pszName; /* printable module name, e.g. for dbgprintf */
+ /* functions supported by all types of modules */
+ rsRetVal (*modInit)(int, int*, rsRetVal(**)()); /* initialize the module */
+ /* be sure to support version handshake! */
+ rsRetVal (*modQueryEtryPt)(uchar *name, rsRetVal (**EtryPoint)()); /* query entry point addresses */
+ rsRetVal (*isCompatibleWithFeature)(syslogFeature);
+ rsRetVal (*freeInstance)(void*);/* called before termination or module unload */
+ rsRetVal (*getWriteFDForSelect)(void*,short *);/* called before termination or module unload */
+ rsRetVal (*onSelectReadyWrite)(void*);/* called when fd is writeable after select() */
+ rsRetVal (*needUDPSocket)(void*);/* called when fd is writeable after select() */
+ rsRetVal (*dbgPrintInstInfo)(void*);/* called before termination or module unload */
+ rsRetVal (*tryResume)(void*);/* called to see if module actin can be resumed now */
+ rsRetVal (*modExit)(); /* called before termination or module unload */
+ /* below: parse a configuration line - return if processed
+ * or not. If not, must be parsed to next module.
+ */
+ rsRetVal (*parseConfigLine)(uchar **pConfLine);
+ /* below: create an instance of this module. Most importantly the module
+ * can allocate instance memory in this call.
+ */
+ rsRetVal (*createInstance)();
+ union {
+ struct {/* data for input modules */
+ /* input modules come after output modules are finished, I am
+ * currently not really thinking about them. rgerhards, 2007-07-19
+ */
+ } im;
+ struct {/* data for output modules */
+ /* below: perform the configured action
+ */
+ rsRetVal (*doAction)(uchar**, unsigned, void*);
+ rsRetVal (*parseSelectorAct)(uchar**, void**,omodStringRequest_t**);
+ } om;
+ } mod;
+} modInfo_t;
+
+/* prototypes */
+rsRetVal doModInit(rsRetVal (*modInit)(), uchar *name);
+modInfo_t *omodGetNxt(modInfo_t *pThis);
+uchar *modGetName(modInfo_t *pThis);
+uchar *modGetStateName(modInfo_t *pThis);
+void modPrintList(void);
+rsRetVal modUnloadAndDestructAll(void);
+
+#endif /* #ifndef MODULES_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/msg.c b/msg.c
new file mode 100644
index 0000000..3ba92b1
--- /dev/null
+++ b/msg.c
@@ -0,0 +1,1642 @@
+/* msg.c
+ * The msg object. Implementation of all msg-related functions
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include "syslogd.h"
+#include "srUtils.h"
+#include "template.h"
+#include "msg.h"
+
+/* The following functions will support advanced output module
+ * multithreading, once this is implemented. Currently, we
+ * include them as hooks only. The idea is that we need to guard
+ * some msg objects data fields against concurrent access if
+ * we run on multiple threads. Please note that in any case this
+ * is not necessary for calls from INPUT modules, because they
+ * construct the message object and do this serially. Only when
+ * the message is in the processing queue, multiple threads may
+ * access a single object. Consequently, there are no guard functions
+ * for "set" methods, as these are called during input. Only "get"
+ * functions that modify important structures have them.
+ * rgerhards, 2007-07-20
+ */
+#define MsgLock(pMsg)
+#define MsgUnlock(pMsg)
+
+
+/* "Constructor" for a msg "object". Returns a pointer to
+ * the new object or NULL if no such object could be allocated.
+ * An object constructed via this function should only be destroyed
+ * via "MsgDestruct()".
+ */
+msg_t* MsgConstruct(void)
+{
+ msg_t *pM;
+
+ if((pM = calloc(1, sizeof(msg_t))) != NULL)
+ { /* initialize members that are non-zero */
+ pM->iRefCount = 1;
+ pM->iSyslogVers = -1;
+ pM->iSeverity = -1;
+ pM->iFacility = -1;
+ getCurrTime(&(pM->tRcvdAt));
+ }
+
+ /* DEV debugging only! dbgprintf("MsgConstruct\t0x%x, ref 1\n", (int)pM);*/
+
+ return(pM);
+}
+
+
+/* Destructor for a msg "object". Must be called to dispose
+ * of a msg object.
+ */
+void MsgDestruct(msg_t * pM)
+{
+ assert(pM != NULL);
+ /* DEV Debugging only ! dbgprintf("MsgDestruct\t0x%x, Ref now: %d\n", (int)pM, pM->iRefCount - 1); */
+ MsgLock();
+ if(--pM->iRefCount == 0)
+ {
+ /* DEV Debugging Only! dbgprintf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); */
+ if(pM->pszUxTradMsg != NULL)
+ free(pM->pszUxTradMsg);
+ if(pM->pszRawMsg != NULL)
+ free(pM->pszRawMsg);
+ if(pM->pszTAG != NULL)
+ free(pM->pszTAG);
+ if(pM->pszHOSTNAME != NULL)
+ free(pM->pszHOSTNAME);
+ if(pM->pszRcvFrom != NULL)
+ free(pM->pszRcvFrom);
+ if(pM->pszMSG != NULL)
+ free(pM->pszMSG);
+ if(pM->pszFacility != NULL)
+ free(pM->pszFacility);
+ if(pM->pszFacilityStr != NULL)
+ free(pM->pszFacilityStr);
+ if(pM->pszSeverity != NULL)
+ free(pM->pszSeverity);
+ if(pM->pszSeverityStr != NULL)
+ free(pM->pszSeverityStr);
+ if(pM->pszRcvdAt3164 != NULL)
+ free(pM->pszRcvdAt3164);
+ if(pM->pszRcvdAt3339 != NULL)
+ free(pM->pszRcvdAt3339);
+ if(pM->pszRcvdAt_MySQL != NULL)
+ free(pM->pszRcvdAt_MySQL);
+ if(pM->pszTIMESTAMP3164 != NULL)
+ free(pM->pszTIMESTAMP3164);
+ if(pM->pszTIMESTAMP3339 != NULL)
+ free(pM->pszTIMESTAMP3339);
+ if(pM->pszTIMESTAMP_MySQL != NULL)
+ free(pM->pszTIMESTAMP_MySQL);
+ if(pM->pszPRI != NULL)
+ free(pM->pszPRI);
+ free(pM);
+ }
+ MsgUnlock();
+}
+
+
+/* The macros below are used in MsgDup(). I use macros
+ * to keep the fuction code somewhat more readyble. It is my
+ * replacement for inline functions in CPP
+ */
+#define tmpCOPYSZ(name) \
+ if(pOld->psz##name != NULL) { \
+ if((pNew->psz##name = srUtilStrDup(pOld->psz##name, pOld->iLen##name)) == NULL) {\
+ MsgDestruct(pNew);\
+ return NULL;\
+ }\
+ pNew->iLen##name = pOld->iLen##name;\
+ }
+
+/* copy the CStr objects.
+ * if the old value is NULL, we do not need to do anything because we
+ * initialized the new value to NULL via calloc().
+ */
+#define tmpCOPYCSTR(name) \
+ if(pOld->pCS##name != NULL) {\
+ if(rsCStrConstructFromCStr(&(pNew->pCS##name), pOld->pCS##name) != RS_RET_OK) {\
+ MsgDestruct(pNew);\
+ return NULL;\
+ }\
+ }
+/* Constructs a message object by duplicating another one.
+ * Returns NULL if duplication failed. We do not need to lock the
+ * message object here, because a fully-created msg object is never
+ * allowed to be manipulated. For this, MsgDup() must be used, so MsgDup()
+ * can never run into a situation where the message object is being
+ * modified while its content is copied - it's forbidden by definition.
+ * rgerhards, 2007-07-10
+ */
+msg_t* MsgDup(msg_t* pOld)
+{
+ msg_t* pNew;
+
+ assert(pOld != NULL);
+
+ if((pNew = (msg_t*) calloc(1, sizeof(msg_t))) == NULL) {
+ glblHadMemShortage = 1;
+ return NULL;
+ }
+
+ /* now copy the message properties */
+ pNew->iRefCount = 1;
+ pNew->iSyslogVers = pOld->iSyslogVers;
+ pNew->bParseHOSTNAME = pOld->bParseHOSTNAME;
+ pNew->iSeverity = pOld->iSeverity;
+ pNew->iFacility = pOld->iFacility;
+ pNew->bParseHOSTNAME = pOld->bParseHOSTNAME;
+ pNew->msgFlags = pOld->msgFlags;
+ pNew->iProtocolVersion = pOld->iProtocolVersion;
+ memcpy(&pNew->tRcvdAt, &pOld->tRcvdAt, sizeof(struct syslogTime));
+ memcpy(&pNew->tTIMESTAMP, &pOld->tTIMESTAMP, sizeof(struct syslogTime));
+ tmpCOPYSZ(Severity);
+ tmpCOPYSZ(SeverityStr);
+ tmpCOPYSZ(Facility);
+ tmpCOPYSZ(FacilityStr);
+ tmpCOPYSZ(PRI);
+ tmpCOPYSZ(RawMsg);
+ tmpCOPYSZ(MSG);
+ tmpCOPYSZ(UxTradMsg);
+ tmpCOPYSZ(TAG);
+ tmpCOPYSZ(HOSTNAME);
+ tmpCOPYSZ(RcvFrom);
+
+ tmpCOPYCSTR(ProgName);
+ tmpCOPYCSTR(StrucData);
+ tmpCOPYCSTR(APPNAME);
+ tmpCOPYCSTR(PROCID);
+ tmpCOPYCSTR(MSGID);
+
+ /* we do not copy all other cache properties, as we do not even know
+ * if they are needed once again. So we let them re-create if needed.
+ */
+
+ return pNew;
+}
+#undef tmpCOPYSZ
+#undef tmpCOPYCSTR
+
+
+/* Increment reference count - see description of the "msg"
+ * structure for details. As a convenience to developers,
+ * this method returns the msg pointer that is passed to it.
+ * It is recommended that it is called as follows:
+ *
+ * pSecondMsgPointer = MsgAddRef(pOrgMsgPointer);
+ */
+msg_t *MsgAddRef(msg_t *pM)
+{
+ assert(pM != NULL);
+ MsgLock();
+ pM->iRefCount++;
+ MsgUnlock();
+ /* DEV debugging only! dbgprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount);*/
+ return(pM);
+}
+
+
+/* This functions tries to aquire the PROCID from TAG. Its primary use is
+ * when a legacy syslog message has been received and should be forwarded as
+ * syslog-protocol (or the PROCID is requested for any other reason).
+ * In legacy syslog, the PROCID is considered to be the character sequence
+ * between the first [ and the first ]. This usually are digits only, but we
+ * do not check that. However, if there is no closing ], we do not assume we
+ * can obtain a PROCID. Take in mind that not every legacy syslog message
+ * actually has a PROCID.
+ * rgerhards, 2005-11-24
+ */
+static rsRetVal aquirePROCIDFromTAG(msg_t *pM)
+{
+ register int i;
+ int iRet;
+
+ assert(pM != NULL);
+ if(pM->pCSPROCID != NULL)
+ return RS_RET_OK; /* we are already done ;) */
+
+ if(getProtocolVersion(pM) != 0)
+ return RS_RET_OK; /* we can only emulate if we have legacy format */
+
+ /* find first '['... */
+ i = 0;
+ while((i < pM->iLenTAG) && (pM->pszTAG[i] != '['))
+ ++i;
+ if(!(i < pM->iLenTAG))
+ return RS_RET_OK; /* no [, so can not emulate... */
+
+ ++i; /* skip '[' */
+
+ /* now obtain the PROCID string... */
+ if((pM->pCSPROCID = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pM->pCSPROCID, 16);
+ while((i < pM->iLenTAG) && (pM->pszTAG[i] != ']')) {
+ if((iRet = rsCStrAppendChar(pM->pCSPROCID, pM->pszTAG[i])) != RS_RET_OK)
+ return iRet;
+ ++i;
+ }
+
+ if(!(i < pM->iLenTAG)) {
+ /* oops... it looked like we had a PROCID, but now it has
+ * turned out this is not true. In this case, we need to free
+ * the buffer and simply return. Note that this is NOT an error
+ * case!
+ */
+ rsCStrDestruct(pM->pCSPROCID);
+ pM->pCSPROCID = NULL;
+ return RS_RET_OK;
+ }
+
+ /* OK, finaally we could obtain a PROCID. So let's use it ;) */
+ if((iRet = rsCStrFinish(pM->pCSPROCID)) != RS_RET_OK)
+ return iRet;
+
+ return RS_RET_OK;
+}
+
+
+/* Parse and set the "programname" for a given MSG object. Programname
+ * is a BSD concept, it is the tag without any instance-specific information.
+ * Precisely, the programname is terminated by either (whichever occurs first):
+ * - end of tag
+ * - nonprintable character
+ * - ':'
+ * - '['
+ * - '/'
+ * The above definition has been taken from the FreeBSD syslogd sources.
+ *
+ * The program name is not parsed by default, because it is infrequently-used.
+ * If it is needed, this function should be called first. It checks if it is
+ * already set and extracts it, if not.
+ * A message object must be provided, else a crash will occur.
+ * rgerhards, 2005-10-19
+ */
+static rsRetVal aquireProgramName(msg_t *pM)
+{
+ register int i;
+ int iRet;
+
+ assert(pM != NULL);
+ if(pM->pCSProgName == NULL) {
+ /* ok, we do not yet have it. So let's parse the TAG
+ * to obtain it.
+ */
+ if((pM->pCSProgName = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pM->pCSProgName, 33);
+ for( i = 0
+ ; (i < pM->iLenTAG) && isprint((int) pM->pszTAG[i])
+ && (pM->pszTAG[i] != '\0') && (pM->pszTAG[i] != ':')
+ && (pM->pszTAG[i] != '[') && (pM->pszTAG[i] != '/')
+ ; ++i) {
+ if((iRet = rsCStrAppendChar(pM->pCSProgName, pM->pszTAG[i])) != RS_RET_OK)
+ return iRet;
+ }
+ if((iRet = rsCStrFinish(pM->pCSProgName)) != RS_RET_OK)
+ return iRet;
+ }
+ return RS_RET_OK;
+}
+
+
+/* This function moves the HOSTNAME inside the message object to the
+ * TAG. It is a specialised function used to handle the condition when
+ * a message without HOSTNAME is being processed. The missing HOSTNAME
+ * is only detected at a later stage, during TAG processing, so that
+ * we already had set the HOSTNAME property and now need to move it to
+ * the TAG. Of course, we could do this via a couple of get/set methods,
+ * but it is far more efficient to do it via this specialised method.
+ * This is especially important as this can be a very common case, e.g.
+ * when BSD syslog is acting as a sender.
+ * rgerhards, 2005-11-10.
+ */
+void moveHOSTNAMEtoTAG(msg_t *pM)
+{
+ assert(pM != NULL);
+ if(pM->pszTAG != NULL)
+ free(pM->pszTAG);
+ pM->pszTAG = pM->pszHOSTNAME;
+ pM->iLenTAG = pM->iLenHOSTNAME;
+ pM->pszHOSTNAME = NULL;
+ pM->iLenHOSTNAME = 0;
+}
+
+/* Access methods - dumb & easy, not a comment for each ;)
+ */
+void setProtocolVersion(msg_t *pM, int iNewVersion)
+{
+ assert(pM != NULL);
+ if(iNewVersion != 0 && iNewVersion != 1) {
+ dbgprintf("Tried to set unsupported protocol version %d - changed to 0.\n", iNewVersion);
+ iNewVersion = 0;
+ }
+ pM->iProtocolVersion = iNewVersion;
+}
+
+int getProtocolVersion(msg_t *pM)
+{
+ assert(pM != NULL);
+ return(pM->iProtocolVersion);
+}
+
+/* note: string is taken from constant pool, do NOT free */
+char *getProtocolVersionString(msg_t *pM)
+{
+ assert(pM != NULL);
+ return(pM->iProtocolVersion ? "1" : "0");
+}
+
+int getMSGLen(msg_t *pM)
+{
+ return((pM == NULL) ? 0 : pM->iLenMSG);
+}
+
+
+char *getRawMsg(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszRawMsg == NULL)
+ return "";
+ else
+ return (char*)pM->pszRawMsg;
+}
+
+char *getUxTradMsg(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszUxTradMsg == NULL)
+ return "";
+ else
+ return (char*)pM->pszUxTradMsg;
+}
+
+char *getMSG(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszMSG == NULL)
+ return "";
+ else
+ return (char*)pM->pszMSG;
+}
+
+
+/* Get PRI value in text form */
+char *getPRI(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+
+ MsgLock();
+ if(pM->pszPRI == NULL) {
+ /* OK, we need to construct it...
+ * we use a 5 byte buffer - as of
+ * RFC 3164, it can't be longer. Should it
+ * still be, snprintf will truncate...
+ */
+ if((pM->pszPRI = malloc(5)) == NULL) return "";
+ pM->iLenPRI = snprintf((char*)pM->pszPRI, 5, "%d",
+ LOG_MAKEPRI(pM->iFacility, pM->iSeverity));
+ }
+ MsgUnlock();
+
+ return (char*)pM->pszPRI;
+}
+
+
+/* Get PRI value as integer */
+int getPRIi(msg_t *pM)
+{
+ assert(pM != NULL);
+ return (pM->iFacility << 3) + (pM->iSeverity);
+}
+
+
+char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt)
+{
+ if(pM == NULL)
+ return "";
+
+ switch(eFmt) {
+ case tplFmtDefault:
+ MsgLock();
+ if(pM->pszTIMESTAMP3164 == NULL) {
+ if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16);
+ }
+ MsgUnlock();
+ return(pM->pszTIMESTAMP3164);
+ case tplFmtMySQLDate:
+ MsgLock();
+ if(pM->pszTIMESTAMP_MySQL == NULL) {
+ if((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestampToMySQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_MySQL, 15);
+ }
+ MsgUnlock();
+ return(pM->pszTIMESTAMP_MySQL);
+ case tplFmtRFC3164Date:
+ MsgLock();
+ if(pM->pszTIMESTAMP3164 == NULL) {
+ if((pM->pszTIMESTAMP3164 = malloc(16)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, 16);
+ }
+ MsgUnlock();
+ return(pM->pszTIMESTAMP3164);
+ case tplFmtRFC3339Date:
+ MsgLock();
+ if(pM->pszTIMESTAMP3339 == NULL) {
+ if((pM->pszTIMESTAMP3339 = malloc(33)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3339(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339, 33);
+ }
+ MsgUnlock();
+ return(pM->pszTIMESTAMP3339);
+ }
+ return "INVALID eFmt OPTION!";
+}
+
+char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt)
+{
+ if(pM == NULL)
+ return "";
+
+ switch(eFmt) {
+ case tplFmtDefault:
+ MsgLock();
+ if(pM->pszRcvdAt3164 == NULL) {
+ if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16);
+ }
+ MsgUnlock();
+ return(pM->pszRcvdAt3164);
+ case tplFmtMySQLDate:
+ MsgLock();
+ if(pM->pszRcvdAt_MySQL == NULL) {
+ if((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestampToMySQL(&pM->tRcvdAt, pM->pszRcvdAt_MySQL, 15);
+ }
+ MsgUnlock();
+ return(pM->pszRcvdAt_MySQL);
+ case tplFmtRFC3164Date:
+ MsgLock();
+ if(pM->pszRcvdAt3164 == NULL) {
+ if((pM->pszRcvdAt3164 = malloc(16)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3164(&pM->tRcvdAt, pM->pszRcvdAt3164, 16);
+ }
+ MsgUnlock();
+ return(pM->pszRcvdAt3164);
+ case tplFmtRFC3339Date:
+ MsgLock();
+ if(pM->pszRcvdAt3339 == NULL) {
+ if((pM->pszRcvdAt3339 = malloc(33)) == NULL) {
+ glblHadMemShortage = 1;
+ MsgUnlock();
+ return "";
+ }
+ formatTimestamp3339(&pM->tRcvdAt, pM->pszRcvdAt3339, 33);
+ }
+ MsgUnlock();
+ return(pM->pszRcvdAt3339);
+ }
+ return "INVALID eFmt OPTION!";
+}
+
+
+char *getSeverity(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+
+ MsgLock();
+ if(pM->pszSeverity == NULL) {
+ /* we use a 2 byte buffer - can only be one digit */
+ if((pM->pszSeverity = malloc(2)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenSeverity =
+ snprintf((char*)pM->pszSeverity, 2, "%d", pM->iSeverity);
+ }
+ MsgUnlock();
+ return((char*)pM->pszSeverity);
+}
+
+
+char *getSeverityStr(msg_t *pM)
+{
+ syslogCODE *c;
+ int val;
+ char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ MsgLock();
+ if(pM->pszSeverityStr == NULL) {
+ for(c = rs_prioritynames, val = pM->iSeverity; c->c_name; c++)
+ if(c->c_val == val) {
+ name = c->c_name;
+ break;
+ }
+ if(name == NULL) {
+ /* we use a 2 byte buffer - can only be one digit */
+ if((pM->pszSeverityStr = malloc(2)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenSeverityStr =
+ snprintf((char*)pM->pszSeverityStr, 2, "%d", pM->iSeverity);
+ } else {
+ if((pM->pszSeverityStr = (uchar*) strdup(name)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenSeverityStr = strlen((char*)name);
+ }
+ }
+ MsgUnlock();
+ return((char*)pM->pszSeverityStr);
+}
+
+char *getFacility(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+
+ MsgLock();
+ if(pM->pszFacility == NULL) {
+ /* we use a 12 byte buffer - as of
+ * syslog-protocol, facility can go
+ * up to 2^32 -1
+ */
+ if((pM->pszFacility = malloc(12)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenFacility =
+ snprintf((char*)pM->pszFacility, 12, "%d", pM->iFacility);
+ }
+ MsgUnlock();
+ return((char*)pM->pszFacility);
+}
+
+char *getFacilityStr(msg_t *pM)
+{
+ syslogCODE *c;
+ int val;
+ char *name = NULL;
+
+ if(pM == NULL)
+ return "";
+
+ MsgLock();
+ if(pM->pszFacilityStr == NULL) {
+ for(c = rs_facilitynames, val = pM->iFacility << 3; c->c_name; c++)
+ if(c->c_val == val) {
+ name = c->c_name;
+ break;
+ }
+ if(name == NULL) {
+ /* we use a 12 byte buffer - as of
+ * syslog-protocol, facility can go
+ * up to 2^32 -1
+ */
+ if((pM->pszFacilityStr = malloc(12)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenFacilityStr =
+ snprintf((char*)pM->pszFacilityStr, 12, "%d", val >> 3);
+ } else {
+ if((pM->pszFacilityStr = (uchar*)strdup(name)) == NULL) { MsgUnlock() ; return ""; }
+ pM->iLenFacilityStr = strlen((char*)name);
+ }
+ }
+ MsgUnlock();
+ return((char*)pM->pszFacilityStr);
+}
+
+
+/* rgerhards 2004-11-24: set APP-NAME in msg object
+ */
+rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pCSAPPNAME == NULL) {
+ /* we need to obtain the object first */
+ if((pMsg->pCSAPPNAME = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pMsg->pCSAPPNAME, 128);
+ }
+ /* if we reach this point, we have the object */
+ return rsCStrSetSzStr(pMsg->pCSAPPNAME, (uchar*) pszAPPNAME);
+}
+
+
+/* This function tries to emulate APPNAME if it is not present. Its
+ * main use is when we have received a log record via legacy syslog and
+ * now would like to send out the same one via syslog-protocol.
+ */
+static void tryEmulateAPPNAME(msg_t *pM)
+{
+ assert(pM != NULL);
+ if(pM->pCSAPPNAME != NULL)
+ return; /* we are already done */
+
+ if(getProtocolVersion(pM) == 0) {
+ /* only then it makes sense to emulate */
+ MsgSetAPPNAME(pM, getProgramName(pM));
+ }
+}
+
+
+/* rgerhards, 2005-11-24
+ */
+int getAPPNAMELen(msg_t *pM)
+{
+ assert(pM != NULL);
+ MsgLock();
+ if(pM->pCSAPPNAME == NULL)
+ tryEmulateAPPNAME(pM);
+ MsgUnlock();
+ return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME);
+}
+
+
+/* rgerhards, 2005-11-24
+ */
+char *getAPPNAME(msg_t *pM)
+{
+ assert(pM != NULL);
+ MsgLock();
+ if(pM->pCSAPPNAME == NULL)
+ tryEmulateAPPNAME(pM);
+ MsgUnlock();
+ return (pM->pCSAPPNAME == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSAPPNAME);
+}
+
+
+
+
+/* rgerhards 2004-11-24: set PROCID in msg object
+ */
+rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pCSPROCID == NULL) {
+ /* we need to obtain the object first */
+ if((pMsg->pCSPROCID = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pMsg->pCSPROCID, 128);
+ }
+ /* if we reach this point, we have the object */
+ return rsCStrSetSzStr(pMsg->pCSPROCID, (uchar*) pszPROCID);
+}
+
+/* rgerhards, 2005-11-24
+ */
+int getPROCIDLen(msg_t *pM)
+{
+ assert(pM != NULL);
+ MsgLock();
+ if(pM->pCSPROCID == NULL)
+ aquirePROCIDFromTAG(pM);
+ MsgUnlock();
+ return (pM->pCSPROCID == NULL) ? 1 : rsCStrLen(pM->pCSPROCID);
+}
+
+
+/* rgerhards, 2005-11-24
+ */
+char *getPROCID(msg_t *pM)
+{
+ assert(pM != NULL);
+ MsgLock();
+ if(pM->pCSPROCID == NULL)
+ aquirePROCIDFromTAG(pM);
+ MsgUnlock();
+ return (pM->pCSPROCID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSPROCID);
+}
+
+
+/* rgerhards 2004-11-24: set MSGID in msg object
+ */
+rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pCSMSGID == NULL) {
+ /* we need to obtain the object first */
+ if((pMsg->pCSMSGID = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pMsg->pCSMSGID, 128);
+ }
+ /* if we reach this point, we have the object */
+ return rsCStrSetSzStr(pMsg->pCSMSGID, (uchar*) pszMSGID);
+}
+
+/* rgerhards, 2005-11-24
+ */
+#if 0 /* This method is currently not called, be we like to preserve it */
+static int getMSGIDLen(msg_t *pM)
+{
+ return (pM->pCSMSGID == NULL) ? 1 : rsCStrLen(pM->pCSMSGID);
+}
+#endif
+
+
+/* rgerhards, 2005-11-24
+ */
+char *getMSGID(msg_t *pM)
+{
+ return (pM->pCSMSGID == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSMSGID);
+}
+
+
+/* Set the TAG to a caller-provided string. This is thought
+ * to be a heap buffer that the caller will no longer use. This
+ * function is a performance optimization over MsgSetTAG().
+ * rgerhards 2004-11-19
+ */
+void MsgAssignTAG(msg_t *pMsg, char *pBuf)
+{
+ assert(pMsg != NULL);
+ pMsg->iLenTAG = (pBuf == NULL) ? 0 : strlen(pBuf);
+ pMsg->pszTAG = (uchar*) pBuf;
+}
+
+
+/* rgerhards 2004-11-16: set TAG in msg object
+ */
+void MsgSetTAG(msg_t *pMsg, char* pszTAG)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pszTAG != NULL)
+ free(pMsg->pszTAG);
+ pMsg->iLenTAG = strlen(pszTAG);
+ if((pMsg->pszTAG = malloc(pMsg->iLenTAG + 1)) != NULL)
+ memcpy(pMsg->pszTAG, pszTAG, pMsg->iLenTAG + 1);
+ else
+ dbgprintf("Could not allocate memory in MsgSetTAG()\n");
+}
+
+
+/* This function tries to emulate the TAG if none is
+ * set. Its primary purpose is to provide an old-style TAG
+ * when a syslog-protocol message has been received. Then,
+ * the tag is APP-NAME "[" PROCID "]". The function first checks
+ * if there is a TAG and, if not, if it can emulate it.
+ * rgerhards, 2005-11-24
+ */
+static void tryEmulateTAG(msg_t *pM)
+{
+ int iTAGLen;
+ char *pBuf;
+ assert(pM != NULL);
+
+ if(pM->pszTAG != NULL)
+ return; /* done, no need to emulate */
+
+ if(getProtocolVersion(pM) == 1) {
+ if(!strcmp(getPROCID(pM), "-")) {
+ /* no process ID, use APP-NAME only */
+ MsgSetTAG(pM, getAPPNAME(pM));
+ } else {
+ /* now we can try to emulate */
+ iTAGLen = getAPPNAMELen(pM) + getPROCIDLen(pM) + 3;
+ if((pBuf = malloc(iTAGLen * sizeof(char))) == NULL)
+ return; /* nothing we can do */
+ snprintf(pBuf, iTAGLen, "%s[%s]", getAPPNAME(pM), getPROCID(pM));
+ MsgAssignTAG(pM, pBuf);
+ }
+ }
+}
+
+
+#if 0 /* This method is currently not called, be we like to preserve it */
+static int getTAGLen(msg_t *pM)
+{
+ if(pM == NULL)
+ return 0;
+ else {
+ tryEmulateTAG(pM);
+ if(pM->pszTAG == NULL)
+ return 0;
+ else
+ return pM->iLenTAG;
+ }
+}
+#endif
+
+
+char *getTAG(msg_t *pM)
+{
+ char *ret;
+
+ MsgLock();
+ if(pM == NULL)
+ ret = "";
+ else {
+ tryEmulateTAG(pM);
+ if(pM->pszTAG == NULL)
+ ret = "";
+ else
+ ret = (char*) pM->pszTAG;
+ }
+ MsgUnlock();
+ return(ret);
+}
+
+
+int getHOSTNAMELen(msg_t *pM)
+{
+ if(pM == NULL)
+ return 0;
+ else
+ if(pM->pszHOSTNAME == NULL)
+ return 0;
+ else
+ return pM->iLenHOSTNAME;
+}
+
+
+char *getHOSTNAME(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszHOSTNAME == NULL)
+ return "";
+ else
+ return (char*) pM->pszHOSTNAME;
+}
+
+
+char *getRcvFrom(msg_t *pM)
+{
+ if(pM == NULL)
+ return "";
+ else
+ if(pM->pszRcvFrom == NULL)
+ return "";
+ else
+ return (char*) pM->pszRcvFrom;
+}
+
+/* rgerhards 2004-11-24: set STRUCTURED DATA in msg object
+ */
+rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pCSStrucData == NULL) {
+ /* we need to obtain the object first */
+ if((pMsg->pCSStrucData = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pMsg->pCSStrucData, 128);
+ }
+ /* if we reach this point, we have the object */
+ return rsCStrSetSzStr(pMsg->pCSStrucData, (uchar*) pszStrucData);
+}
+
+/* get the length of the "STRUCTURED-DATA" sz string
+ * rgerhards, 2005-11-24
+ */
+#if 0 /* This method is currently not called, be we like to preserve it */
+static int getStructuredDataLen(msg_t *pM)
+{
+ return (pM->pCSStrucData == NULL) ? 1 : rsCStrLen(pM->pCSStrucData);
+}
+#endif
+
+
+/* get the "STRUCTURED-DATA" as sz string
+ * rgerhards, 2005-11-24
+ */
+char *getStructuredData(msg_t *pM)
+{
+ return (pM->pCSStrucData == NULL) ? "-" : (char*) rsCStrGetSzStrNoNULL(pM->pCSStrucData);
+}
+
+
+
+/* get the length of the "programname" sz string
+ * rgerhards, 2005-10-19
+ */
+int getProgramNameLen(msg_t *pM)
+{
+ int iRet;
+
+ assert(pM != NULL);
+ MsgLock();
+ if((iRet = aquireProgramName(pM)) != RS_RET_OK) {
+ dbgprintf("error %d returned by aquireProgramName() in getProgramNameLen()\n", iRet);
+ MsgUnlock();
+ return 0; /* best we can do (consistent wiht what getProgramName() returns) */
+ }
+ MsgUnlock();
+
+ return (pM->pCSProgName == NULL) ? 0 : rsCStrLen(pM->pCSProgName);
+}
+
+
+/* get the "programname" as sz string
+ * rgerhards, 2005-10-19
+ */
+char *getProgramName(msg_t *pM)
+{
+ int iRet;
+
+ assert(pM != NULL);
+ MsgLock();
+ if((iRet = aquireProgramName(pM)) != RS_RET_OK) {
+ dbgprintf("error %d returned by aquireProgramName() in getProgramName()\n", iRet);
+ MsgUnlock();
+ return ""; /* best we can do */
+ }
+ MsgUnlock();
+
+ return (pM->pCSProgName == NULL) ? "" : (char*) rsCStrGetSzStrNoNULL(pM->pCSProgName);
+}
+
+
+/* rgerhards 2004-11-16: set pszRcvFrom in msg object
+ */
+void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pszRcvFrom != NULL)
+ free(pMsg->pszRcvFrom);
+
+ pMsg->iLenRcvFrom = strlen(pszRcvFrom);
+ if((pMsg->pszRcvFrom = malloc(pMsg->iLenRcvFrom + 1)) != NULL) {
+ memcpy(pMsg->pszRcvFrom, pszRcvFrom, pMsg->iLenRcvFrom + 1);
+ }
+}
+
+
+/* Set the HOSTNAME to a caller-provided string. This is thought
+ * to be a heap buffer that the caller will no longer use. This
+ * function is a performance optimization over MsgSetHOSTNAME().
+ * rgerhards 2004-11-19
+ */
+void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf)
+{
+ assert(pMsg != NULL);
+ assert(pBuf != NULL);
+ pMsg->iLenHOSTNAME = strlen(pBuf);
+ pMsg->pszHOSTNAME = (uchar*) pBuf;
+}
+
+
+/* rgerhards 2004-11-09: set HOSTNAME in msg object
+ * rgerhards, 2007-06-21:
+ * Does not return anything. If an error occurs, the hostname is
+ * simply not set. I have changed this behaviour. The only problem
+ * we can run into is memory shortage. If we have such, it is better
+ * to loose the hostname than the full message. So we silently ignore
+ * that problem and hope that memory will be available the next time
+ * we need it. The rest of the code already knows how to handle an
+ * unset HOSTNAME.
+ */
+void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pszHOSTNAME != NULL)
+ free(pMsg->pszHOSTNAME);
+
+ pMsg->iLenHOSTNAME = strlen(pszHOSTNAME);
+ if((pMsg->pszHOSTNAME = malloc(pMsg->iLenHOSTNAME + 1)) != NULL)
+ memcpy(pMsg->pszHOSTNAME, pszHOSTNAME, pMsg->iLenHOSTNAME + 1);
+ else
+ dbgprintf("Could not allocate memory in MsgSetHOSTNAME()\n");
+}
+
+
+/* Set the UxTradMsg to a caller-provided string. This is thought
+ * to be a heap buffer that the caller will no longer use. This
+ * function is a performance optimization over MsgSetUxTradMsg().
+ * rgerhards 2004-11-19
+ */
+#if 0 /* This method is currently not called, be we like to preserve it */
+static void MsgAssignUxTradMsg(msg_t *pMsg, char *pBuf)
+{
+ assert(pMsg != NULL);
+ assert(pBuf != NULL);
+ pMsg->iLenUxTradMsg = strlen(pBuf);
+ pMsg->pszUxTradMsg = pBuf;
+}
+#endif
+
+
+/* rgerhards 2004-11-17: set the traditional Unix message in msg object
+ */
+int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg)
+{
+ assert(pMsg != NULL);
+ assert(pszUxTradMsg != NULL);
+ pMsg->iLenUxTradMsg = strlen(pszUxTradMsg);
+ if(pMsg->pszUxTradMsg != NULL)
+ free(pMsg->pszUxTradMsg);
+ if((pMsg->pszUxTradMsg = malloc(pMsg->iLenUxTradMsg + 1)) != NULL)
+ memcpy(pMsg->pszUxTradMsg, pszUxTradMsg, pMsg->iLenUxTradMsg + 1);
+ else
+ dbgprintf("Could not allocate memory for pszUxTradMsg buffer.");
+
+ return(0);
+}
+
+
+/* rgerhards 2004-11-09: set MSG in msg object
+ */
+void MsgSetMSG(msg_t *pMsg, char* pszMSG)
+{
+ assert(pMsg != NULL);
+ assert(pszMSG != NULL);
+
+ if(pMsg->pszMSG != NULL)
+ free(pMsg->pszMSG);
+
+ pMsg->iLenMSG = strlen(pszMSG);
+ if((pMsg->pszMSG = malloc(pMsg->iLenMSG + 1)) != NULL)
+ memcpy(pMsg->pszMSG, pszMSG, pMsg->iLenMSG + 1);
+ else
+ dbgprintf("MsgSetMSG could not allocate memory for pszMSG buffer.");
+}
+
+/* rgerhards 2004-11-11: set RawMsg in msg object
+ */
+void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg)
+{
+ assert(pMsg != NULL);
+ if(pMsg->pszRawMsg != NULL)
+ free(pMsg->pszRawMsg);
+
+ pMsg->iLenRawMsg = strlen(pszRawMsg);
+ if((pMsg->pszRawMsg = malloc(pMsg->iLenRawMsg + 1)) != NULL)
+ memcpy(pMsg->pszRawMsg, pszRawMsg, pMsg->iLenRawMsg + 1);
+ else
+ dbgprintf("Could not allocate memory for pszRawMsg buffer.");
+}
+
+
+/* Decode a priority into textual information like auth.emerg.
+ * The variable pRes must point to a user-supplied buffer and
+ * pResLen must contain its size. The pointer to the buffer
+ * is also returned, what makes this functiona suitable for
+ * use in printf-like functions.
+ * Note: a buffer size of 20 characters is always sufficient.
+ * Interface to this function changed 2007-06-15 by RGerhards
+ */
+char *textpri(char *pRes, size_t pResLen, int pri)
+{
+ syslogCODE *c_pri, *c_fac;
+
+ assert(pRes != NULL);
+ assert(pResLen > 0);
+
+ for (c_fac = rs_facilitynames; c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri)<<3); c_fac++);
+ for (c_pri = rs_prioritynames; c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
+
+ snprintf (pRes, pResLen, "%s.%s<%d>", c_fac->c_name, c_pri->c_name, pri);
+
+ return pRes;
+}
+
+
+/* This function returns the current date in different
+ * variants. It is used to construct the $NOW series of
+ * system properties. The returned buffer must be freed
+ * by the caller when no longer needed. If the function
+ * can not allocate memory, it returns a NULL pointer.
+ * Added 2007-07-10 rgerhards
+ */
+typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_MINUTE } eNOWType;
+#define tmpBUFSIZE 16 /* size of formatting buffer */
+static uchar *getNOW(eNOWType eNow)
+{
+ uchar *pBuf;
+ struct syslogTime t;
+
+ if((pBuf = (uchar*) malloc(sizeof(uchar) * tmpBUFSIZE)) == NULL) {
+ glblHadMemShortage = 1;
+ return NULL;
+ }
+
+ getCurrTime(&t);
+ switch(eNow) {
+ case NOW_NOW:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
+ break;
+ case NOW_YEAR:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d", t.year);
+ break;
+ case NOW_MONTH:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.month);
+ break;
+ case NOW_DAY:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.day);
+ break;
+ case NOW_HOUR:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.hour);
+ break;
+ case NOW_MINUTE:
+ snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.minute);
+ break;
+ }
+
+ return(pBuf);
+}
+#undef tmpBUFSIZE /* clean up */
+
+
+/* This function returns a string-representation of the
+ * requested message property. This is a generic function used
+ * to abstract properties so that these can be easier
+ * queried. Returns NULL if property could not be found.
+ * Actually, this function is a big if..elseif. What it does
+ * is simply to map property names (from MonitorWare) to the
+ * message object data fields.
+ *
+ * In case we need string forms of propertis we do not
+ * yet have in string form, we do a memory allocation that
+ * is sufficiently large (in all cases). Once the string
+ * form has been obtained, it is saved until the Msg object
+ * is finally destroyed. This is so that we save the processing
+ * time in the (likely) case that this property is requested
+ * again. It also saves us a lot of dynamic memory management
+ * issues in the upper layers, because we so can guarantee that
+ * the buffer will remain static AND available during the lifetime
+ * of the object. Please note that both the max size allocation as
+ * well as keeping things in memory might like look like a
+ * waste of memory (some might say it actually is...) - we
+ * deliberately accept this because performance is more important
+ * to us ;)
+ * rgerhards 2004-11-18
+ * Parameter "bMustBeFreed" is set by this function. It tells the
+ * caller whether or not the string returned must be freed by the
+ * caller itself. It is is 0, the caller MUST NOT free it. If it is
+ * 1, the caller MUST free 1. Handling this wrongly leads to either
+ * a memory leak of a program abort (do to double-frees or frees on
+ * the constant memory pool). So be careful to do it right.
+ * rgerhards 2004-11-23
+ * regular expression support contributed by Andres Riancho merged
+ * on 2005-09-13
+ * changed so that it now an be called without a template entry (NULL).
+ * In this case, only the (unmodified) property is returned. This will
+ * be used in selector line processing.
+ * rgerhards 2005-09-15
+ */
+char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
+ rsCStrObj *pCSPropName, unsigned short *pbMustBeFreed)
+{
+ char *pName;
+ char *pRes; /* result pointer */
+ char *pBufStart;
+ char *pBuf;
+ int iLen;
+
+#ifdef FEATURE_REGEXP
+ /* Variables necessary for regular expression matching */
+ size_t nmatch = 2;
+ regmatch_t pmatch[2];
+#endif
+
+ assert(pMsg != NULL);
+ assert(pbMustBeFreed != NULL);
+
+ if(pCSPropName == NULL) {
+ assert(pTpe != NULL);
+ pName = pTpe->data.field.pPropRepl;
+ } else {
+ pName = (char*) rsCStrGetSzStr(pCSPropName);
+ }
+ *pbMustBeFreed = 0;
+
+ /* sometimes there are aliases to the original MonitoWare
+ * property names. These come after || in the ifs below. */
+ if(!strcmp(pName, "msg")) {
+ pRes = getMSG(pMsg);
+ } else if(!strcmp(pName, "rawmsg")) {
+ pRes = getRawMsg(pMsg);
+ } else if(!strcmp(pName, "UxTradMsg")) {
+ pRes = getUxTradMsg(pMsg);
+ } else if(!strcmp(pName, "FROMHOST")) {
+ pRes = getRcvFrom(pMsg);
+ } else if(!strcmp(pName, "source")
+ || !strcmp(pName, "HOSTNAME")) {
+ pRes = getHOSTNAME(pMsg);
+ } else if(!strcmp(pName, "syslogtag")) {
+ pRes = getTAG(pMsg);
+ } else if(!strcmp(pName, "PRI")) {
+ pRes = getPRI(pMsg);
+ } else if(!strcmp(pName, "PRI-text")) {
+ pBuf = malloc(20 * sizeof(char));
+ if(pBuf == NULL) {
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ } else {
+ *pbMustBeFreed = 1;
+ pRes = textpri(pBuf, 20, getPRIi(pMsg));
+ }
+ } else if(!strcmp(pName, "iut")) {
+ pRes = "1"; /* always 1 for syslog messages (a MonitorWare thing;)) */
+ } else if(!strcmp(pName, "syslogfacility")) {
+ pRes = getFacility(pMsg);
+ } else if(!strcmp(pName, "syslogfacility-text")) {
+ pRes = getFacilityStr(pMsg);
+ } else if(!strcmp(pName, "syslogseverity") || !strcmp(pName, "syslogpriority")) {
+ pRes = getSeverity(pMsg);
+ } else if(!strcmp(pName, "syslogseverity-text") || !strcmp(pName, "syslogpriority-text")) {
+ pRes = getSeverityStr(pMsg);
+ } else if(!strcmp(pName, "timegenerated")) {
+ pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat);
+ } else if(!strcmp(pName, "timereported")
+ || !strcmp(pName, "TIMESTAMP")) {
+ pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat);
+ } else if(!strcmp(pName, "programname")) {
+ pRes = getProgramName(pMsg);
+ } else if(!strcmp(pName, "PROTOCOL-VERSION")) {
+ pRes = getProtocolVersionString(pMsg);
+ } else if(!strcmp(pName, "STRUCTURED-DATA")) {
+ pRes = getStructuredData(pMsg);
+ } else if(!strcmp(pName, "APP-NAME")) {
+ pRes = getAPPNAME(pMsg);
+ } else if(!strcmp(pName, "PROCID")) {
+ pRes = getPROCID(pMsg);
+ } else if(!strcmp(pName, "MSGID")) {
+ pRes = getMSGID(pMsg);
+ /* here start system properties (those, that do not relate to the message itself */
+ } else if(!strcmp(pName, "$NOW")) {
+ if((pRes = (char*) getNOW(NOW_NOW)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else if(!strcmp(pName, "$YEAR")) {
+ if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else if(!strcmp(pName, "$MONTH")) {
+ if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else if(!strcmp(pName, "$DAY")) {
+ if((pRes = (char*) getNOW(NOW_DAY)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else if(!strcmp(pName, "$HOUR")) {
+ if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else if(!strcmp(pName, "$MINUTE")) {
+ if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) {
+ return "***OUT OF MEMORY***";
+ } else
+ *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
+ } else {
+ /* there is no point in continuing, we may even otherwise render the
+ * error message unreadable. rgerhards, 2007-07-10
+ */
+ return "**INVALID PROPERTY NAME**";
+ }
+
+ /* If we did not receive a template pointer, we are already done... */
+ if(pTpe == NULL) {
+ return pRes;
+ }
+
+ /* Now check if we need to make "temporary" transformations (these
+ * are transformations that do not go back into the message -
+ * memory must be allocated for them!).
+ */
+
+ /* substring extraction */
+ /* first we check if we need to extract by field number
+ * rgerhards, 2005-12-22
+ */
+ if(pTpe->data.field.has_fields == 1) {
+ size_t iCurrFld;
+ char *pFld;
+ char *pFldEnd;
+ /* first, skip to the field in question. The field separator
+ * is always one character and is stored in the template entry.
+ */
+ iCurrFld = 1;
+ pFld = pRes;
+ while(*pFld && iCurrFld < pTpe->data.field.iToPos) {
+ /* skip fields until the requested field or end of string is found */
+ while(*pFld && (uchar) *pFld != pTpe->data.field.field_delim)
+ ++pFld; /* skip to field terminator */
+ if(*pFld == pTpe->data.field.field_delim) {
+ ++pFld; /* eat it */
+ ++iCurrFld;
+ }
+ }
+ dbgprintf("field requested %d, field found %d\n", pTpe->data.field.iToPos, iCurrFld);
+
+ if(iCurrFld == pTpe->data.field.iToPos) {
+ /* field found, now extract it */
+ /* first of all, we need to find the end */
+ pFldEnd = pFld;
+ while(*pFldEnd && *pFldEnd != pTpe->data.field.field_delim)
+ ++pFldEnd;
+ --pFldEnd; /* we are already at the delimiter - so we need to
+ * step back a little not to copy it as part of the field. */
+ /* we got our end pointer, now do the copy */
+ /* TODO: code copied from below, this is a candidate for a separate function */
+ iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */
+ pBufStart = pBuf = malloc((iLen + 1) * sizeof(char));
+ if(pBuf == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ /* now copy */
+ memcpy(pBuf, pFld, iLen);
+ pBuf[iLen] = '\0'; /* terminate it */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBufStart;
+ *pbMustBeFreed = 1;
+ if(*(pFldEnd+1) != '\0')
+ ++pFldEnd; /* OK, skip again over delimiter char */
+ } else {
+ /* field not found, return error */
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**FIELD NOT FOUND**";
+ }
+ } else if(pTpe->data.field.iFromPos != 0 || pTpe->data.field.iToPos != 0) {
+ /* we need to obtain a private copy */
+ int iFrom, iTo;
+ iFrom = pTpe->data.field.iFromPos;
+ iTo = pTpe->data.field.iToPos;
+ /* need to zero-base to and from (they are 1-based!) */
+ if(iFrom > 0)
+ --iFrom;
+ if(iTo > 0)
+ --iTo;
+ iLen = iTo - iFrom + 1; /* the +1 is for an actual char, NOT \0! */
+ pBufStart = pBuf = malloc((iLen + 1) * sizeof(char));
+ if(pBuf == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ if(iFrom) {
+ /* skip to the start of the substring (can't do pointer arithmetic
+ * because the whole string might be smaller!!)
+ */
+ while(*pRes && iFrom) {
+ --iFrom;
+ ++pRes;
+ }
+ }
+ /* OK, we are at the begin - now let's copy... */
+ while(*pRes && iLen) {
+ *pBuf++ = *pRes;
+ ++pRes;
+ --iLen;
+ }
+ *pBuf = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBufStart;
+ *pbMustBeFreed = 1;
+#ifdef FEATURE_REGEXP
+ } else {
+ /* Check for regular expressions */
+ if (pTpe->data.field.has_regex != 0) {
+ if (pTpe->data.field.has_regex == 2)
+ /* Could not compile regex before! */
+ return
+ "**NO MATCH** **BAD REGULAR EXPRESSION**";
+
+ dbgprintf("debug: String to match for regex is: %s\n",
+ pRes);
+
+ if (0 != regexec(&pTpe->data.field.re, pRes, nmatch,
+ pmatch, 0)) {
+ /* we got no match! */
+ return "**NO MATCH**";
+ } else {
+ /* Match! */
+ /* I need to malloc pB */
+ int iLenBuf;
+ char *pB;
+
+ iLenBuf = pmatch[1].rm_eo - pmatch[1].rm_so;
+ pB = (char *) malloc((iLenBuf + 1) * sizeof(char));
+
+ if (pB == NULL) {
+ if (*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY ALLOCATING pBuf**";
+ }
+
+ /* Lets copy the matched substring to the buffer */
+ memcpy(pB, pRes + pmatch[1].rm_so, iLenBuf);
+ pB[iLenBuf] = '\0';/* terminate string, did not happen before */
+
+ if (*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pB;
+ *pbMustBeFreed = 1;
+ }
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+
+ /* case conversations (should go after substring, because so we are able to
+ * work on the smallest possible buffer).
+ */
+ if(pTpe->data.field.eCaseConv != tplCaseConvNo) {
+ /* we need to obtain a private copy */
+ int iBufLen = strlen(pRes);
+ char *pBStart;
+ char *pB;
+ pBStart = pB = malloc((iBufLen + 1) * sizeof(char));
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ while(*pRes) {
+ *pB++ = (pTpe->data.field.eCaseConv == tplCaseConvUpper) ?
+ toupper(*pRes) : tolower(*pRes);
+ /* currently only these two exist */
+ ++pRes;
+ }
+ *pB = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBStart;
+ *pbMustBeFreed = 1;
+ }
+
+ /* now do control character dropping/escaping/replacement
+ * Only one of these can be used. If multiple options are given, the
+ * result is random (though currently there obviously is an order of
+ * preferrence, see code below. But this is NOT guaranteed.
+ * RGerhards, 2006-11-17
+ */
+ if(pTpe->data.field.options.bDropCC) {
+ char *pSrc = pRes;
+ char *pDst = pRes;
+
+ while(*pSrc) {
+ if(!iscntrl((int) *pSrc))
+ *pDst++ = *pSrc;
+ ++pSrc;
+ }
+ *pDst = '\0';
+ } else if(pTpe->data.field.options.bSpaceCC) {
+ char *pB = pRes;
+ while(*pB) {
+ if(iscntrl((int) *pB))
+ *pB = ' ';
+ ++pB;
+ }
+ } else if(pTpe->data.field.options.bEscapeCC) {
+ /* we must first count how many control charactes are
+ * present, because we need this to compute the new string
+ * buffer length. While doing so, we also compute the string
+ * length.
+ */
+ int iNumCC = 0;
+ int iLenBuf = 0;
+ char *pB;
+
+ for(pB = pRes ; *pB ; ++pB) {
+ ++iLenBuf;
+ if(iscntrl((int) *pB))
+ ++iNumCC;
+ }
+
+ if(iNumCC > 0) { /* if 0, there is nothing to escape, so we are done */
+ /* OK, let's do the escaping... */
+ char *pBStart;
+ char szCCEsc[8]; /* buffer for escape sequence */
+ int i;
+
+ iLenBuf += iNumCC * 4;
+ pBStart = pB = malloc((iLenBuf + 1) * sizeof(char));
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ while(*pRes) {
+ if(iscntrl((int) *pRes)) {
+ snprintf(szCCEsc, sizeof(szCCEsc), "#%3.3d", *pRes);
+ for(i = 0 ; i < 4 ; ++i)
+ *pB++ = szCCEsc[i];
+ } else {
+ *pB++ = *pRes;
+ }
+ ++pRes;
+ }
+ *pB = '\0';
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ pRes = pBStart;
+ *pbMustBeFreed = 1;
+ }
+ }
+
+ /* Now drop last LF if present (pls note that this must not be done
+ * if bEscapeCC was set!
+ */
+ if(pTpe->data.field.options.bDropLastLF && !pTpe->data.field.options.bEscapeCC) {
+ int iLn = strlen(pRes);
+ char *pB;
+ if(*(pRes + iLn - 1) == '\n') {
+ /* we have a LF! */
+ /* check if we need to obtain a private copy */
+ if(pbMustBeFreed == 0) {
+ /* ok, original copy, need a private one */
+ pB = malloc((iLn + 1) * sizeof(char));
+ if(pB == NULL) {
+ if(*pbMustBeFreed == 1)
+ free(pRes);
+ *pbMustBeFreed = 0;
+ return "**OUT OF MEMORY**";
+ }
+ memcpy(pB, pRes, iLn - 1);
+ pRes = pB;
+ *pbMustBeFreed = 1;
+ }
+ *(pRes + iLn - 1) = '\0'; /* drop LF ;) */
+ }
+ }
+
+ /*dbgprintf("MsgGetProp(\"%s\"): \"%s\"\n", pName, pRes); only for verbose debug logging */
+ return(pRes);
+}
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/msg.h b/msg.h
new file mode 100644
index 0000000..794fb95
--- /dev/null
+++ b/msg.h
@@ -0,0 +1,156 @@
+/* msg.h
+ * Header file for all msg-related functions.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef MSG_H_INCLUDED
+#define MSG_H_INCLUDED 1
+
+#include "syslogd-types.h"
+#include "template.h"
+
+/* rgerhards 2004-11-08: The following structure represents a
+ * syslog message.
+ *
+ * Important Note:
+ * The message object is used for multiple purposes (once it
+ * has been created). Once created, it actully is a read-only
+ * object (though we do not specifically express this). In order
+ * to avoid multiple copies of the same object, we use a
+ * reference counter. This counter is set to 1 by the constructer
+ * and increased by 1 with a call to MsgAddRef(). The destructor
+ * checks the reference count. If it is more than 1, only the counter
+ * will be decremented. If it is 1, however, the object is actually
+ * destroyed. To make this work, it is vital that MsgAddRef() is
+ * called each time a "copy" is stored somewhere.
+ */
+struct msg {
+ int iRefCount; /* reference counter (0 = unused) */
+ short iSyslogVers; /* version of syslog protocol
+ * 0 - RFC 3164
+ * 1 - RFC draft-protocol-08 */
+ short bParseHOSTNAME; /* should the hostname be parsed from the message? */
+ /* background: the hostname is not present on "regular" messages
+ * received via UNIX domain sockets from the same machine. However,
+ * it is available when we have a forwarder (e.g. rfc3195d) using local
+ * sockets. All in all, the parser would need parse templates, that would
+ * resolve all these issues... rgerhards, 2005-10-06
+ */
+ short iSeverity; /* the severity 0..7 */
+ uchar *pszSeverity; /* severity as string... */
+ int iLenSeverity; /* ... and its length. */
+ uchar *pszSeverityStr; /* severity name... */
+ int iLenSeverityStr; /* ... and its length. */
+ int iFacility; /* Facility code (up to 2^32-1) */
+ uchar *pszFacility; /* Facility as string... */
+ int iLenFacility; /* ... and its length. */
+ uchar *pszFacilityStr; /* facility name... */
+ int iLenFacilityStr; /* ... and its length. */
+ uchar *pszPRI; /* the PRI as a string */
+ int iLenPRI; /* and its length */
+ uchar *pszRawMsg; /* message as it was received on the
+ * wire. This is important in case we
+ * need to preserve cryptographic verifiers.
+ */
+ int iLenRawMsg; /* length of raw message */
+ uchar *pszMSG; /* the MSG part itself */
+ int iLenMSG; /* Length of the MSG part */
+ uchar *pszUxTradMsg; /* the traditional UNIX message */
+ int iLenUxTradMsg;/* Length of the traditional UNIX message */
+ uchar *pszTAG; /* pointer to tag value */
+ int iLenTAG; /* Length of the TAG part */
+ uchar *pszHOSTNAME; /* HOSTNAME from syslog message */
+ int iLenHOSTNAME; /* Length of HOSTNAME */
+ uchar *pszRcvFrom; /* System message was received from */
+ int iLenRcvFrom; /* Length of pszRcvFrom */
+ int iProtocolVersion;/* protocol version of message received 0 - legacy, 1 syslog-protocol) */
+ rsCStrObj *pCSProgName; /* the (BSD) program name */
+ rsCStrObj *pCSStrucData;/* STRUCTURED-DATA */
+ rsCStrObj *pCSAPPNAME; /* APP-NAME */
+ rsCStrObj *pCSPROCID; /* PROCID */
+ rsCStrObj *pCSMSGID; /* MSGID */
+ struct syslogTime tRcvdAt;/* time the message entered this program */
+ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 charcters) */
+ char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 charcters at most) */
+ char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 charcters) */
+ struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */
+ char *pszTIMESTAMP3164; /* TIMESTAMP as RFC3164 formatted string (always 15 charcters) */
+ char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 charcters at most) */
+ char *pszTIMESTAMP_MySQL;/* TIMESTAMP as MySQL formatted string (always 14 charcters) */
+ int msgFlags; /* flags associated with this message */
+};
+typedef struct msg msg_t; /* new name */
+
+/* function prototypes
+ */
+char* getProgramName(msg_t*);
+msg_t* MsgConstruct(void);
+void MsgDestruct(msg_t * pM);
+msg_t* MsgDup(msg_t* pOld);
+msg_t *MsgAddRef(msg_t *pM);
+void setProtocolVersion(msg_t *pM, int iNewVersion);
+int getProtocolVersion(msg_t *pM);
+char *getProtocolVersionString(msg_t *pM);
+int getMSGLen(msg_t *pM);
+char *getRawMsg(msg_t *pM);
+char *getUxTradMsg(msg_t *pM);
+char *getMSG(msg_t *pM);
+char *getPRI(msg_t *pM);
+int getPRIi(msg_t *pM);
+char *getTimeReported(msg_t *pM, enum tplFormatTypes eFmt);
+char *getTimeGenerated(msg_t *pM, enum tplFormatTypes eFmt);
+char *getSeverity(msg_t *pM);
+char *getSeverityStr(msg_t *pM);
+char *getFacility(msg_t *pM);
+char *getFacilityStr(msg_t *pM);
+rsRetVal MsgSetAPPNAME(msg_t *pMsg, char* pszAPPNAME);
+int getAPPNAMELen(msg_t *pM);
+char *getAPPNAME(msg_t *pM);
+rsRetVal MsgSetPROCID(msg_t *pMsg, char* pszPROCID);
+int getPROCIDLen(msg_t *pM);
+char *getPROCID(msg_t *pM);
+rsRetVal MsgSetMSGID(msg_t *pMsg, char* pszMSGID);
+void MsgAssignTAG(msg_t *pMsg, char *pBuf);
+void MsgSetTAG(msg_t *pMsg, char* pszTAG);
+char *getTAG(msg_t *pM);
+int getHOSTNAMELen(msg_t *pM);
+char *getHOSTNAME(msg_t *pM);
+char *getRcvFrom(msg_t *pM);
+rsRetVal MsgSetStructuredData(msg_t *pMsg, char* pszStrucData);
+char *getStructuredData(msg_t *pM);
+int getProgramNameLen(msg_t *pM);
+char *getProgramName(msg_t *pM);
+void MsgSetRcvFrom(msg_t *pMsg, char* pszRcvFrom);
+void MsgAssignHOSTNAME(msg_t *pMsg, char *pBuf);
+void MsgSetHOSTNAME(msg_t *pMsg, char* pszHOSTNAME);
+int MsgSetUxTradMsg(msg_t *pMsg, char* pszUxTradMsg);
+void MsgSetMSG(msg_t *pMsg, char* pszMSG);
+void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg);
+void moveHOSTNAMEtoTAG(msg_t *pM);
+char *getMSGID(msg_t *pM);
+char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
+ rsCStrObj *pCSPropName, unsigned short *pbMustBeFreed);
+char *textpri(char *pRes, size_t pResLen, int pri);
+
+#endif /* #ifndef MSG_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/net.c b/net.c
new file mode 100644
index 0000000..bf0e468
--- /dev/null
+++ b/net.c
@@ -0,0 +1,242 @@
+/* net.c
+ * Implementation of network-related stuff.
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#ifdef SYSLOG_INET
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <ctype.h>
+#include <netdb.h>
+
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "net.h"
+
+/* The following #ifdef sequence is a small compatibility
+ * layer. It tries to work around the different availality
+ * levels of SO_BSDCOMPAT on linuxes...
+ * I borrowed this code from
+ * http://www.erlang.org/ml-archive/erlang-questions/200307/msg00037.html
+ * It still needs to be a bit better adapted to rsyslog.
+ * rgerhards 2005-09-19
+ */
+#ifndef BSD
+#include <sys/utsname.h>
+int should_use_so_bsdcompat(void)
+{
+ static int init_done;
+ static int so_bsdcompat_is_obsolete;
+
+ if (!init_done) {
+ struct utsname utsname;
+ unsigned int version, patchlevel;
+
+ init_done = 1;
+ if (uname(&utsname) < 0) {
+ dbgprintf("uname: %s\r\n", strerror(errno));
+ return 1;
+ }
+ /* Format is <version>.<patchlevel>.<sublevel><extraversion>
+ where the first three are unsigned integers and the last
+ is an arbitrary string. We only care about the first two. */
+ if (sscanf(utsname.release, "%u.%u", &version, &patchlevel) != 2) {
+ dbgprintf("uname: unexpected release '%s'\r\n",
+ utsname.release);
+ return 1;
+ }
+ /* SO_BSCOMPAT is deprecated and triggers warnings in 2.5
+ kernels. It is a no-op in 2.4 but not in 2.2 kernels. */
+ if (version > 2 || (version == 2 && patchlevel >= 5))
+ so_bsdcompat_is_obsolete = 1;
+ }
+ return !so_bsdcompat_is_obsolete;
+}
+#else /* #ifndef BSD */
+#define should_use_so_bsdcompat() 1
+#endif /* #ifndef BSD */
+#ifndef SO_BSDCOMPAT
+/* this shall prevent compiler errors due to undfined name */
+#define SO_BSDCOMPAT 0
+#endif
+
+
+/* Return a printable representation of a host address.
+ * Now (2007-07-16) also returns the full host name (if it could be obtained)
+ * in the second param [thanks to mildew@gmail.com for the patch].
+ * The caller must provide buffer space for pszHost and pszHostFQDN. These
+ * buffers must be of size NI_MAXHOST. This is not checked here, because
+ * there is no way to check it. We use this way of doing things because it
+ * frees us from using dynamic memory allocation where it really does not
+ * pay.
+ * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats)
+ * for some explanation of the code found below. We do by default not
+ * discard message where we detected malicouos DNS PTR records. However,
+ * there is a user-configurabel option that will tell us if
+ * we should abort. For this, the return value tells the caller if the
+ * message should be processed (1) or discarded (0).
+ */
+int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN)
+{
+ register uchar *p;
+ int count, error;
+ sigset_t omask, nmask;
+ char ip[NI_MAXHOST];
+ struct addrinfo hints, *res;
+
+ assert(f != NULL);
+ assert(pszHost != NULL);
+ assert(pszHostFQDN != NULL);
+
+ error = getnameinfo((struct sockaddr *)f, SALEN((struct sockaddr *)f),
+ ip, sizeof ip, NULL, 0, NI_NUMERICHOST);
+
+ if (error) {
+ dbgprintf("Malformed from address %s\n", gai_strerror(error));
+ strcpy((char*) pszHost, "???");
+ strcpy((char*) pszHostFQDN, "???");
+ return 1;
+ }
+
+ if (!DisableDNS) {
+ sigemptyset(&nmask);
+ sigaddset(&nmask, SIGHUP);
+ sigprocmask(SIG_BLOCK, &nmask, &omask);
+
+ error = getnameinfo((struct sockaddr *)f, sizeof(*f),
+ (char*)pszHostFQDN, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+
+ if (error == 0) {
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ /* we now do a lookup once again. This one should fail,
+ * because we should not have obtained a numeric address. If
+ * we got a numeric one, someone messed with DNS!
+ */
+ if (getaddrinfo ((char*)pszHostFQDN, NULL, &hints, &res) == 0) {
+ uchar szErrMsg[1024];
+ freeaddrinfo (res);
+ /* OK, we know we have evil. The question now is what to do about
+ * it. One the one hand, the message might probably be intended
+ * to harm us. On the other hand, losing the message may also harm us.
+ * Thus, the behaviour is controlled by the $DropMsgsWithMaliciousDnsPTRRecords
+ * option. If it tells us we should discard, we do so, else we proceed,
+ * but log an error message together with it.
+ * time being, we simply drop the name we obtained and use the IP - that one
+ * is OK in any way. We do also log the error message. rgerhards, 2007-07-16
+ */
+ if(bDropMalPTRMsgs == 1) {
+ snprintf((char*)szErrMsg, sizeof(szErrMsg) / sizeof(uchar),
+ "Malicious PTR record, message dropped "
+ "IP = \"%s\" HOST = \"%s\"",
+ ip, pszHostFQDN);
+ logerror((char*)szErrMsg);
+ return 0;
+ }
+
+ /* Please note: we deal with a malicous entry. Thus, we have crafted
+ * the snprintf() below so that all text is in front of the entry - maybe
+ * it would contain characters that would make the message unreadble
+ * (OK, I admit this is more or less impossible, but I am paranoid...)
+ * rgerhards, 2007-07-16
+ */
+ snprintf((char*)szErrMsg, sizeof(szErrMsg) / sizeof(uchar),
+ "Malicious PTR record (message accepted, but used IP "
+ "instead of PTR name: IP = \"%s\" HOST = \"%s\"",
+ ip, pszHostFQDN);
+ logerror((char*)szErrMsg);
+
+ error = 1; /* that will trigger using IP address below. */
+ }
+ }
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+ }
+
+ if (error || DisableDNS) {
+ dbgprintf("Host name for your address (%s) unknown\n", ip);
+ strcpy((char*) pszHostFQDN, ip);
+ strcpy((char*) pszHost, ip);
+ return 1;
+ }
+
+ /* Convert to lower case, just like LocalDomain above
+ */
+ for (p = pszHostFQDN ; *p ; p++)
+ if (isupper((int) *p))
+ *p = tolower(*p);
+
+ /* OK, the fqdn is now known. Now it is time to extract only the hostname
+ * part if we were instructed to do so.
+ */
+ /* TODO: quick and dirty right now: we need to optimize that. We simply
+ * copy over the buffer and then use the old code.
+ */
+ strcpy((char*)pszHost, (char*)pszHostFQDN);
+ if ((p = (uchar*) strchr((char*)pszHost, '.'))) {
+ if(strcmp((char*) (p + 1), LocalDomain) == 0) {
+ *p = '\0'; /* simply terminate the string */
+ return 1;
+ } else {
+ if (StripDomains) {
+ count=0;
+ while (StripDomains[count]) {
+ if (strcmp((char*)(p + 1), StripDomains[count]) == 0) {
+ *p = '\0';
+ return 1;
+ }
+ count++;
+ }
+ }
+ /* TODO: bug in syslogd? That all doesn't make so much sense... rger 2007-07-16 */
+ if (LocalHosts) {
+ count=0;
+ while (LocalHosts[count]) {
+ if (!strcmp((char*)pszHost, LocalHosts[count])) {
+ *p = '\0';
+ return 1;
+ }
+ count++;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+#endif /* #ifdef SYSLOG_INET */
+/*
+ * vi:set ai:
+ */
diff --git a/net.h b/net.h
new file mode 100644
index 0000000..5f6705d
--- /dev/null
+++ b/net.h
@@ -0,0 +1,75 @@
+/* Definitions for network-related stuff.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#ifndef INCLUDED_NET_H
+#define INCLUDED_NET_H
+
+#ifdef SYSLOG_INET
+#include <netinet/in.h>
+
+#define F_SET(where, flag) (where)|=(flag)
+#define F_ISSET(where, flag) ((where)&(flag))==(flag)
+#define F_UNSET(where, flag) (where)&=~(flag)
+
+#define ADDR_NAME 0x01 /* address is hostname wildcard) */
+#define ADDR_PRI6 0x02 /* use IPv6 address prior to IPv4 when resolving */
+
+#ifdef BSD
+#ifndef _KERNEL
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+#endif
+
+struct NetAddr {
+ uint8_t flags;
+ union {
+ struct sockaddr *NetAddr;
+ char *HostWildcard;
+ } addr;
+};
+
+#ifndef BSD
+ int should_use_so_bsdcompat(void);
+#else
+# define should_use_so_bsdcompat() 1
+#endif /* #ifndef BSD */
+
+#ifndef SO_BSDCOMPAT
+ /* this shall prevent compiler errors due to undfined name */
+# define SO_BSDCOMPAT 0
+#endif
+
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define SALEN(sa) ((sa)->sa_len)
+#else
+static inline size_t SALEN(struct sockaddr *sa) {
+ switch (sa->sa_family) {
+ case AF_INET: return (sizeof (struct sockaddr_in));
+ case AF_INET6: return (sizeof (struct sockaddr_in6));
+ default: return 0;
+ }
+}
+#endif
+
+int cvthname(struct sockaddr_storage *f, uchar *pszHost, uchar *pszHostFQDN);
+
+#endif /* #ifdef SYSLOG_INET */
+#endif /* #ifndef INCLUDED_NET_H */
diff --git a/objomsr.c b/objomsr.c
new file mode 100644
index 0000000..979f9d3
--- /dev/null
+++ b/objomsr.c
@@ -0,0 +1,144 @@
+/* objomsr.c
+ * Implementation of the omsr (omodStringRequest) object.
+ *
+ * File begun on 2007-07-27 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "rsyslog.h"
+#include "objomsr.h"
+
+
+/* destructor
+ */
+rsRetVal OMSRdestruct(omodStringRequest_t *pThis)
+{
+ int i;
+
+ assert(pThis != NULL);
+ /* free the strings */
+ if(pThis->ppTplName != NULL) {
+ for(i = 0 ; i < pThis->iNumEntries ; ++i) {
+ if(pThis->ppTplName[i] != NULL) {
+ free(pThis->ppTplName[i]);
+ }
+ }
+ free(pThis->ppTplName);
+ }
+ if(pThis->piTplOpts != NULL)
+ free(pThis->piTplOpts);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* constructor
+ */
+rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries)
+{
+ omodStringRequest_t *pThis;
+ DEFiRet;
+
+ assert(ppThis != NULL);
+ assert(iNumEntries >= 0);
+ if((pThis = calloc(1, sizeof(omodStringRequest_t))) == NULL) {
+ iRet = RS_RET_OUT_OF_MEMORY;
+ goto abort_it;
+ }
+
+ /* got the structure, so fill it */
+ pThis->iNumEntries = iNumEntries;
+ /* allocate string for template name array. The individual strings will be
+ * allocated as the code progresses (we do not yet know the string sizes)
+ */
+ if((pThis->ppTplName = calloc(iNumEntries, sizeof(uchar*))) == NULL) {
+ OMSRdestruct(pThis);
+ pThis = NULL;
+ iRet = RS_RET_OUT_OF_MEMORY;
+ goto abort_it;
+ }
+ /* allocate the template options array. */
+ if((pThis->piTplOpts = calloc(iNumEntries, sizeof(int))) == NULL) {
+ OMSRdestruct(pThis);
+ pThis = NULL;
+ iRet = RS_RET_OUT_OF_MEMORY;
+ goto abort_it;
+ }
+
+abort_it:
+ *ppThis = pThis;
+ return iRet;
+}
+
+/* set a template name and option to the object. Index must be given. The pTplName must be
+ * pointing to memory that can be freed. If in doubt, the caller must strdup() the value.
+ */
+rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts)
+{
+ assert(pThis != NULL);
+ assert(pTplName != NULL);
+ assert(iEntry < pThis->iNumEntries);
+
+ if(pThis->ppTplName[iEntry] != NULL)
+ free(pThis->ppTplName[iEntry]);
+ pThis->ppTplName[iEntry] = pTplName;
+ pThis->piTplOpts[iEntry] = iTplOpts;
+
+ return RS_RET_OK;
+}
+
+
+/* get number of entries for this object
+ */
+int OMSRgetEntryCount(omodStringRequest_t *pThis)
+{
+ assert(pThis != NULL);
+ return pThis->iNumEntries;
+}
+
+
+/* return data for a specific entry. All data returned is
+ * read-only and lasts only as long as the object lives. If the caller
+ * needs it for an extended period of time, the caller must copy the
+ * strings. Please note that the string pointer may be NULL, which is the
+ * case when it was never set.
+ */
+int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts)
+{
+ assert(pThis != NULL);
+ assert(ppTplName != NULL);
+ assert(piTplOpts != NULL);
+ assert(iEntry < pThis->iNumEntries);
+
+ *ppTplName = pThis->ppTplName[iEntry];
+ *piTplOpts = pThis->piTplOpts[iEntry];
+
+ return RS_RET_OK;
+}
+/*
+ * vi:set ai:
+ */
diff --git a/objomsr.h b/objomsr.h
new file mode 100644
index 0000000..f6eae47
--- /dev/null
+++ b/objomsr.h
@@ -0,0 +1,44 @@
+/* Definition of the omsr (omodStringRequest) object.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+
+#ifndef OBJOMSR_H_INCLUDED
+#define OBJOMSR_H_INCLUDED
+
+/* define flags for required template options */
+#define OMSR_NO_RQD_TPL_OPTS 0
+#define OMSR_RQD_TPL_OPT_SQL 1
+/* next option is 2, 4, 8, ... */
+
+struct omodStringRequest_s { /* strings requested by output module for doAction() */
+ int iNumEntries; /* number of array entries for data elements below */
+ uchar **ppTplName; /* pointer to array of template names */
+ int *piTplOpts;/* pointer to array of check-options when pulling template */
+};
+typedef struct omodStringRequest_s omodStringRequest_t;
+
+/* prototypes */
+rsRetVal OMSRdestruct(omodStringRequest_t *pThis);
+rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries);
+rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts);
+int OMSRgetEntryCount(omodStringRequest_t *pThis);
+int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts);
+
+#endif /* #ifndef OBJOMSR_H_INCLUDED */
diff --git a/omdiscard.c b/omdiscard.c
new file mode 100644
index 0000000..d335003
--- /dev/null
+++ b/omdiscard.c
@@ -0,0 +1,127 @@
+/* omdiscard.c
+ * This is the implementation of the built-in discard output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-24 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "omdiscard.h"
+#include "module-template.h"
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+} instanceData;
+
+/* we do not need a createInstance()!
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+*/
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* do nothing */
+ENDdbgPrintInstInfo
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ /* we are not compatible with repeated msg reduction feature, so do not allow it */
+ENDisCompatibleWithFeature
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ iRet = RS_RET_DISCARDMSG;
+ENDdoAction
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* we do not have instance data, so we do not need to
+ * do anything here. -- rgerhards, 2007-07-25
+ */
+ENDfreeInstance
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(0)
+ pData = NULL; /* this action does not have any instance data */
+ p = *pp;
+
+ if(*p == '~') {
+ /* TODO: check the rest of the selector line - error reporting */
+ dbgprintf("discard\n");
+ } else {
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ }
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ENDneedUDPSocket
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ENDonSelectReadyWrite
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ENDgetWriteFDForSelect
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Discard)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+/*
+ * vi:set ai:
+ */
diff --git a/omdiscard.h b/omdiscard.h
new file mode 100644
index 0000000..113845f
--- /dev/null
+++ b/omdiscard.h
@@ -0,0 +1,33 @@
+/* omdiscard.h
+ * These are the definitions for the built-in discard output module.
+ *
+ * File begun on 2007-07-24 by RGerhards
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef OMDISCARD_H_INCLUDED
+#define OMDISCARD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitDiscard(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+
+#endif /* #ifndef OMDISCARD_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/omfile.c b/omfile.c
new file mode 100644
index 0000000..af59402
--- /dev/null
+++ b/omfile.c
@@ -0,0 +1,803 @@
+/* omfile.c
+ * This is the implementation of the build-in file output module.
+ *
+ * Handles: eTypeCONSOLE, eTypeTTY, eTypeFILE, eTypePIPE
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/file.h>
+
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "outchannel.h"
+#include "omfile.h"
+#include "cfsysline.h"
+#include "module-template.h"
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+/* The following structure is a dynafile name cache entry.
+ */
+struct s_dynaFileCacheEntry {
+ uchar *pName; /* name currently open, if dynamic name */
+ short fd; /* name associated with file name in cache */
+ time_t lastUsed; /* for LRU - last access */
+};
+typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
+
+
+/* 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 = 0644; /* mode to use when creating files */
+static int bFailOnChown; /* fail if chown fails? */
+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 */
+static uid_t dirGID; /* GID to be used for newly created directories */
+static int bCreateDirs; /* auto-create directories for dynaFiles: 0 - no, 1 - yes */
+/* end globals for default values */
+
+typedef struct _instanceData {
+ char f_fname[MAXFNAME];/* file or template name (display only) */
+ short fd; /* file descriptor for (current) file */
+ enum {
+ eTypeFILE,
+ eTypeTTY,
+ eTypeCONSOLE,
+ eTypePIPE
+ } fileType;
+ struct template *pTpl; /* pointer to template object */
+ char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */
+ int fCreateMode; /* file creation mode for open() */
+ int fDirCreateMode; /* creation mode for mkdir() */
+ int bCreateDirs; /* auto-create directories? */
+ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */
+ uid_t fileUID; /* IDs for creation */
+ uid_t dirUID;
+ gid_t fileGID;
+ gid_t dirGID;
+ int bFailOnChown; /* fail creation if chown fails? */
+ int iCurrElt; /* currently active cache element (-1 = none) */
+ int iCurrCacheSize; /* currently cache size (1-based) */
+ int iDynaFileCacheSize; /* size of file handle cache */
+ /* The cache is implemented as an array. An empty element is indicated
+ * by a NULL pointer. Memory is allocated as needed. The following
+ * pointer points to the overall structure.
+ */
+ dynaFileCacheEntry **dynCache;
+ off_t f_sizeLimit; /* file size limit, 0 = no limit */
+ char *f_sizeLimitCmd; /* command to carry out when size limit is reached */
+} instanceData;
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ if(pData->bDynamicName) {
+ printf("[dynamic]\n\ttemplate='%s'"
+ "\tfile cache size=%d\n"
+ "\tcreate directories: %s\n"
+ "\tfile owner %d, group %d\n"
+ "\tdirectory owner %d, group %d\n"
+ "\tfail if owner/group can not be set: %s\n",
+ pData->f_fname,
+ pData->iDynaFileCacheSize,
+ pData->bCreateDirs ? "yes" : "no",
+ pData->fileUID, pData->fileGID,
+ pData->dirUID, pData->dirGID,
+ pData->bFailOnChown ? "yes" : "no"
+ );
+ } else { /* regular file */
+ printf("%s", pData->f_fname);
+ if (pData->fd == -1)
+ printf(" (unused)");
+ }
+ENDdbgPrintInstInfo
+
+
+/* set the dynaFile cache size. Does some limit checking.
+ * rgerhards, 2007-07-31
+ */
+rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ DEFiRet;
+ uchar errMsg[128]; /* for dynamic error messages */
+
+ if(iNewVal < 1) {
+ snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
+ "DynaFileCacheSize must be greater 0 (%d given), changed to 1.", iNewVal);
+ errno = 0;
+ logerror((char*) errMsg);
+ iRet = RS_RET_VAL_OUT_OF_RANGE;
+ iNewVal = 1;
+ } else if(iNewVal > 10000) {
+ snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
+ "DynaFileCacheSize maximum is 10,000 (%d given), changed to 10,000.", iNewVal);
+ errno = 0;
+ logerror((char*) errMsg);
+ iRet = RS_RET_VAL_OUT_OF_RANGE;
+ iNewVal = 10000;
+ }
+
+ iDynaFileCacheSize = iNewVal;
+ dbgprintf("DynaFileCacheSize changed to %d.\n", iNewVal);
+
+ return iRet;
+}
+
+
+/* Helper to cfline(). Parses a output channel name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template. Maps the output channel to the
+ * proper filed structure settings. Everything is stored in the
+ * filed struct. Over time, the dependency on filed might be
+ * removed.
+ * rgerhards 2005-06-21
+ */
+static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts)
+{
+ DEFiRet;
+ size_t i;
+ struct outchannel *pOch;
+ char szBuf[128]; /* should be more than sufficient */
+
+ /* this must always be a file, because we can not set a size limit
+ * on a pipe...
+ * rgerhards 2005-06-21: later, this will be a separate type, but let's
+ * emulate things for the time being. When everything runs, we can
+ * extend it...
+ */
+ pData->fileType = eTypeFILE;
+
+ ++p; /* skip '$' */
+ i = 0;
+ /* get outchannel name */
+ while(*p && *p != ';' && *p != ' ' &&
+ i < sizeof(szBuf) / sizeof(char)) {
+ szBuf[i++] = *p++;
+ }
+ szBuf[i] = '\0';
+
+ /* got the name, now look up the channel... */
+ pOch = ochFind(szBuf, i);
+
+ if(pOch == NULL) {
+ char errMsg[128];
+ errno = 0;
+ snprintf(errMsg, sizeof(errMsg)/sizeof(char),
+ "outchannel '%s' not found - ignoring action line",
+ szBuf);
+ logerror(errMsg);
+ return RS_RET_NOT_FOUND;
+ }
+
+ /* check if there is a file name in the outchannel... */
+ if(pOch->pszFileTemplate == NULL) {
+ char errMsg[128];
+ errno = 0;
+ snprintf(errMsg, sizeof(errMsg)/sizeof(char),
+ "outchannel '%s' has no file name template - ignoring action line",
+ szBuf);
+ logerror(errMsg);
+ return RS_RET_ERR;
+ }
+
+ /* OK, we finally got a correct template. So let's use it... */
+ strncpy(pData->f_fname, pOch->pszFileTemplate, MAXFNAME);
+ pData->f_sizeLimit = pOch->uSizeLimit;
+ /* WARNING: It is dangerous "just" to pass the pointer. As we
+ * never rebuild the output channel description, this is acceptable here.
+ */
+ pData->f_sizeLimitCmd = pOch->cmdOnSizeLimit;
+
+ iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, (uchar*) " TradFmt");
+
+ return(iRet);
+}
+
+
+/* rgerhards 2005-06-21: Try to resolve a size limit
+ * situation. This first runs the command, and then
+ * checks if we are still above the treshold.
+ * returns 0 if ok, 1 otherwise
+ * TODO: consider moving the initial check in here, too
+ */
+int resolveFileSizeLimit(instanceData *pData)
+{
+ uchar *pParams;
+ uchar *pCmd;
+ uchar *p;
+ off_t actualFileSize;
+ assert(pData != NULL);
+
+ if(pData->f_sizeLimitCmd == NULL)
+ return 1; /* nothing we can do in this case... */
+
+ /* the execProg() below is probably not great, but at least is is
+ * fairly secure now. Once we change the way file size limits are
+ * handled, we should also revisit how this command is run (and
+ * with which parameters). rgerhards, 2007-07-20
+ */
+ /* we first check if we have command line parameters. We assume this,
+ * when we have a space in the program name. If we find it, everything after
+ * the space is treated as a single argument.
+ */
+ if((pCmd = (uchar*)strdup((char*)pData->f_sizeLimitCmd)) == NULL) {
+ /* there is not much we can do - we make syslogd close the file in this case */
+ glblHadMemShortage = 1;
+ return 1;
+ }
+
+ for(p = pCmd ; *p && *p != ' ' ; ++p) {
+ /* JUST SKIP */
+ }
+
+ if(*p == ' ') {
+ *p = '\0'; /* pretend string-end */
+ pParams = p+1;
+ } else
+ pParams = NULL;
+
+ execProg(pCmd, 1, pParams);
+
+ pData->fd = open(pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fCreateMode);
+
+ actualFileSize = lseek(pData->fd, 0, SEEK_END);
+ if(actualFileSize >= pData->f_sizeLimit) {
+ /* OK, it didn't work out... */
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* This function deletes an entry from the dynamic file name
+ * cache. A pointer to the cache must be passed in as well
+ * as the index of the to-be-deleted entry. This index may
+ * point to an unallocated entry, in whcih case the
+ * function immediately returns. Parameter bFreeEntry is 1
+ * if the entry should be free()ed and 0 if not.
+ */
+static void dynaFileDelCacheEntry(dynaFileCacheEntry **pCache, int iEntry, int bFreeEntry)
+{
+ assert(pCache != NULL);
+
+ if(pCache[iEntry] == NULL)
+ return;
+
+ dbgprintf("Removed entry %d for file '%s' from dynaCache.\n", iEntry,
+ pCache[iEntry]->pName == NULL ? "[OPEN FAILED]" : (char*)pCache[iEntry]->pName);
+ /* if the name is NULL, this is an improperly initilized entry which
+ * needs to be discarded. In this case, neither the file is to be closed
+ * not the name to be freed.
+ */
+ if(pCache[iEntry]->pName != NULL) {
+ close(pCache[iEntry]->fd);
+ free(pCache[iEntry]->pName);
+ pCache[iEntry]->pName = NULL;
+ }
+
+ if(bFreeEntry) {
+ free(pCache[iEntry]);
+ pCache[iEntry] = NULL;
+ }
+}
+
+
+/* This function frees the dynamic file name cache.
+ */
+static void dynaFileFreeCache(instanceData *pData)
+{
+ register int i;
+ assert(pData != NULL);
+
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ dynaFileDelCacheEntry(pData->dynCache, i, 1);
+ }
+
+ free(pData->dynCache);
+}
+
+
+/* This function handles dynamic file names. It checks if the
+ * requested file name is already open and, if not, does everything
+ * needed to switch to the it.
+ * Function returns 0 if all went well and non-zero otherwise.
+ * On successful return pData->fd must point to the correct file to
+ * be written.
+ * This is a helper to writeFile(). rgerhards, 2007-07-03
+ */
+static int prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts)
+{
+ time_t ttOldest; /* timestamp of oldest element */
+ int iOldest;
+ int i;
+ int iFirstFree;
+ dynaFileCacheEntry **pCache;
+
+ assert(pData != NULL);
+ assert(newFileName != NULL);
+
+ pCache = pData->dynCache;
+
+ /* first check, if we still have the current file
+ * I *hope* this will be a performance enhancement.
+ */
+ if( (pData->iCurrElt != -1)
+ && !strcmp((char*) newFileName, (char*) pCache[pData->iCurrElt])) {
+ /* great, we are all set */
+ pCache[pData->iCurrElt]->lastUsed = time(NULL); /* update timestamp for LRU */
+ return 0;
+ }
+
+ /* ok, no luck. Now let's search the table if we find a matching spot.
+ * While doing so, we also prepare for creation of a new one.
+ */
+ iFirstFree = -1; /* not yet found */
+ iOldest = 0; /* we assume the first element to be the oldest - that will change as we loop */
+ ttOldest = time(NULL) + 1; /* there must always be an older one */
+ for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
+ if(pCache[i] == NULL) {
+ if(iFirstFree == -1)
+ iFirstFree = i;
+ } else { /* got an element, let's see if it matches */
+ if(!strcmp((char*) newFileName, (char*) pCache[i]->pName)) {
+ /* we found our element! */
+ pData->fd = pCache[i]->fd;
+ pData->iCurrElt = i;
+ pCache[i]->lastUsed = time(NULL); /* update timestamp for LRU */
+ return 0;
+ }
+ /* did not find it - so lets keep track of the counters for LRU */
+ if(pCache[i]->lastUsed < ttOldest) {
+ ttOldest = pCache[i]->lastUsed;
+ iOldest = i;
+ }
+ }
+ }
+
+ /* we have not found an entry */
+ if(iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) {
+ /* there is space left, so set it to that index */
+ iFirstFree = pData->iCurrCacheSize++;
+ }
+
+ if(iFirstFree == -1) {
+ dynaFileDelCacheEntry(pCache, iOldest, 0);
+ iFirstFree = iOldest; /* this one *is* now free ;) */
+ } else {
+ /* we need to allocate memory for the cache structure */
+ pCache[iFirstFree] = (dynaFileCacheEntry*) calloc(1, sizeof(dynaFileCacheEntry));
+ if(pCache[iFirstFree] == NULL) {
+ glblHadMemShortage = TRUE;
+ dbgprintf("prepareDynfile(): could not alloc mem, discarding this request\n");
+ return -1;
+ }
+ }
+
+ /* Ok, we finally can open the file */
+ if(access((char*)newFileName, F_OK) == 0) {
+ /* file already exists */
+ pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fCreateMode);
+ } else {
+ /* file does not exist, create it (and eventually parent directories */
+ if(pData->bCreateDirs) {
+ /* we fist need to create parent dirs if they are missing
+ * We do not report any errors here ourselfs but let the code
+ * fall through to error handler below.
+ */
+ if(makeFileParentDirs(newFileName, strlen((char*)newFileName),
+ pData->fDirCreateMode, pData->dirUID,
+ pData->dirGID, pData->bFailOnChown) == 0) {
+ pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fCreateMode);
+ if(pData->fd != -1) {
+ /* check and set uid/gid */
+ if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
+ /* we need to set owner/group */
+ if(fchown(pData->fd, pData->fileUID,
+ pData->fileGID) != 0) {
+ if(pData->bFailOnChown) {
+ int eSave = errno;
+ close(pData->fd);
+ pData->fd = -1;
+ errno = eSave;
+ }
+ /* we will silently ignore the chown() failure
+ * if configured to do so.
+ */
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* file is either open now or an error state set */
+ if(pData->fd == -1) {
+ /* do not report anything if the message is an internally-generated
+ * message. Otherwise, we could run into a never-ending loop. The bad
+ * news is that we also lose errors on startup messages, but so it is.
+ */
+ if(iMsgOpts & INTERNAL_MSG)
+ dbgprintf("Could not open dynaFile, discarding message\n");
+ else
+ logerrorSz("Could not open dynamic file '%s' - discarding message", (char*)newFileName);
+ dynaFileDelCacheEntry(pCache, iFirstFree, 1);
+ return -1;
+ }
+
+ pCache[iFirstFree]->fd = pData->fd;
+ pCache[iFirstFree]->pName = (uchar*)strdup((char*)newFileName); /* TODO: check for NULL (very unlikely) */
+ pCache[iFirstFree]->lastUsed = time(NULL);
+ pData->iCurrElt = iFirstFree;
+ dbgprintf("Added new entry %d for file cache, file '%s'.\n",
+ iFirstFree, newFileName);
+
+ return 0;
+}
+
+
+/* rgerhards 2004-11-11: write to a file output. This
+ * will be called for all outputs using file semantics,
+ * for example also for pipes.
+ */
+static rsRetVal writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData)
+{
+ off_t actualFileSize;
+ DEFiRet;
+
+ assert(pData != NULL);
+
+ /* first check if we have a dynamic file name and, if so,
+ * check if it still is ok or a new file needs to be created
+ */
+ if(pData->bDynamicName) {
+ if(prepareDynFile(pData, ppString[1], iMsgOpts) != 0)
+ return RS_RET_ERR;
+ }
+
+ /* create the message based on format specified */
+again:
+ /* check if we have a file size limit and, if so,
+ * obey to it.
+ */
+ if(pData->f_sizeLimit != 0) {
+ actualFileSize = lseek(pData->fd, 0, SEEK_END);
+ if(actualFileSize >= pData->f_sizeLimit) {
+ char errMsg[256];
+ /* for now, we simply disable a file once it is
+ * beyond the maximum size. This is better than having
+ * us aborted by the OS... rgerhards 2005-06-21
+ */
+ (void) close(pData->fd);
+ /* try to resolve the situation */
+ if(resolveFileSizeLimit(pData) != 0) {
+ /* didn't work out, so disable... */
+ snprintf(errMsg, sizeof(errMsg),
+ "no longer writing to file %s; grown beyond configured file size of %lld bytes, actual size %lld - configured command did not resolve situation",
+ pData->f_fname, (long long) pData->f_sizeLimit, (long long) actualFileSize);
+ errno = 0;
+ logerror(errMsg);
+ return RS_RET_DISABLE_ACTION;
+ } else {
+ snprintf(errMsg, sizeof(errMsg),
+ "file %s had grown beyond configured file size of %lld bytes, actual size was %lld - configured command resolved situation",
+ pData->f_fname, (long long) pData->f_sizeLimit, (long long) actualFileSize);
+ errno = 0;
+ logerror(errMsg);
+ }
+ }
+ }
+
+ if (write(pData->fd, ppString[0], strlen((char*)ppString[0])) < 0) {
+ int e = errno;
+
+ /* If a named pipe is full, just ignore it for now
+ - mrn 24 May 96 */
+ if (pData->fileType == eTypePIPE && e == EAGAIN)
+ return RS_RET_OK;
+
+ /* If the filesystem is filled up, just ignore
+ * it for now and continue writing when possible
+ * based on patch for sysklogd by Martin Schulze on 2007-05-24
+ */
+ if (pData->fileType == eTypeFILE && e == ENOSPC)
+ return RS_RET_OK;
+
+ (void) close(pData->fd);
+ /*
+ * Check for EBADF on TTY's due to vhangup()
+ * Linux uses EIO instead (mrn 12 May 96)
+ */
+ if ((pData->fileType == eTypeTTY || pData->fileType == eTypeCONSOLE)
+#ifdef linux
+ && e == EIO) {
+#else
+ && e == EBADF) {
+#endif
+ pData->fd = open(pData->f_fname, O_WRONLY|O_APPEND|O_NOCTTY);
+ if (pData->fd < 0) {
+ iRet = RS_RET_DISABLE_ACTION;
+ logerror(pData->f_fname);
+ } else {
+ untty();
+ goto again;
+ }
+ } else {
+ iRet = RS_RET_DISABLE_ACTION;
+ errno = e;
+ logerror(pData->f_fname);
+ }
+ } else if (pData->bSyncFile)
+ fsync(pData->fd);
+ return(iRet);
+}
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ if(pData->bDynamicName) {
+ dynaFileFreeCache(pData);
+ } else
+ close(pData->fd);
+ENDfreeInstance
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ENDonSelectReadyWrite
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ENDneedUDPSocket
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ENDgetWriteFDForSelect
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf(" (%s)\n", pData->f_fname);
+ /* pData->fd == -1 is an indicator that the we couldn't
+ * open the file at startup. For dynaFiles, this is ok,
+ * all others are doomed.
+ */
+ if(pData->bDynamicName || (pData->fd != -1))
+ iRet = writeFile(ppString, iMsgOpts, pData);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+ /* yes, the if below is redundant, but I need it now. Will go away as
+ * the code further changes. -- rgerhards, 2007-07-25
+ */
+ if(*p == '$' || *p == '?' || *p == '|' || *p == '/' || *p == '-') {
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ return iRet;
+ } else {
+ /* this is not clean, but we need it for the time being
+ * TODO: remove when cleaning up modularization
+ */
+ return RS_RET_CONFLINE_UNPROCESSED;
+ }
+
+ if (*p == '-') {
+ pData->bSyncFile = 0;
+ p++;
+ } else
+ pData->bSyncFile = 1;
+
+ pData->f_sizeLimit = 0; /* default value, use outchannels to configure! */
+
+ switch (*p)
+ {
+ case '$':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* rgerhards 2005-06-21: this is a special setting for output-channel
+ * definitions. In the long term, this setting will probably replace
+ * anything else, but for the time being we must co-exist with the
+ * traditional mode lines.
+ * rgerhards, 2007-07-24: output-channels will go away. We keep them
+ * for compatibility reasons, but seems to have been a bad idea.
+ */
+ if((iRet = cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS)) == RS_RET_OK) {
+ pData->bDynamicName = 0;
+ pData->fCreateMode = fCreateMode; /* preserve current setting */
+ pData->fDirCreateMode = fDirCreateMode; /* preserve current setting */
+ pData->fd = open(pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fCreateMode);
+ }
+ break;
+
+ case '?': /* This is much like a regular file handle, but we need to obtain
+ * a template name. rgerhards, 2007-07-03
+ */
+ CODE_STD_STRING_REQUESTparseSelectorAct(2)
+ ++p; /* eat '?' */
+ if((iRet = cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS))
+ != RS_RET_OK)
+ break;
+ /* "filename" is actually a template name, we need this as string 1. So let's add it
+ * to the pOMSR. -- rgerhards, 2007-07-27
+ */
+ if((iRet = OMSRsetEntry(*ppOMSR, 1, (uchar*)strdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS)) != RS_RET_OK)
+ break;
+
+ pData->bDynamicName = 1;
+ pData->iCurrElt = -1; /* no current element */
+ pData->fCreateMode = fCreateMode; /* freeze current setting */
+ pData->fDirCreateMode = fDirCreateMode; /* preserve current setting */
+ pData->bCreateDirs = bCreateDirs;
+ pData->bFailOnChown = bFailOnChown;
+ pData->fileUID = fileUID;
+ pData->fileGID = fileGID;
+ pData->dirUID = dirUID;
+ pData->dirGID = dirGID;
+ pData->iDynaFileCacheSize = iDynaFileCacheSize; /* freeze current setting */
+ /* we now allocate the cache table. We use calloc() intentionally, as we
+ * need all pointers to be initialized to NULL pointers.
+ */
+ if((pData->dynCache = (dynaFileCacheEntry**)
+ calloc(iDynaFileCacheSize, sizeof(dynaFileCacheEntry*))) == NULL) {
+ iRet = RS_RET_OUT_OF_MEMORY;
+ dbgprintf("Could not allocate memory for dynaFileCache - selector disabled.\n");
+ }
+ break;
+
+ case '|':
+ case '/':
+ CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* rgerhards, 2007-0726: first check if file or pipe */
+ if(*p == '|') {
+ pData->fileType = eTypePIPE;
+ ++p;
+ } else {
+ pData->fileType = eTypeFILE;
+ }
+ /* rgerhards 2004-11-17: from now, we need to have different
+ * processing, because after the first comma, the template name
+ * to use is specified. So we need to scan for the first coma first
+ * and then look at the rest of the line.
+ */
+ if((iRet = cflineParseFileName(p, (uchar*) pData->f_fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS))
+ != RS_RET_OK)
+ break;
+
+ pData->bDynamicName = 0;
+ pData->fCreateMode = fCreateMode; /* preserve current setting */
+ if(pData->fileType == eTypePIPE) {
+ pData->fd = open(pData->f_fname, O_RDWR|O_NONBLOCK);
+ } else {
+ pData->fd = open(pData->f_fname, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY,
+ pData->fCreateMode);
+ }
+
+ if ( pData->fd < 0 ){
+ pData->fd = -1;
+ dbgprintf("Error opening log file: %s\n", pData->f_fname);
+ logerror(pData->f_fname);
+ break;
+ }
+ if (isatty(pData->fd)) {
+ pData->fileType = eTypeTTY;
+ untty();
+ }
+ if (strcmp((char*) p, ctty) == 0)
+ pData->fileType = eTypeCONSOLE;
+ break;
+ default:
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ break;
+ }
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+/* Reset config variables for this module to default values.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ fileUID = -1;
+ fileGID = -1;
+ dirUID = -1;
+ dirGID = -1;
+ bFailOnChown = 1;
+ iDynaFileCacheSize = 10;
+ fCreateMode = 0644;
+ fDirCreateMode = 0644;
+ bCreateDirs = 1;
+
+ return RS_RET_OK;
+}
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(File)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, (void*) setDynaFileCacheSize, NULL));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &dirUID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &dirGID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &fileUID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &fileGID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fDirCreateMode));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL));
+ENDmodInit
+
+/*
+ * vi:set ai:
+ */
diff --git a/omfile.h b/omfile.h
new file mode 100644
index 0000000..5352704
--- /dev/null
+++ b/omfile.h
@@ -0,0 +1,34 @@
+/* omfile.h
+ * These are the definitions for the build-in file output module.
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef OMFILE_H_INCLUDED
+#define OMFILE_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitFile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+rsRetVal setDynaFileCacheSize(void __attribute__((unused)) *pVal, int iNewVal); // TODO: remove me after testing!
+
+#endif /* #ifndef OMFILE_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/omfwd.c b/omfwd.c
new file mode 100644
index 0000000..096d5d7
--- /dev/null
+++ b/omfwd.c
@@ -0,0 +1,925 @@
+/* omfwd.c
+ * This is the implementation of the build-in forwarding output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#ifdef SYSLOG_INET
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#ifdef USE_PTHREADS
+#include <pthread.h>
+#else
+#include <fcntl.h>
+#endif
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "net.h"
+#include "omfwd.h"
+#include "template.h"
+#include "msg.h"
+#include "tcpsyslog.h"
+#include "module-template.h"
+
+#ifdef SYSLOG_INET
+//#define INET_SUSPEND_TIME 60 /* equal to 1 minute
+#define INET_SUSPEND_TIME 2 /* equal to 1 minute
+ * rgerhards, 2005-07-26: This was 3 minutes. As the
+ * same timer is used for tcp based syslog, we have
+ * reduced it. However, it might actually be worth
+ * thinking about a buffered tcp sender, which would be
+ * a much better alternative. When that happens, this
+ * time here can be re-adjusted to 3 minutes (or,
+ * even better, made configurable).
+ */
+#define INET_RETRY_MAX 30 /* maximum of retries for gethostbyname() */
+ /* was 10, changed to 30 because we reduced INET_SUSPEND_TIME by one third. So
+ * this "fixes" some of implications of it (see comment on INET_SUSPEND_TIME).
+ * rgerhards, 2005-07-26
+ */
+#endif
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ char f_hname[MAXHOSTNAMELEN+1];
+ short sock; /* file descriptor */
+ enum { /* TODO: we shoud revisit these definitions */
+ eDestFORW,
+ eDestFORW_SUSP,
+ eDestFORW_UNKN
+ } eDestState;
+ int iRtryCnt;
+ struct addrinfo *f_addr;
+ int compressionLevel; /* 0 - no compression, else level for zlib */
+ char *port;
+ int protocol;
+ TCPFRAMINGMODE tcp_framing;
+# define FORW_UDP 0
+# define FORW_TCP 1
+ /* following fields for TCP-based delivery */
+ enum TCPSendStatus {
+ TCP_SEND_NOTCONNECTED = 0,
+ TCP_SEND_CONNECTING = 1,
+ TCP_SEND_READY = 2
+ } status;
+ char *savedMsg;
+ int savedMsgLen; /* length of savedMsg in octets */
+ time_t ttSuspend; /* time selector was suspended */
+# ifdef USE_PTHREADS
+ pthread_mutex_t mtxTCPSend;
+# endif
+} instanceData;
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ switch (pData->eDestState) {
+ case eDestFORW:
+ case eDestFORW_SUSP:
+ freeaddrinfo(pData->f_addr);
+ /* fall through */
+ case eDestFORW_UNKN:
+ if(pData->port != NULL)
+ free(pData->port);
+ break;
+ }
+# ifdef USE_PTHREADS
+ /* delete any mutex objects, if present */
+ if(pData->protocol == FORW_TCP) {
+ pthread_mutex_destroy(&pData->mtxTCPSend);
+ }
+# endif
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("%s", pData->f_hname);
+ENDdbgPrintInstInfo
+
+/* CODE FOR SENDING TCP MESSAGES */
+
+/* get send status
+ * rgerhards, 2005-10-24
+ */
+static void TCPSendSetStatus(instanceData *pData, enum TCPSendStatus iNewState)
+{
+ assert(pData != NULL);
+ assert(pData->protocol == FORW_TCP);
+ assert( (iNewState == TCP_SEND_NOTCONNECTED)
+ || (iNewState == TCP_SEND_CONNECTING)
+ || (iNewState == TCP_SEND_READY));
+
+ /* there can potentially be a race condition, so guard by mutex */
+# ifdef USE_PTHREADS
+ pthread_mutex_lock(&pData->mtxTCPSend);
+# endif
+ pData->status = iNewState;
+# ifdef USE_PTHREADS
+ pthread_mutex_unlock(&pData->mtxTCPSend);
+# endif
+}
+
+
+/* set send status
+ * rgerhards, 2005-10-24
+ */
+static enum TCPSendStatus TCPSendGetStatus(instanceData *pData)
+{
+ enum TCPSendStatus eState;
+ assert(pData != NULL);
+ assert(pData->protocol == FORW_TCP);
+
+ /* there can potentially be a race condition, so guard by mutex */
+# ifdef USE_PTHREADS
+ pthread_mutex_lock(&pData->mtxTCPSend);
+# endif
+ eState = pData->status;
+# ifdef USE_PTHREADS
+ pthread_mutex_unlock(&pData->mtxTCPSend);
+# endif
+
+ return eState;
+}
+
+
+/* Initialize TCP sockets (for sender)
+ * This is done once per selector line, if not yet initialized.
+ */
+static int TCPSendCreateSocket(instanceData *pData, struct addrinfo *addrDest)
+{
+ int fd;
+ struct addrinfo *r;
+
+ assert(pData != NULL);
+
+ r = addrDest;
+
+ while(r != NULL) {
+ fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if (fd != -1) {
+ /* We can not allow the TCP sender to block syslogd, at least
+ * not in a single-threaded design. That would cause rsyslogd to
+ * loose input messages - which obviously also would affect
+ * other selector lines, too. So we do set it to non-blocking and
+ * handle the situation ourselfs (by discarding messages). IF we run
+ * dual-threaded, however, the situation is different: in this case,
+ * the receivers and the selector line processing are only loosely
+ * coupled via a memory buffer. Now, I think, we can afford the extra
+ * wait time. Thus, we enable blocking mode for TCP if we compile with
+ * pthreads.
+ * rgerhards, 2005-10-25
+ */
+# ifndef USE_PTHREADS
+ /* set to nonblocking - rgerhards 2005-07-20 */
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+# endif
+ if (connect (fd, r->ai_addr, r->ai_addrlen) != 0) {
+ if(errno == EINPROGRESS) {
+ /* this is normal - will complete during select */
+ TCPSendSetStatus(pData, TCP_SEND_CONNECTING);
+ return fd;
+ } else {
+ dbgprintf("create tcp connection failed, reason %s",
+ strerror(errno));
+ }
+
+ }
+ else {
+ TCPSendSetStatus(pData, TCP_SEND_READY);
+ return fd;
+ }
+ close(fd);
+ }
+ else {
+ dbgprintf("couldn't create send socket, reason %s", strerror(errno));
+ }
+ r = r->ai_next;
+ }
+
+ dbgprintf("no working socket could be obtained");
+
+ return -1;
+}
+
+/* Sends a TCP message. It is first checked if the
+ * session is open and, if not, it is opened. Then the send
+ * is tried. If it fails, one silent re-try is made. If the send
+ * fails again, an error status (-1) is returned. If all goes well,
+ * 0 is returned. The TCP session is NOT torn down.
+ * For now, EAGAIN is ignored (causing message loss) - but it is
+ * hard to do something intelligent in this case. With this
+ * implementation here, we can not block and/or defer. Things are
+ * probably a bit better when we move to liblogging. The alternative
+ * would be to enhance the current select server with buffering and
+ * write descriptors. This seems not justified, given the expected
+ * short life span of this code (and the unlikeliness of this event).
+ * rgerhards 2005-07-06
+ * This function is now expected to stay. Libloging won't be used for
+ * that purpose. I have added the param "len", because it is known by the
+ * caller and so safes us some time. Also, it MUST be given because there
+ * may be NULs inside msg so that we can not rely on strlen(). Please note
+ * that the restrictions outlined above do not existin in multi-threaded
+ * mode, which we assume will now be most often used. So there is no
+ * real issue with the potential message loss in single-threaded builds.
+ * rgerhards, 2006-11-30
+ *
+ * In order to support compressed messages via TCP, we must support an
+ * octet-counting based framing (LF may be part of the compressed message).
+ * We are now supporting the same mode that is available in IETF I-D
+ * syslog-transport-tls-05 (current at the time of this writing). This also
+ * eases things when we go ahead and implement that framing. I have now made
+ * available two cases where this framing is used: either by explitely
+ * specifying it in the config file or implicitely when sending a compressed
+ * message. In the later case, compressed and uncompressed messages within
+ * the same session have different framings. If it is explicitely set to
+ * octet-counting, only this framing mode is used within the session.
+ * rgerhards, 2006-12-07
+ */
+static int TCPSend(instanceData *pData, char *msg, size_t len)
+{
+ int retry = 0;
+ int done = 0;
+ int bIsCompressed;
+ int lenSend;
+ char *buf = NULL; /* if this is non-NULL, it MUST be freed before return! */
+ enum TCPSendStatus eState;
+ TCPFRAMINGMODE framingToUse;
+
+ assert(pData != NULL);
+ assert(msg != NULL);
+ assert(len > 0);
+
+ bIsCompressed = *msg == 'z'; /* cache this, so that we can modify the message buffer */
+ /* select framing for this record. If we have a compressed record, we always need to
+ * use octet counting because the data potentially contains all control characters
+ * including LF.
+ */
+ framingToUse = bIsCompressed ? TCP_FRAMING_OCTET_COUNTING : pData->tcp_framing;
+
+ do { /* try to send message */
+ if(pData->sock <= 0) {
+ /* we need to open the socket first */
+ if((pData->sock = TCPSendCreateSocket(pData, pData->f_addr)) <= 0) {
+ return -1;
+ }
+ }
+
+ eState = TCPSendGetStatus(pData); /* cache info */
+
+ if(eState == TCP_SEND_CONNECTING) {
+ /* In this case, we save the buffer. If we have a
+ * system with few messages, that hopefully prevents
+ * message loss at all. However, we make no further attempts,
+ * just the first message is saved. So we only try this
+ * if there is not yet a saved message present.
+ * rgerhards 2005-07-20
+ */
+ if(pData->savedMsg == NULL) {
+ pData->savedMsg = malloc(len * sizeof(char));
+ if(pData->savedMsg == NULL)
+ return 0; /* nothing we can do... */
+ memcpy(pData->savedMsg, msg, len);
+ pData->savedMsgLen = len;
+ }
+ return 0;
+ } else if(eState != TCP_SEND_READY)
+ /* This here is debatable. For the time being, we
+ * accept the loss of a single message (e.g. during
+ * connection setup in favour of not messing with
+ * wait time and timeouts. The reason is that such
+ * things might otherwise cost us considerable message
+ * loss on the receiving side (even at a timeout set
+ * to just 1 second). - rgerhards 2005-07-20
+ */
+ return 0;
+
+ /* now check if we need to add a line terminator. We need to
+ * copy the string in memory in this case, this is probably
+ * quicker than using writev and definitely quicker than doing
+ * two socket calls.
+ * rgerhards 2005-07-22
+ *//*
+ * Some messages already contain a \n character at the end
+ * of the message. We append one only if we there is not
+ * already one. This seems the best fit, though this also
+ * means the message does not arrive unaltered at the final
+ * destination. But in the spirit of legacy syslog, this is
+ * probably the best to do...
+ * rgerhards 2005-07-20
+ */
+
+ /* Build frame based on selected framing */
+ if(framingToUse == TCP_FRAMING_OCTET_STUFFING) {
+ if((*(msg+len-1) != '\n')) {
+ if(buf != NULL)
+ free(buf);
+ /* in the malloc below, we need to add 2 to the length. The
+ * reason is that we a) add one character and b) len does
+ * not take care of the '\0' byte. Up until today, it was just
+ * +1 , which caused rsyslogd to sometimes dump core.
+ * I have added this comment so that the logic is not accidently
+ * changed again. rgerhards, 2005-10-25
+ */
+ if((buf = malloc((len + 2) * sizeof(char))) == NULL) {
+ /* extreme mem shortage, try to solve
+ * as good as we can. No point in calling
+ * any alarms, they might as well run out
+ * of memory (the risk is very high, so we
+ * do NOT risk that). If we have a message of
+ * more than 1 byte (what I guess), we simply
+ * overwrite the last character.
+ * rgerhards 2005-07-22
+ */
+ if(len > 1) {
+ *(msg+len-1) = '\n';
+ } else {
+ /* we simply can not do anything in
+ * this case (its an error anyhow...).
+ */
+ }
+ } else {
+ /* we got memory, so we can copy the message */
+ memcpy(buf, msg, len); /* do not copy '\0' */
+ *(buf+len) = '\n';
+ *(buf+len+1) = '\0';
+ msg = buf; /* use new one */
+ ++len; /* care for the \n */
+ }
+ }
+ } else {
+ /* Octect-Counting
+ * In this case, we need to always allocate a buffer. This is because
+ * we need to put a header in front of the message text
+ */
+ char szLenBuf[16];
+ int iLenBuf;
+
+ /* important: the printf-mask is "%d<sp>" because there must be a
+ * space after the len!
+ *//* The chairs of the IETF syslog-sec WG have announced that it is
+ * consensus to do the octet count on the SYSLOG-MSG part only. I am
+ * now changing the code to reflect this. Hopefully, it will not change
+ * once again (there can no compatibility layer programmed for this).
+ * To be on the save side, I just comment the code out. I mark these
+ * comments with "IETF20061218".
+ * rgerhards, 2006-12-19
+ */
+ iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", (int) len);
+ /* IETF20061218 iLenBuf =
+ snprintf(szLenBuf, sizeof(szLenBuf)/sizeof(char), "%d ", len + iLenBuf);*/
+
+ if((buf = malloc((len + iLenBuf) * sizeof(char))) == NULL) {
+ /* we are out of memory. This is an extreme situation. We do not
+ * call any alarm handlers because they most likely run out of mem,
+ * too. We are brave enough to call debug output, though. Other than
+ * that, there is nothing left to do. We can not sent the message (as
+ * in case of the other framing, because the message is incomplete.
+ * We could, however, send two chunks (header and text separate), but
+ * that would cause a lot of complexity in the code. So we think it
+ * is appropriate enough to just make sure we do not crash in this
+ * very unlikely case. For this, it is justified just to loose
+ * the message. Rgerhards, 2006-12-07
+ */
+ dbgprintf("Error: out of memory when building TCP octet-counted "
+ "frame. Message is lost, trying to continue.\n");
+ return 0;
+ }
+
+ memcpy(buf, szLenBuf, iLenBuf); /* header */
+ memcpy(buf + iLenBuf, msg, len); /* message */
+ len += iLenBuf; /* new message size */
+ msg = buf; /* set message buffer */
+ }
+
+ /* frame building complete, on to actual sending */
+
+ lenSend = send(pData->sock, msg, len, 0);
+ dbgprintf("TCP sent %d bytes, requested %d, msg: '%s'\n", lenSend, len,
+ bIsCompressed ? "***compressed***" : msg);
+ if((unsigned)lenSend == len) {
+ /* all well */
+ if(buf != NULL) {
+ free(buf);
+ }
+ return 0;
+ } else if(lenSend != -1) {
+ /* no real error, could "just" not send everything...
+ * For the time being, we ignore this...
+ * rgerhards, 2005-10-25
+ */
+ dbgprintf("message not completely (tcp)send, ignoring %d\n", lenSend);
+# if USE_PTHREADS
+ usleep(1000); /* experimental - might be benefitial in this situation */
+# endif
+ if(buf != NULL)
+ free(buf);
+ return 0;
+ }
+
+ switch(errno) {
+ case EMSGSIZE:
+ dbgprintf("message not (tcp)send, too large\n");
+ /* This is not a real error, so it is not flagged as one */
+ if(buf != NULL)
+ free(buf);
+ return 0;
+ break;
+ case EINPROGRESS:
+ case EAGAIN:
+ dbgprintf("message not (tcp)send, would block\n");
+# if USE_PTHREADS
+ usleep(1000); /* experimental - might be benefitial in this situation */
+# endif
+ /* we loose this message, but that's better than loosing
+ * all ;)
+ */
+ /* This is not a real error, so it is not flagged as one */
+ if(buf != NULL)
+ free(buf);
+ return 0;
+ break;
+ default:
+ dbgprintf("message not (tcp)send");
+ break;
+ }
+
+ if(retry == 0) {
+ ++retry;
+ /* try to recover */
+ close(pData->sock);
+ TCPSendSetStatus(pData, TCP_SEND_NOTCONNECTED);
+ pData->sock = -1;
+ } else {
+ if(buf != NULL)
+ free(buf);
+ return -1;
+ }
+ } while(!done); /* warning: do ... while() */
+ /*NOT REACHED*/
+
+ if(buf != NULL)
+ free(buf);
+ return -1; /* only to avoid compiler warning! */
+}
+
+
+/* get the syslog forward port from selector_t. The passed in
+ * struct must be one that is setup for forwarding.
+ * rgerhards, 2007-06-28
+ * We may change the implementation to try to lookup the port
+ * if it is unspecified. So far, we use the IANA default auf 514.
+ */
+static char *getFwdSyslogPt(instanceData *pData)
+{
+ assert(pData != NULL);
+ if(pData->port == NULL)
+ return("514");
+ else
+ return(pData->port);
+}
+
+
+/* try to resume connection if it is not ready
+ * rgerhards, 2007-08-02
+ */
+static rsRetVal doTryResume(instanceData *pData)
+{
+ DEFiRet;
+ struct addrinfo *res;
+ struct addrinfo hints;
+ unsigned e;
+
+ switch (pData->eDestState) {
+ case eDestFORW_SUSP:
+ iRet = RS_RET_OK; /* the actual check happens during doAction() only */
+ pData->eDestState = eDestFORW;
+ break;
+
+ case eDestFORW_UNKN:
+ /* The remote address is not yet known and needs to be obtained */
+ dbgprintf(" %s\n", pData->f_hname);
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requests this */
+ /* TODO: this code is a duplicate from cfline() - we should later create
+ * a common function.
+ */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = family;
+ hints.ai_socktype = pData->protocol == FORW_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ if((e = getaddrinfo(pData->f_hname,
+ getFwdSyslogPt(pData), &hints, &res)) == 0) {
+ dbgprintf("%s found, resuming.\n", pData->f_hname);
+ pData->f_addr = res;
+ pData->iRtryCnt = 0;
+ pData->eDestState = eDestFORW;
+ } else {
+ iRet = RS_RET_SUSPENDED;
+ }
+ break;
+ }
+
+ return iRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ iRet = doTryResume(pData);
+ENDtryResume
+
+BEGINdoAction
+ char *psz; /* temporary buffering */
+ register unsigned l;
+ struct addrinfo *r;
+ int i;
+ unsigned lsent = 0;
+ int bSendSuccess;
+CODESTARTdoAction
+ switch (pData->eDestState) {
+ case eDestFORW_SUSP:
+ dbgprintf("internal error in omfwd.c, eDestFORW_SUSP in doAction()!\n");
+ iRet = RS_RET_SUSPENDED;
+ break;
+
+ case eDestFORW_UNKN:
+ dbgprintf("doAction eDestFORW_UNKN\n");
+ iRet = doTryResume(pData);
+ break;
+
+ case eDestFORW:
+ dbgprintf(" %s:%s/%s\n", pData->f_hname, getFwdSyslogPt(pData),
+ pData->protocol == FORW_UDP ? "udp" : "tcp");
+ if ( 0) // TODO: think about this strcmp(getHOSTNAME(f->f_pMsg), LocalHostName) && NoHops )
+ /* what we need to do is get the hostname as an additonal string (during parseSe..). Then,
+ * we can compare that string to LocalHostName. That way, we do not need to access the
+ * msgobject, and everything is clean. The question remains, though, if that functionality
+ * here actually makes sense or not. If we really need it, it might make more sense to compare
+ * the target IP address to the IP addresses of the local machene - that is a far better way of
+ * handling things than to relay on the error-prone hostname property.
+ * rgerhards, 2007-07-27
+ */
+ dbgprintf("Not sending message to remote.\n");
+ else {
+ pData->ttSuspend = time(NULL);
+ psz = (char*) ppString[0];
+ l = strlen((char*) psz);
+ if (l > MAXLINE)
+ l = MAXLINE;
+
+# ifdef USE_NETZIP
+ /* Check if we should compress and, if so, do it. We also
+ * check if the message is large enough to justify compression.
+ * The smaller the message, the less likely is a gain in compression.
+ * To save CPU cycles, we do not try to compress very small messages.
+ * What "very small" means needs to be configured. Currently, it is
+ * hard-coded but this may be changed to a config parameter.
+ * rgerhards, 2006-11-30
+ */
+ if(pData->compressionLevel && (l > MIN_SIZE_FOR_COMPRESS)) {
+ Bytef out[MAXLINE+MAXLINE/100+12] = "z";
+ uLongf destLen = sizeof(out) / sizeof(Bytef);
+ uLong srcLen = l;
+ int ret;
+ ret = compress2((Bytef*) out+1, &destLen, (Bytef*) psz,
+ srcLen, pData->compressionLevel);
+ dbgprintf("Compressing message, length was %d now %d, return state %d.\n",
+ l, (int) destLen, ret);
+ if(ret != Z_OK) {
+ /* if we fail, we complain, but only in debug mode
+ * Otherwise, we are silent. In any case, we ignore the
+ * failed compression and just sent the uncompressed
+ * data, which is still valid. So this is probably the
+ * best course of action.
+ * rgerhards, 2006-11-30
+ */
+ dbgprintf("Compression failed, sending uncompressed message\n");
+ } else if(destLen+1 < l) {
+ /* only use compression if there is a gain in using it! */
+ dbgprintf("there is gain in compression, so we do it\n");
+ psz = (char*) out;
+ l = destLen + 1; /* take care for the "z" at message start! */
+ }
+ ++destLen;
+ }
+# endif
+
+ if(pData->protocol == FORW_UDP) {
+ /* forward via UDP */
+ if(finet != NULL) {
+ /* we need to track if we have success sending to the remote
+ * peer. Success is indicated by at least one sendto() call
+ * succeeding. We track this be bSendSuccess. We can not simply
+ * rely on lsent, as a call might initially work, but a later
+ * call fails. Then, lsent has the error status, even though
+ * the sendto() succeeded.
+ * rgerhards, 2007-06-22
+ */
+ bSendSuccess = FALSE;
+ for (r = pData->f_addr; r; r = r->ai_next) {
+ for (i = 0; i < *finet; i++) {
+ lsent = sendto(finet[i+1], psz, l, 0,
+ r->ai_addr, r->ai_addrlen);
+ if (lsent == l) {
+ bSendSuccess = TRUE;
+ break;
+ } else {
+ int eno = errno;
+ dbgprintf("sendto() error: %d = %s.\n",
+ eno, strerror(eno));
+ }
+ }
+ if (lsent == l && !send_to_all)
+ break;
+ }
+ /* finished looping */
+ if (bSendSuccess == FALSE) {
+ dbgprintf("error forwarding via udp, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+ } else {
+ /* forward via TCP */
+ if(TCPSend(pData, psz, l) != 0) {
+ /* error! */
+ dbgprintf("error forwarding via tcp, suspending\n");
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+ }
+ break;
+ }
+ENDdoAction
+
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+ int error;
+ int bErr;
+ struct addrinfo hints, *res;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ if(*p == '@') {
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ return iRet;
+ ++p; /* eat '@' */
+ if(*p == '@') { /* indicator for TCP! */
+ pData->protocol = FORW_TCP;
+ ++p; /* eat this '@', too */
+ /* in this case, we also need a mutex... */
+# ifdef USE_PTHREADS
+ pthread_mutex_init(&pData->mtxTCPSend, 0);
+# endif
+ } else {
+ pData->protocol = FORW_UDP;
+ }
+ /* we are now after the protocol indicator. Now check if we should
+ * use compression. We begin to use a new option format for this:
+ * @(option,option)host:port
+ * The first option defined is "z[0..9]" where the digit indicates
+ * the compression level. If it is not given, 9 (best compression) is
+ * assumed. An example action statement might be:
+ * @@(z5,o)127.0.0.1:1400
+ * Which means send via TCP with medium (5) compresion (z) to the local
+ * host on port 1400. The '0' option means that octet-couting (as in
+ * IETF I-D syslog-transport-tls) is to be used for framing (this option
+ * applies to TCP-based syslog only and is ignored when specified with UDP).
+ * That is not yet implemented.
+ * rgerhards, 2006-12-07
+ */
+ if(*p == '(') {
+ /* at this position, it *must* be an option indicator */
+ do {
+ ++p; /* eat '(' or ',' (depending on when called) */
+ /* check options */
+ if(*p == 'z') { /* compression */
+# ifdef USE_NETZIP
+ ++p; /* eat */
+ if(isdigit((int) *p)) {
+ int iLevel;
+ iLevel = *p - '0';
+ ++p; /* eat */
+ pData->compressionLevel = iLevel;
+ } else {
+ logerrorInt("Invalid compression level '%c' specified in "
+ "forwardig action - NOT turning on compression.",
+ *p);
+ }
+# else
+ logerror("Compression requested, but rsyslogd is not compiled "
+ "with compression support - request ignored.");
+# endif /* #ifdef USE_NETZIP */
+ } else if(*p == 'o') { /* octet-couting based TCP framing? */
+ ++p; /* eat */
+ /* no further options settable */
+ pData->tcp_framing = TCP_FRAMING_OCTET_COUNTING;
+ } else { /* invalid option! Just skip it... */
+ logerrorInt("Invalid option %c in forwarding action - ignoring.", *p);
+ ++p; /* eat invalid option */
+ }
+ /* the option processing is done. We now do a generic skip
+ * to either the next option or the end of the option
+ * block.
+ */
+ while(*p && *p != ')' && *p != ',')
+ ++p; /* just skip it */
+ } while(*p && *p == ','); /* Attention: do.. while() */
+ if(*p == ')')
+ ++p; /* eat terminator, on to next */
+ else
+ /* we probably have end of string - leave it for the rest
+ * of the code to handle it (but warn the user)
+ */
+ logerror("Option block not terminated in forwarding action.");
+ }
+ /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0')
+ * now skip to port and then template name. rgerhards 2005-07-06
+ */
+ for(q = p ; *p && *p != ';' && *p != ':' ; ++p)
+ /* JUST SKIP */;
+
+ pData->port = NULL;
+ if(*p == ':') { /* process port */
+ uchar * tmp;
+
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ tmp = ++p;
+ for(i=0 ; *p && isdigit((int) *p) ; ++p, ++i)
+ /* SKIP AND COUNT */;
+ pData->port = malloc(i + 1);
+ if(pData->port == NULL) {
+ logerror("Could not get memory to store syslog forwarding port, "
+ "using default port, results may not be what you intend\n");
+ /* we leave f_forw.port set to NULL, this is then handled by
+ * getFwdSyslogPt().
+ */
+ } else {
+ memcpy(pData->port, tmp, i);
+ *(pData->port + i) = '\0';
+ }
+ }
+
+ /* now skip to template */
+ bErr = 0;
+ while(*p && *p != ';') {
+ if(*p && *p != ';' && !isspace((int) *p)) {
+ if(bErr == 0) { /* only 1 error msg! */
+ bErr = 1;
+ errno = 0;
+ logerror("invalid selector line (port), probably not doing "
+ "what was intended");
+ }
+ }
+ ++p;
+ }
+
+ /* TODO: make this if go away! */
+ if(*p == ';') {
+ *p = '\0'; /* trick to obtain hostname (later)! */
+ strcpy(pData->f_hname, (char*) q);
+ *p = ';';
+ } else
+ strcpy(pData->f_hname, (char*) q);
+
+ /* process template */
+ if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) " StdFwdFmt"))
+ != RS_RET_OK)
+ return iRet;
+
+ /* first set the pData->eDestState */
+ memset(&hints, 0, sizeof(hints));
+ /* port must be numeric, because config file syntax requests this */
+ hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_family = family;
+ hints.ai_socktype = pData->protocol == FORW_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ if( (error = getaddrinfo(pData->f_hname, getFwdSyslogPt(pData), &hints, &res)) != 0) {
+ pData->eDestState = eDestFORW_UNKN;
+ pData->iRtryCnt = INET_RETRY_MAX;
+ pData->ttSuspend = time(NULL);
+ } else {
+ pData->eDestState = eDestFORW;
+ pData->f_addr = res;
+ }
+
+ /*
+ * Otherwise the host might be unknown due to an
+ * inaccessible nameserver (perhaps on the same
+ * host). We try to get the ip number later, like
+ * FORW_SUSP.
+ */
+ } else {
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ }
+
+ /* TODO: do we need to call freeInstance if we failed - this is a general question for
+ * all output modules. I'll address it lates as the interface evolves. rgerhards, 2007-07-25
+ */
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ iRet = RS_RET_TRUE;
+ENDneedUDPSocket
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ dbgprintf("tcp send socket %d ready for writing.\n", pData->sock);
+ TCPSendSetStatus(pData, TCP_SEND_READY);
+ /* Send stored message (if any) */
+ if(pData->savedMsg != NULL) {
+ if(TCPSend(pData, pData->savedMsg,
+ pData->savedMsgLen) != 0) {
+ /* error! */
+ pData->eDestState = eDestFORW_SUSP;
+ errno = 0;
+ logerror("error forwarding via tcp, suspending...");
+ }
+ free(pData->savedMsg);
+ pData->savedMsg = NULL;
+ }
+ENDonSelectReadyWrite
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ if( (pData->eDestState == eDestFORW)
+ && (pData->protocol == FORW_TCP)
+ && TCPSendGetStatus(pData) == TCP_SEND_CONNECTING) {
+ *fd = pData->sock;
+ iRet = RS_RET_OK;
+ }
+ENDgetWriteFDForSelect
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Fwd)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+#endif /* #ifdef SYSLOG_INET */
+/*
+ * vi:set ai:
+ */
diff --git a/omfwd.h b/omfwd.h
new file mode 100644
index 0000000..b2ea5cc
--- /dev/null
+++ b/omfwd.h
@@ -0,0 +1,33 @@
+/* omfwd.h
+ * These are the definitions for the build-in forwarding output module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef OMFWD_H_INCLUDED
+#define OMFWD_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitFwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+
+#endif /* #ifndef OMFWD_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/ommysql.c b/ommysql.c
new file mode 100644
index 0000000..fac4c18
--- /dev/null
+++ b/ommysql.c
@@ -0,0 +1,310 @@
+/* ommysql.c
+ * This is the implementation of the build-in output module for MySQL.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#ifdef WITH_DB
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <time.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "template.h"
+#include "ommysql.h"
+#include "mysql/mysql.h"
+#include "mysql/errmsg.h"
+#include "module-template.h"
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ MYSQL *f_hmysql; /* handle to MySQL */
+ char f_dbsrv[MAXHOSTNAMELEN+1]; /* IP or hostname of DB server*/
+ char f_dbname[_DB_MAXDBLEN+1]; /* DB name */
+ char f_dbuid[_DB_MAXUNAMELEN+1]; /* DB user */
+ char f_dbpwd[_DB_MAXPWDLEN+1]; /* DB user's password */
+ unsigned uLastMySQLErrno; /* last errno returned by MySQL or 0 if all is well */
+} instanceData;
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+/* The following function is responsible for closing a
+ * MySQL connection.
+ * Initially added 2004-10-28
+ */
+static void closeMySQL(instanceData *pData)
+{
+ assert(pData != NULL);
+
+ if(pData->f_hmysql != NULL) { /* just to be on the safe side... */
+ mysql_close(pData->f_hmysql);
+ pData->f_hmysql = NULL;
+ }
+}
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ closeMySQL(pData);
+ENDfreeInstance
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ENDneedUDPSocket
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ /* nothing special here */
+ENDdbgPrintInstInfo
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ENDonSelectReadyWrite
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ENDgetWriteFDForSelect
+
+
+/* log a database error with descriptive message.
+ * We check if we have a valid MySQL handle. If not, we simply
+ * report an error, but can not be specific. RGerhards, 2007-01-30
+ */
+static void reportDBError(instanceData *pData, int bSilent)
+{
+ char errMsg[512];
+ unsigned uMySQLErrno;
+
+ assert(pData != NULL);
+
+ /* output log message */
+ errno = 0;
+ if(pData->f_hmysql == NULL) {
+ logerror("unknown DB error occured - could not obtain MySQL handle");
+ } else { /* we can ask mysql for the error description... */
+ uMySQLErrno = mysql_errno(pData->f_hmysql);
+ snprintf(errMsg, sizeof(errMsg)/sizeof(char), "db error (%d): %s\n", uMySQLErrno,
+ mysql_error(pData->f_hmysql));
+ if(bSilent || uMySQLErrno == pData->uLastMySQLErrno)
+ dbgprintf("mysql, DBError(silent): %s\n", errMsg);
+ else {
+ pData->uLastMySQLErrno = uMySQLErrno;
+ logerror(errMsg);
+ }
+ }
+
+ return;
+}
+
+
+/* The following function is responsible for initializing a
+ * MySQL connection.
+ * Initially added 2004-10-28 mmeckelein
+ */
+static rsRetVal initMySQL(instanceData *pData, int bSilent)
+{
+ DEFiRet;
+
+ assert(pData != NULL);
+ assert(pData->f_hmysql == NULL);
+
+ pData->f_hmysql = mysql_init(NULL);
+ if(pData->f_hmysql == NULL) {
+ logerror("can not initialize MySQL handle");
+ iRet = RS_RET_SUSPENDED;
+ } else { /* we could get the handle, now on with work... */
+ /* Connect to database */
+ if(mysql_real_connect(pData->f_hmysql, pData->f_dbsrv, pData->f_dbuid,
+ pData->f_dbpwd, pData->f_dbname, 0, NULL, 0) == NULL) {
+ reportDBError(pData, bSilent);
+ closeMySQL(pData); /* ignore any error we may get */
+ iRet = RS_RET_SUSPENDED;
+ }
+ }
+
+ return iRet;
+}
+
+
+/* The following function writes the current log entry
+ * to an established MySQL session.
+ * Initially added 2004-10-28 mmeckelein
+ */
+rsRetVal writeMySQL(uchar *psz, instanceData *pData)
+{
+ DEFiRet;
+
+ assert(psz != NULL);
+ assert(pData != NULL);
+
+ /* try insert */
+ if(mysql_query(pData->f_hmysql, (char*)psz)) {
+ /* error occured, try to re-init connection and retry */
+ closeMySQL(pData); /* close the current handle */
+ CHKiRet(initMySQL(pData, 0)); /* try to re-open */
+ if(mysql_query(pData->f_hmysql, (char*)psz)) { /* re-try insert */
+ /* we failed, giving up for now */
+ reportDBError(pData, 0);
+ closeMySQL(pData); /* free ressources */
+ ABORT_FINALIZE(RS_RET_SUSPENDED);
+ }
+ }
+
+finalize_it:
+ if(iRet == RS_RET_OK) {
+ pData->uLastMySQLErrno = 0; /* reset error for error supression */
+ }
+
+ return iRet;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ if(pData->f_hmysql == NULL) {
+ iRet = initMySQL(pData, 1);
+ }
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf("\n");
+ iRet = writeMySQL(ppString[0], pData);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+ int iMySQLPropErr = 0;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(*p != '>') {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ return iRet;
+
+ p++; /* eat '>' '*/
+
+ /* rger 2004-10-28: added support for MySQL
+ * >server,dbname,userid,password
+ * rgerhards 2005-08-12: changed rsyslogd so that
+ * if no DB is selected and > is used, an error
+ * message is logged.
+ */
+ if(bModMySQLLoaded == 0)
+ logerror("To enable MySQL logging, a \"$ModLoad MySQL\" must be done - accepted for "
+ "the time being, but will fail in future releases.");
+#ifndef WITH_DB
+ iRet = RS_RET_ERROR; /* this goes away anyhow, so it's not worth putting much effort in the return code */
+ errno = 0;
+ logerror("write to database action in config file, but rsyslogd compiled without "
+ "database functionality - ignored");
+#else /* WITH_DB defined! */
+
+ /* Now we read the MySQL connection properties
+ * and verify that the properties are valid.
+ */
+ if(getSubString(&p, pData->f_dbsrv, MAXHOSTNAMELEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->f_dbsrv == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->f_dbname, _DB_MAXDBLEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->f_dbname == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->f_dbuid, _DB_MAXUNAMELEN+1, ','))
+ iMySQLPropErr++;
+ if(*pData->f_dbuid == '\0')
+ iMySQLPropErr++;
+ if(getSubString(&p, pData->f_dbpwd, _DB_MAXPWDLEN+1, ';'))
+ iMySQLPropErr++;
+ /* now check for template
+ * We specify that the SQL option must be present in the template.
+ * This is for your own protection (prevent sql injection).
+ */
+ if(*(p-1) == ';')
+ --p; /* TODO: the whole parsing of the MySQL module needs to be re-thought - but this here
+ * is clean enough for the time being -- rgerhards, 2007-07-30
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_RQD_TPL_OPT_SQL, (uchar*) " StdDBFmt"));
+
+ /* If we detect invalid properties, we disable logging,
+ * because right properties are vital at this place.
+ * Retries make no sense.
+ */
+ if (iMySQLPropErr) {
+ logerror("Trouble with MySQL connection properties. -MySQL logging disabled");
+ ABORT_FINALIZE(RS_RET_INVALID_PARAMS);
+ } else {
+ CHKiRet(initMySQL(pData, 0));
+ }
+#endif /* #ifdef WITH_DB */
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(MySQL)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+#endif /* #ifdef WITH_DB */
+/*
+ * vi:set ai:
+ */
diff --git a/ommysql.h b/ommysql.h
new file mode 100644
index 0000000..3162a7c
--- /dev/null
+++ b/ommysql.h
@@ -0,0 +1,38 @@
+/* omusrmsg.c
+ * These are the definitions for the build-in MySQL output module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef OMMYSQL_H_INCLUDED
+#define OMMYSQL_H_INCLUDED 1
+#ifdef WITH_DB
+
+/* prototypes */
+/* prototypes will be removed as syslogd needs no longer to directly
+ * call into the module!
+ */
+rsRetVal modInitMySQL(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+
+#endif /* #ifdef WITH_DB */
+#endif /* #ifndef OMMYSQL_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/omshell.c b/omshell.c
new file mode 100644
index 0000000..ac0c9aa
--- /dev/null
+++ b/omshell.c
@@ -0,0 +1,151 @@
+/* omshell.c
+ * This is the implementation of the build-in shell output module.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * shell support was initially written by bkalkbrenner 2005-09-20
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "srUtils.h"
+#include "omshell.h"
+#include "module-template.h"
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ uchar progName[MAXFNAME]; /* program to execute */
+} instanceData;
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ printf("%s", pData->progName);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ /* TODO: using pData->progName is not clean from the point of
+ * modularization. We'll change that as we go ahead with modularization.
+ * rgerhards, 2007-07-20
+ */
+ dbgprintf("\n");
+ if(execProg((uchar*) pData->progName, 1, ppString[0]) == 0)
+ logerrorSz("Executing program '%s' failed", (char*)pData->progName);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* yes, the if below is redundant, but I need it now. Will go away as
+ * the code further changes. -- rgerhards, 2007-07-25
+ */
+ if(*p == '^') {
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ return iRet;
+ }
+
+
+ switch (*p)
+ {
+ case '^': /* bkalkbrenner 2005-09-20: execute shell command */
+ dbgprintf("exec\n");
+ ++p;
+ iRet = cflineParseFileName(p, (uchar*) pData->progName, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS);
+ break;
+ default:
+ iRet = RS_RET_CONFLINE_UNPROCESSED;
+ break;
+ }
+
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ENDneedUDPSocket
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ENDonSelectReadyWrite
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ENDgetWriteFDForSelect
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(Shell)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+/*
+ * vi:set ai:
+ */
diff --git a/omshell.h b/omshell.h
new file mode 100644
index 0000000..8ae2ef0
--- /dev/null
+++ b/omshell.h
@@ -0,0 +1,33 @@
+/* omshell.c
+ * These are the definitions for the build-in shell output module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef ACTSHELL_H_INCLUDED
+#define ACTSHELL_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitShell(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+
+#endif /* #ifndef ACTSHELL_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/omusrmsg.c b/omusrmsg.c
new file mode 100644
index 0000000..736f325
--- /dev/null
+++ b/omusrmsg.c
@@ -0,0 +1,334 @@
+/* omusrmsg.c
+ * This is the implementation of the build-in output module for sending
+ * user messages.
+ *
+ * NOTE: read comments in module-template.h to understand how this file
+ * works!
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <setjmp.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#include <sys/msgbuf.h>
+#endif
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "syslogd.h"
+#include "omusrmsg.h"
+#include "module-template.h"
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+typedef struct _instanceData {
+ int bIsWall; /* 1- is wall, 0 - individual users */
+ char uname[MAXUNAMES][UNAMESZ+1];
+} instanceData;
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ if(eFeat == sFEATURERepeatedMsgReduction)
+ iRet = RS_RET_OK;
+ENDisCompatibleWithFeature
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ /* TODO: free the instance pointer (currently a leak, will go away) */
+ENDfreeInstance
+
+
+BEGINneedUDPSocket
+CODESTARTneedUDPSocket
+ENDneedUDPSocket
+
+
+BEGINdbgPrintInstInfo
+ register int i;
+CODESTARTdbgPrintInstInfo
+ for (i = 0; i < MAXUNAMES && *pData->uname[i]; i++)
+ printf("%s, ", pData->uname[i]);
+ENDdbgPrintInstInfo
+
+
+static jmp_buf ttybuf;
+
+static void endtty()
+{
+ longjmp(ttybuf, 1);
+}
+
+/**
+ * BSD setutent/getutent() replacement routines
+ * The following routines emulate setutent() and getutent() under
+ * BSD because they are not available there. We only emulate what we actually
+ * need! rgerhards 2005-03-18
+ */
+#ifdef BSD
+static FILE *BSD_uf = NULL;
+void setutent(void)
+{
+ assert(BSD_uf == NULL);
+ if ((BSD_uf = fopen(_PATH_UTMP, "r")) == NULL) {
+ logerror(_PATH_UTMP);
+ return;
+ }
+}
+
+struct utmp* getutent(void)
+{
+ static struct utmp st_utmp;
+
+ if(fread((char *)&st_utmp, sizeof(st_utmp), 1, BSD_uf) != 1)
+ return NULL;
+
+ return(&st_utmp);
+}
+
+void endutent(void)
+{
+ fclose(BSD_uf);
+ BSD_uf = NULL;
+}
+#endif
+
+
+/*
+ * WALLMSG -- Write a message to the world at large
+ *
+ * Write the specified message to either the entire
+ * world, or a list of approved users.
+ *
+ * rgerhards, 2005-10-19: applying the following sysklogd patch:
+ * Tue May 4 16:52:01 CEST 2004: Solar Designer <solar@openwall.com>
+ * Adjust the size of a variable to prevent a buffer overflow
+ * should _PATH_DEV ever contain something different than "/dev/".
+ */
+static rsRetVal wallmsg(uchar* pMsg, instanceData *pData)
+{
+
+ char p[sizeof(_PATH_DEV) + UNAMESZ];
+ register int i;
+ int ttyf;
+ static int reenter = 0;
+ struct utmp ut;
+ struct utmp *uptr;
+
+ assert(pMsg != NULL);
+
+ if (reenter++)
+ return RS_RET_OK;
+
+ /* open the user login file */
+ setutent();
+
+ /*
+ * Might as well fork instead of using nonblocking I/O
+ * and doing notty().
+ */
+ if (fork() == 0) {
+ signal(SIGTERM, SIG_DFL);
+ alarm(0);
+# ifdef SIGTTOU
+ signal(SIGTTOU, SIG_IGN);
+# endif
+ sigsetmask(0);
+ /* TODO: find a way to limit the max size of the message. hint: this
+ * should go into the template!
+ */
+
+ /* rgerhards 2005-10-24: HINT: this code might be run in a seperate thread
+ * instead of a seperate process once we have multithreading...
+ */
+
+ /* scan the user login file */
+ while ((uptr = getutent())) {
+ memcpy(&ut, uptr, sizeof(ut));
+ /* is this slot used? */
+ if (ut.ut_name[0] == '\0')
+ continue;
+#ifndef BSD
+ if (ut.ut_type != USER_PROCESS)
+ continue;
+#endif
+ if (!(strncmp (ut.ut_name,"LOGIN", 6))) /* paranoia */
+ continue;
+
+ /* should we send the message to this user? */
+ if (pData->bIsWall == 0) {
+ for (i = 0; i < MAXUNAMES; i++) {
+ if (!pData->uname[i][0]) {
+ i = MAXUNAMES;
+ break;
+ }
+ if (strncmp(pData->uname[i],
+ ut.ut_name, UNAMESZ) == 0)
+ break;
+ }
+ if (i >= MAXUNAMES)
+ continue;
+ }
+
+ /* compute the device name */
+ strcpy(p, _PATH_DEV);
+ strncat(p, ut.ut_line, UNAMESZ);
+
+ if (setjmp(ttybuf) == 0) {
+ (void) signal(SIGALRM, endtty);
+ (void) alarm(15);
+ /* open the terminal */
+ ttyf = open(p, O_WRONLY|O_NOCTTY);
+ if (ttyf >= 0) {
+ struct stat statb;
+
+ if (fstat(ttyf, &statb) == 0 &&
+ (statb.st_mode & S_IWRITE)) {
+ (void) write(ttyf, pMsg, strlen((char*)pMsg));
+ }
+ close(ttyf);
+ ttyf = -1;
+ }
+ }
+ (void) alarm(0);
+ }
+ exit(0); /* "good" exit - this terminates the child forked just for message delivery */
+ }
+ /* close the user login file */
+ endutent();
+ reenter = 0;
+ return RS_RET_OK;
+}
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+BEGINdoAction
+CODESTARTdoAction
+ dbgprintf("\n");
+ iRet = wallmsg(ppString[0], pData);
+ENDdoAction
+
+
+BEGINparseSelectorAct
+ uchar *q;
+ int i;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+
+#if 0 /* TODO: think about it and activate later - see comments in else below */
+ if(**pp != '*')
+ return RS_RET_CONFLINE_UNPROCESSED;
+#endif
+ if((iRet = createInstance(&pData)) != RS_RET_OK)
+ return iRet;
+
+
+ if(*p == '*') { /* wall */
+ dbgprintf("write-all");
+ ++p; /* eat '*' */
+ pData->bIsWall = 1; /* write to all users */
+ if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*) " WallFmt"))
+ != RS_RET_OK)
+ return iRet;
+ } else {
+ /* everything else is currently treated as a user name
+ * TODO: we must reconsider this - see also comment in
+ * loadBuildInModules() in syslogd.c
+ */
+ dbgprintf("users: %s\n", p); /* ASP */
+ pData->bIsWall = 0; /* write to individual users */
+ for (i = 0; i < MAXUNAMES && *p && *p != ';'; i++) {
+ for (q = p; *q && *q != ',' && *q != ';'; )
+ q++;
+ (void) strncpy((char*) pData->uname[i], (char*) p, UNAMESZ);
+ if ((q - p) > UNAMESZ)
+ pData->uname[i][UNAMESZ] = '\0';
+ else
+ pData->uname[i][q - p] = '\0';
+ while (*q == ',' || *q == ' ')
+ q++;
+ p = q;
+ }
+ /* done, on to the template
+ * TODO: we need to handle the case where i >= MAXUNAME!
+ */
+ if((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar*)" StdUsrMsgFmt"))
+ != RS_RET_OK)
+ return iRet;
+ }
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINonSelectReadyWrite
+CODESTARTonSelectReadyWrite
+ENDonSelectReadyWrite
+
+
+BEGINgetWriteFDForSelect
+CODESTARTgetWriteFDForSelect
+ENDgetWriteFDForSelect
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+ENDqueryEtryPt
+
+
+BEGINmodInit(UsrMsg)
+CODESTARTmodInit
+ *ipIFVersProvided = 1; /* so far, we only support the initial definition */
+CODEmodInit_QueryRegCFSLineHdlr
+ENDmodInit
+
+/*
+ * vi:set ai:
+ */
diff --git a/omusrmsg.h b/omusrmsg.h
new file mode 100644
index 0000000..2c0aeb8
--- /dev/null
+++ b/omusrmsg.h
@@ -0,0 +1,33 @@
+/* omusrmsg.c
+ * These are the definitions for the build-in user message output module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef OMUSRMSG_H_INCLUDED
+#define OMUSRMSG_H_INCLUDED 1
+
+/* prototypes */
+rsRetVal modInitUsrMsg(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar*, rsRetVal (**)()));
+
+#endif /* #ifndef OMUSRMSG_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/outchannel.c b/outchannel.c
new file mode 100644
index 0000000..a713680
--- /dev/null
+++ b/outchannel.c
@@ -0,0 +1,279 @@
+/* This is the output channel processing code of rsyslog.
+ * Output channels - in the long term - will define how
+ * messages will be sent to whatever file or other medium.
+ * Currently, they mainly provide a way to store some file-related
+ * information (most importantly the maximum file size allowed).
+ * Please see syslogd.c for license information.
+ * This code is placed under the GPL.
+ * begun 2005-06-21 rgerhards
+ */
+#include "config.h"
+
+#ifdef __FreeBSD__
+#define BSD
+#endif
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "stringbuf.h"
+#include "outchannel.h"
+#include "syslogd.h"
+
+static struct outchannel *ochRoot = NULL; /* the root of the outchannel list */
+static struct outchannel *ochLast = NULL; /* points to the last element of the outchannel list */
+
+/* Constructs a outchannel list object. Returns pointer to it
+ * or NULL (if it fails).
+ */
+struct outchannel* ochConstruct(void)
+{
+ struct outchannel *pOch;
+ if((pOch = calloc(1, sizeof(struct outchannel))) == NULL)
+ return NULL;
+
+ /* basic initialisaion is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(ochLast == NULL)
+ { /* we are the first element! */
+ ochRoot = ochLast = pOch;
+ }
+ else
+ {
+ ochLast->pNext = pOch;
+ ochLast = pOch;
+ }
+
+ return(pOch);
+}
+
+
+/* skips the next comma and any whitespace
+ * in front and after it.
+ */
+static void skip_Comma(char **pp)
+{
+ register char *p;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ p = *pp;
+ while(isspace((int)*p))
+ ++p;
+ if(*p == ',')
+ ++p;
+ while(isspace((int)*p))
+ ++p;
+ *pp = p;
+}
+
+/* helper to ochAddLine. Parses a comma-delimited field
+ * The field is delimited by SP or comma. Leading whitespace
+ * is "eaten" and does not become part of the field content.
+ * returns: 0 - ok, 1 - failure
+ */
+static int get_Field(uchar **pp, char **pField)
+{
+ register uchar *p;
+ rsCStrObj *pStrB;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pField != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ if((pStrB = rsCStrConstruct()) == NULL)
+ return 1;
+ rsCStrSetAllocIncrement(pStrB, 32);
+
+ /* copy the field */
+ while(*p && *p != ' ' && *p != ',') {
+ rsCStrAppendChar(pStrB, *p++);
+ }
+
+ *pp = p;
+ rsCStrFinish(pStrB);
+ *pField = (char*)rsCStrConvSzStrAndDestruct(pStrB);
+
+ return 0;
+}
+
+
+/* helper to ochAddLine. Parses a off_t type from the
+ * input line.
+ * returns: 0 - ok, 1 - failure
+ */
+static int get_off_t(uchar **pp, off_t *pOff_t)
+{
+ register uchar *p;
+ off_t val;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pOff_t != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ val = 0;
+ while(*p && isdigit((int)*p)) {
+ val = val * 10 + (*p - '0');
+ ++p;
+ }
+
+ *pp = p;
+ *pOff_t = val;
+
+ return 0;
+}
+
+
+/* helper to ochAddLine. Parses everything from the
+ * current position to the end of line and returns it
+ * to the caller. Leading white space is removed, but
+ * not trailing.
+ * returns: 0 - ok, 1 - failure
+ */
+static inline int get_restOfLine(uchar **pp, char **pBuf)
+{
+ register uchar *p;
+ rsCStrObj *pStrB;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pBuf != NULL);
+
+ skip_Comma((char**)pp);
+ p = *pp;
+
+ if((pStrB = rsCStrConstruct()) == NULL)
+ return 1;
+ rsCStrSetAllocIncrement(pStrB, 32);
+
+ /* copy the field */
+ while(*p) {
+ rsCStrAppendChar(pStrB, *p++);
+ }
+
+ *pp = p;
+ rsCStrFinish(pStrB);
+ *pBuf = (char*) rsCStrConvSzStrAndDestruct(pStrB);
+
+ return 0;
+}
+
+
+/* Add a new outchannel line
+ * returns pointer to new object if it succeeds, NULL otherwise.
+ * An outchannel line is primarily a set of fields delemited by commas.
+ * There might be some whitespace between the field (but not within)
+ * and the commas. This can be removed.
+ */
+struct outchannel *ochAddLine(char* pName, uchar** ppRestOfConfLine)
+{
+ struct outchannel *pOch;
+ uchar *p;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+
+ if((pOch = ochConstruct()) == NULL)
+ return NULL;
+
+ pOch->iLenName = strlen(pName);
+ pOch->pszName = (char*) malloc(sizeof(char) * (pOch->iLenName + 1));
+ if(pOch->pszName == NULL) {
+ dbgprintf("ochAddLine could not alloc memory for outchannel name!");
+ pOch->iLenName = 0;
+ return NULL;
+ /* I know - we create a memory leak here - but I deem
+ * it acceptable as it is a) a very small leak b) very
+ * unlikely to happen. rgerhards 2004-11-17
+ */
+ }
+ memcpy(pOch->pszName, pName, pOch->iLenName + 1);
+
+ /* now actually parse the line */
+ p = *ppRestOfConfLine;
+ assert(p != NULL);
+
+ /* get params */
+ get_Field(&p, &pOch->pszFileTemplate);
+ if(*p) get_off_t(&p, &pOch->uSizeLimit);
+ if(*p) get_restOfLine(&p, &pOch->cmdOnSizeLimit);
+
+ *ppRestOfConfLine = p;
+ return(pOch);
+}
+
+
+/* Find a outchannel object based on name. Search
+ * currently is case-senstive (should we change?).
+ * returns pointer to outchannel object if found and
+ * NULL otherwise.
+ * rgerhards 2004-11-17
+ */
+struct outchannel *ochFind(char *pName, int iLenName)
+{
+ struct outchannel *pOch;
+
+ assert(pName != NULL);
+
+ pOch = ochRoot;
+ while(pOch != NULL &&
+ !(pOch->iLenName == iLenName &&
+ !strcmp(pOch->pszName, pName)
+ ))
+ {
+ pOch = pOch->pNext;
+ }
+ return(pOch);
+}
+
+/* Destroy the outchannel structure. This is for de-initialization
+ * at program end. Everything is deleted.
+ * rgerhards 2005-02-22
+ */
+void ochDeleteAll(void)
+{
+ struct outchannel *pOch, *pOchDel;
+
+ pOch = ochRoot;
+ while(pOch != NULL) {
+ dbgprintf("Delete Outchannel: Name='%s'\n ", pOch->pszName == NULL? "NULL" : pOch->pszName);
+ pOchDel = pOch;
+ pOch = pOch->pNext;
+ if(pOchDel->pszName != NULL)
+ free(pOchDel->pszName);
+ free(pOchDel);
+ }
+}
+
+
+/* Print the outchannel structure. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ */
+void ochPrintList(void)
+{
+ struct outchannel *pOch;
+
+ pOch = ochRoot;
+ while(pOch != NULL) {
+ dbgprintf("Outchannel: Name='%s'\n", pOch->pszName == NULL? "NULL" : pOch->pszName);
+ dbgprintf("\tFile Template: '%s'\n", pOch->pszFileTemplate == NULL ? "NULL" : pOch->pszFileTemplate);
+ dbgprintf("\tMax Size.....: %lu\n", pOch->uSizeLimit);
+ dbgprintf("\tOnSizeLimtCmd: '%s'\n", pOch->cmdOnSizeLimit == NULL ? "NULL" : pOch->cmdOnSizeLimit);
+ pOch = pOch->pNext; /* done, go next */
+ }
+}
+/*
+ * vi:set ai:
+ */
diff --git a/outchannel.h b/outchannel.h
new file mode 100644
index 0000000..eb12af7
--- /dev/null
+++ b/outchannel.h
@@ -0,0 +1,23 @@
+/* This is the header for the output channel code of rsyslog.
+ * Please see syslogd.c for license information.
+ * This code is placed under the GPL.
+ * begun 2005-06-21 rgerhards
+ */
+struct outchannel {
+ struct outchannel *pNext;
+ char *pszName;
+ int iLenName;
+ char *pszFileTemplate;
+ off_t uSizeLimit;
+ char *cmdOnSizeLimit;
+};
+
+struct outchannel* ochConstruct(void);
+struct outchannel *ochAddLine(char* pName, unsigned char** pRestOfConfLine);
+struct outchannel *ochFind(char *pName, int iLenName);
+void ochDeleteAll(void);
+void ochPrintList(void);
+
+/*
+ * vi:set ai:
+ */
diff --git a/parse.c b/parse.c
new file mode 100644
index 0000000..efa7f53
--- /dev/null
+++ b/parse.c
@@ -0,0 +1,555 @@
+/* parsing routines for the counted string class. for generic
+ * informaton see parse.h.
+ *
+ * begun 2005-09-15 rgerhards
+ *
+ * Copyright 2005
+ * Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
+ * This code is placed under the GPL.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include "rsyslog.h"
+#include "net.h" /* struct NetAddr */
+#include "parse.h"
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+
+/**
+ * Destruct a rsPars object and its associated string.
+ * rgerhards, 2005-09-26
+ */
+rsRetVal rsParsDestruct(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if(pThis->pCStr != NULL)
+ rsCStrDestruct (pThis->pCStr);
+ RSFREEOBJ(pThis);
+ return RS_RET_OK;
+}
+
+
+/**
+ * Construct a rsPars object.
+ */
+rsRetVal rsParsConstruct(rsParsObj **ppThis)
+{
+ rsParsObj *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (rsParsObj*) calloc(1, sizeof(rsParsObj))) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ rsSETOBJTYPE(pThis, OIDrsPars);
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+/**
+ * Construct a rsPars object and populate it with a
+ * classical zero-terinated C-String.
+ * rgerhards, 2005-09-27
+ */
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz)
+{
+ rsParsObj *pThis;
+ rsCStrObj *pCS;
+ rsRetVal iRet;
+
+ assert(ppThis != NULL);
+ assert(psz != NULL);
+
+ /* create string for parser */
+ if((iRet = rsCStrConstructFromszStr(&pCS, psz)) != RS_RET_OK)
+ return(iRet);
+
+ /* create parser */
+ if((iRet = rsParsConstruct(&pThis)) != RS_RET_OK) {
+ rsCStrDestruct (pCS);
+ return(iRet);
+ }
+
+ /* assign string to parser */
+ if((iRet = rsParsAssignString(pThis, pCS)) != RS_RET_OK) {
+ rsParsDestruct(pThis);
+ return(iRet);
+ }
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+/**
+ * Assign the to-be-parsed string.
+ */
+rsRetVal rsParsAssignString(rsParsObj *pThis, rsCStrObj *pCStr)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ rsCHECKVALIDOBJECT(pCStr, OIDrsCStr);
+
+ pThis->pCStr = pCStr;
+ pThis->iCurrPos = 0;
+
+ return RS_RET_OK;
+}
+
+/* parse an integer. The parse pointer is advanced to the
+ * position directly after the last digit. If no digit is
+ * found at all, an error is returned and the parse pointer
+ * is NOT advanced.
+ * PORTABILITY WARNING: this function depends on the
+ * continues representation of digits inside the character
+ * set (as in ASCII).
+ * rgerhards 2005-09-27
+ */
+rsRetVal parsInt(rsParsObj *pThis, int* pInt)
+{
+ unsigned char *pC;
+ int iVal;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pInt != NULL);
+
+ iVal = 0;
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* order of checks is important, else we might do
+ * mis-addressing! (off by one)
+ */
+ if(pThis->iCurrPos >= rsCStrLen(pThis->pCStr))
+ return RS_RET_NO_MORE_DATA;
+ if(!isdigit((int)*pC))
+ return RS_RET_NO_DIGIT;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && isdigit((int)*pC)) {
+ iVal = iVal * 10 + *pC - '0';
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ *pInt = iVal;
+
+ return RS_RET_OK;
+}
+
+/* Skip everything up to a specified character.
+ * Returns with ParsePointer set BEHIND this character.
+ * Returns RS_RET_OK if found, RS_RET_NOT_FOUND if not
+ * found. In that case, the ParsePointer is moved to the
+ * last character of the string.
+ * 2005-09-19 rgerhards
+ */
+rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c)
+{
+ register unsigned char *pC;
+ rsRetVal iRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr);
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ if(pC[pThis->iCurrPos] == c)
+ break;
+ ++pThis->iCurrPos;
+ }
+
+ /* delimiter found? */
+ if(pC[pThis->iCurrPos] == c) {
+ if(pThis->iCurrPos+1 < rsCStrLen(pThis->pCStr)) {
+ iRet = RS_RET_OK;
+ pThis->iCurrPos++; /* 'eat' delimiter */
+ } else {
+ iRet = RS_RET_FOUND_AT_STRING_END;
+ }
+ } else {
+ iRet = RS_RET_NOT_FOUND;
+ }
+
+ return iRet;
+}
+
+/* Skip whitespace. Often used to trim parsable entries.
+ * Returns with ParsePointer set to first non-whitespace
+ * character (or at end of string).
+ */
+rsRetVal parsSkipWhitespace(rsParsObj *pThis)
+{
+ register unsigned char *pC;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr);
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ if(!isspace((int)*(pC+pThis->iCurrPos)))
+ break;
+ ++pThis->iCurrPos;
+ }
+
+ return RS_RET_OK;
+}
+
+/* Parse string up to a delimiter.
+ *
+ * Input:
+ * cDelim - the delimiter
+ * The following two are for whitespace stripping,
+ * 0 means "no", 1 "yes"
+ * - bTrimLeading
+ * - bTrimTrailing
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string - must be freed by caller!
+ */
+rsRetVal parsDelimCStr(rsParsObj *pThis, rsCStrObj **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing)
+{
+ register unsigned char *pC;
+ rsCStrObj *pCStr;
+ rsRetVal iRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if((pCStr = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ if(bTrimLeading)
+ parsSkipWhitespace(pThis);
+
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && *pC != cDelim) {
+ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ if(*pC == cDelim) {
+ ++pThis->iCurrPos; /* eat delimiter */
+ }
+
+ /* We got the string, now take it and see if we need to
+ * remove anything at its end.
+ */
+ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+
+ if(bTrimTrailing) {
+ if((iRet = rsCStrTrimTrailingWhiteSpace(pCStr))
+ != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return iRet;
+ }
+ }
+
+ /* done! */
+ *ppCStr = pCStr;
+ return RS_RET_OK;
+}
+
+/* Parse a quoted string ("-some-data") from the given position.
+ * Leading whitespace before the first quote is skipped. During
+ * parsing, escape sequences are detected and converted:
+ * \\ - backslash character
+ * \" - quote character
+ * any other value \<somechar> is reserved for future use.
+ *
+ * After return, the parse pointer is paced after the trailing
+ * quote.
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string - must be freed by caller and
+ * does NOT include the quotes.
+ * rgerhards, 2005-09-19
+ */
+rsRetVal parsQuotedCStr(rsParsObj *pThis, rsCStrObj **ppCStr)
+{
+ register unsigned char *pC;
+ rsCStrObj *pCStr;
+ rsRetVal iRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if((iRet = parsSkipAfterChar(pThis, '"')) != RS_RET_OK)
+ return iRet;
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* OK, we most probably can obtain a value... */
+ if((pCStr = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ if(*pC == '"') {
+ break; /* we are done! */
+ } else if(*pC == '\\') {
+ ++pThis->iCurrPos;
+ ++pC;
+ if(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) {
+ /* in this case, we copy the escaped character
+ * to the output buffer (but do not rely on this,
+ * we might later introduce other things, like \007!
+ */
+ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+ }
+ } else { /* regular character */
+ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ if(*pC == '"') {
+ ++pThis->iCurrPos; /* 'eat' trailing quote */
+ } else {
+ /* error - improperly quoted string! */
+ rsCStrDestruct (pCStr);
+ return RS_RET_MISSING_TRAIL_QUOTE;
+ }
+
+ /* We got the string, let's finish it... */
+ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+
+ /* done! */
+ *ppCStr = pCStr;
+ return RS_RET_OK;
+}
+
+/*
+ * Parsing routine for IPv4, IPv6 and domain name wildcards.
+ *
+ * Parses string in the format <addr>[/bits] where
+ * addr can be a IPv4 address (e.g.: 127.0.0.1), IPv6 address (e.g.: [::1]),
+ * full hostname (e.g.: localhost.localdomain) or hostname wildcard
+ * (e.g.: *.localdomain).
+ */
+#ifdef SYSLOG_INET
+rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits)
+{
+ register unsigned char *pC;
+ unsigned char *pszIP;
+ uchar *pszTmp;
+ struct addrinfo hints, *res = NULL;
+ rsCStrObj *pCStr;
+ rsRetVal iRet;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pIP != NULL);
+ assert(pBits != NULL);
+
+ if((pCStr = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ parsSkipWhitespace(pThis);
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+
+ /* we parse everything until either '/', ',' or
+ * whitespace. Validity will be checked down below.
+ */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && *pC != '/' && *pC != ',' && !isspace((int)*pC)) {
+ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ /* We got the string, let's finish it... */
+ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) {
+ rsCStrDestruct (pCStr);
+ return(iRet);
+ }
+
+ /* now we have the string and must check/convert it to
+ * an NetAddr structure.
+ */
+ if((pszIP = rsCStrConvSzStrAndDestruct(pCStr)) == NULL)
+ return RS_RET_ERR;
+
+ *pIP = malloc (sizeof (struct NetAddr));
+ memset (*pIP, 0, sizeof (struct NetAddr));
+
+ if (*((char*)pszIP) == '[') {
+ pszTmp = (uchar*)strchr ((char*)pszIP, ']');
+ if (pszTmp == NULL) {
+ free (pszIP);
+ return RS_RET_INVALID_IP;
+ }
+ *pszTmp = '\0';
+
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
+
+ switch(getaddrinfo ((char*)pszIP+1, NULL, &hints, &res)) {
+ case 0:
+ (*pIP)->addr.NetAddr = malloc (res->ai_addrlen);
+ memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo (res);
+ break;
+ case EAI_NONAME:
+ F_SET((*pIP)->flags, ADDR_NAME|ADDR_PRI6);
+ (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP+1);
+ break;
+ default:
+ free (pszIP);
+ free (*pIP);
+ return RS_RET_ERR;
+ }
+
+ if(*pC == '/') {
+ /* mask bits follow, let's parse them! */
+ ++pThis->iCurrPos; /* eat slash */
+ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
+ free (pszIP);
+ free (*pIP);
+ return(iRet);
+ }
+ /* we need to refresh pointer (changed by parsInt()) */
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+ } else {
+ /* no slash, so we assume a single host (/128) */
+ *pBits = 128;
+ }
+ } else { /* now parse IPv4 */
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_INET;
+ hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST;
+
+ switch(getaddrinfo ((char*)pszIP, NULL, &hints, &res)) {
+ case 0:
+ (*pIP)->addr.NetAddr = malloc (res->ai_addrlen);
+ memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo (res);
+ break;
+ case EAI_NONAME:
+ F_SET((*pIP)->flags, ADDR_NAME);
+ (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP);
+ break;
+ default:
+ free (pszIP);
+ free (*pIP);
+ return RS_RET_ERR;
+ }
+
+ if(*pC == '/') {
+ /* mask bits follow, let's parse them! */
+ ++pThis->iCurrPos; /* eat slash */
+ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) {
+ free (pszIP);
+ free (*pIP);
+ return(iRet);
+ }
+ /* we need to refresh pointer (changed by parsInt()) */
+ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos;
+ } else {
+ /* no slash, so we assume a single host (/32) */
+ *pBits = 32;
+ }
+ }
+ free(pszIP); /* no longer needed */
+
+ /* skip to next processable character */
+ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)
+ && (*pC == ',' || isspace((int)*pC))) {
+ ++pThis->iCurrPos;
+ ++pC;
+ }
+
+ return RS_RET_OK;
+}
+#endif /* #ifdef SYSLOG_INET */
+
+
+/* tell if the parsepointer is at the end of the
+ * to-be-parsed string. Returns 1, if so, 0
+ * otherwise. rgerhards, 2005-09-27
+ */
+int parsIsAtEndOfParseString(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ return (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) ? 0 : 1;
+}
+
+
+/* return the position of the parse pointer
+ */
+int rsParsGetParsePointer(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+
+ if(pThis->iCurrPos < rsCStrLen(pThis->pCStr))
+ return pThis->iCurrPos;
+ else
+ return rsCStrLen(pThis->pCStr) - 1;
+}
+
+/* peek at the character at the parse pointer
+ * the caller must ensure that the parse pointer is not
+ * at the end of the parse buffer (e.g. by first calling
+ * parsIsAtEndOfParseString).
+ * rgerhards, 2005-09-27
+ */
+char parsPeekAtCharAtParsPtr(rsParsObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsPars);
+ assert(pThis->iCurrPos < rsCStrLen(pThis->pCStr));
+
+ return(*(pThis->pCStr->pBuf + pThis->iCurrPos));
+}
+
+/* return the current position inside the parse object.
+ * rgerhards, 2007-07-04
+ */
+int parsGetCurrentPosition(rsParsObj *pThis)
+{
+ return pThis->iCurrPos;
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/parse.h b/parse.h
new file mode 100644
index 0000000..b0dbd0f
--- /dev/null
+++ b/parse.h
@@ -0,0 +1,105 @@
+/* parsing routines for the counted string class. These
+ * routines provide generic parsing aid as well some fairly
+ * complex routines targeted toward specific needs.
+ *
+ * General information - read this:
+ * All routines work on a single CStr object, which must be supplied
+ * during construction. The parse class keeps an internal pointer of
+ * where the next parse operation is to start (you could also say
+ * this is where the last parse operation stopped).
+ *
+ * Each parse operation carried out by this package starts from the
+ * parse pointer, parses the caller-requested element (e.g. an
+ * integer or delemited string) and the update the parse pointer. If
+ * the caller tries to parse beyond the end of the original string,
+ * an error is returned. In general, all functions return a parsRet
+ * error code and all require the parseObj to be the first parameter.
+ * The to-be-parsed string provided to the parse object MUST NOT be
+ * freed or modified by the caller during the lifetime of the parse
+ * object. However, the caller must free it when it is no longer needed.
+ * Optinally, the parse object can be instructed to do that. All objects
+ * returned by the parse routines must be freed by the caller. For
+ * simpler data types (like integers), the caller must provide the
+ * necessary buffer space.
+ *
+ * begun 2005-09-09 rgerhards
+ */
+#ifndef _PARSE_H_INCLUDED__
+#define _PARSE_H_INCLUDED__ 1
+
+#include "stringbuf.h"
+
+/**
+ * The parse object
+ */
+struct rsParsObject
+{
+#ifndef NDEBUG
+ rsObjID OID; /**< object ID */
+#endif
+ rsCStrObj *pCStr; /**< pointer to the string object we are parsing */
+ int iCurrPos; /**< current parsing position (char offset) */
+};
+typedef struct rsParsObject rsParsObj;
+
+
+/* BEGIN "inline"-like functions */
+/* END "inline"-like functions */
+
+int rsParsGetParsePointer(rsParsObj *pThis);
+
+/**
+ * Construct a rsPars object.
+ */
+rsRetVal rsParsConstruct(rsParsObj **ppThis);
+rsRetVal rsParsAssignString(rsParsObj *pThis, rsCStrObj *pCStr);
+
+/* parse an integer. The parse pointer is advanced */
+rsRetVal parsInt(rsParsObj *pThis, int* pInt);
+
+/* Skip whitespace. Often used to trim parsable entries. */
+rsRetVal parsSkipWhitespace(rsParsObj *pThis);
+
+/* Parse string up to a delimiter.
+ *
+ * Input:
+ * cDelim - the delimiter
+ * The following two are for whitespace stripping,
+ * 0 means "no", 1 "yes"
+ * - bTrimLeading
+ * - bTrimTrailing
+ *
+ * Output:
+ * ppCStr Pointer to the parsed string
+ */
+rsRetVal parsDelimCStr(rsParsObj *pThis, rsCStrObj **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing);
+
+rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c);
+rsRetVal parsQuotedCStr(rsParsObj *pThis, rsCStrObj **ppCStr);
+rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz);
+rsRetVal rsParsDestruct(rsParsObj *pThis);
+int parsIsAtEndOfParseString(rsParsObj *pThis);
+int parsGetCurrentPosition(rsParsObj *pThis);
+char parsPeekAtCharAtParsPtr(rsParsObj *pThis);
+#ifdef SYSLOG_INET
+rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits);
+#endif
+
+#if 0 /* later! - but leave it in in case we need it some day... */
+/* Parse a property
+ * This is a complex parsing routine. It parses an property
+ * entry suitable for use in the property replacer. It is currently
+ * just an idea if this should be a parser function.
+ */
+parsRet parsProp(parseObj *pThis, ?? **pPropEtry);
+#endif
+
+#endif
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/pidfile.c b/pidfile.c
new file mode 100644
index 0000000..8ab6f82
--- /dev/null
+++ b/pidfile.c
@@ -0,0 +1,147 @@
+/*
+ pidfile.c - interact with pidfiles
+ Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA
+*/
+#include "config.h"
+
+
+/*
+ * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze
+ * First version (v0.2) released
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#ifdef __sun
+#include <fcntl.h>
+#endif
+
+/* read_pid
+ *
+ * Reads the specified pidfile and returns the read pid.
+ * 0 is returned if either there's no pidfile, it's empty
+ * or no pid can be read.
+ */
+int read_pid (char *pidfile)
+{
+ FILE *f;
+ int pid;
+
+ if (!(f=fopen(pidfile,"r")))
+ return 0;
+ fscanf(f,"%d", &pid);
+ fclose(f);
+ return pid;
+}
+
+/* check_pid
+ *
+ * Reads the pid using read_pid and looks up the pid in the process
+ * table (using /proc) to determine if the process already exists. If
+ * so 1 is returned, otherwise 0.
+ */
+int check_pid (char *pidfile)
+{
+ int pid = read_pid(pidfile);
+
+ /* Amazing ! _I_ am already holding the pid file... */
+ if ((!pid) || (pid == getpid ()))
+ return 0;
+
+ /*
+ * The 'standard' method of doing this is to try and do a 'fake' kill
+ * of the process. If an ESRCH error is returned the process cannot
+ * be found -- GW
+ */
+ /* But... errno is usually changed only on error.. */
+ if (kill(pid, 0) && errno == ESRCH)
+ return(0);
+
+ return pid;
+}
+
+/* write_pid
+ *
+ * Writes the pid to the specified file. If that fails 0 is
+ * returned, otherwise the pid.
+ */
+int write_pid (char *pidfile)
+{
+ FILE *f;
+ int fd;
+ int pid;
+
+ if ( ((fd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1)
+ || ((f = fdopen(fd, "r+")) == NULL) ) {
+ fprintf(stderr, "Can't open or create %s.\n", pidfile);
+ return 0;
+ }
+
+ /* It seems to be acceptable that we do not lock the pid file
+ * if we run under Solaris. In any case, it is highly unlikely
+ * that two instances try to access this file. And flock is really
+ * causing me grief on my initial steps on Solaris. Some time later,
+ * we might re-enable it (or use some alternate method).
+ * 2006-02-16 rgerhards
+ */
+
+#ifndef __sun
+ if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
+ fscanf(f, "%d", &pid);
+ fclose(f);
+ printf("Can't lock, lock is held by pid %d.\n", pid);
+ return 0;
+ }
+#endif
+
+ pid = getpid();
+ if (!fprintf(f,"%d\n", pid)) {
+ printf("Can't write pid , %s.\n", strerror(errno));
+ close(fd);
+ return 0;
+ }
+ fflush(f);
+
+#ifndef __sun
+ if (flock(fd, LOCK_UN) == -1) {
+ printf("Can't unlock pidfile %s, %s.\n", pidfile, strerror(errno));
+ close(fd);
+ return 0;
+ }
+#endif
+ close(fd);
+
+ return pid;
+}
+
+/* remove_pid
+ *
+ * Remove the the specified file. The result from unlink(2)
+ * is returned
+ */
+int remove_pid (char *pidfile)
+{
+ return unlink (pidfile);
+}
+
diff --git a/pidfile.h b/pidfile.h
new file mode 100644
index 0000000..19d19c1
--- /dev/null
+++ b/pidfile.h
@@ -0,0 +1,50 @@
+/*
+ pidfile.h - interact with pidfiles
+ Copyright (c) 1995 Martin Schulze <Martin.Schulze@Linux.DE>
+
+ This file is part of the sysklogd package, a kernel and system log daemon.
+
+ This program 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 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+*/
+
+/* read_pid
+ *
+ * Reads the specified pidfile and returns the read pid.
+ * 0 is returned if either there's no pidfile, it's empty
+ * or no pid can be read.
+ */
+int read_pid (char *pidfile);
+
+/* check_pid
+ *
+ * Reads the pid using read_pid and looks up the pid in the process
+ * table (using /proc) to determine if the process already exists. If
+ * so 1 is returned, otherwise 0.
+ */
+int check_pid (char *pidfile);
+
+/* write_pid
+ *
+ * Writes the pid to the specified file. If that fails 0 is
+ * returned, otherwise the pid.
+ */
+int write_pid (char *pidfile);
+
+/* remove_pid
+ *
+ * Remove the the specified file. The result from unlink(2)
+ * is returned
+ */
+int remove_pid (char *pidfile);
diff --git a/redhat/rsyslog.conf b/redhat/rsyslog.conf
new file mode 100644
index 0000000..9d34c80
--- /dev/null
+++ b/redhat/rsyslog.conf
@@ -0,0 +1,26 @@
+# Log all kernel messages to the console.
+# Logging much else clutters up the screen.
+#kern.* /dev/console
+
+# Log anything (except mail) of level info or higher.
+# Don't log private authentication messages!
+*.info;mail.none;authpriv.none;cron.none /var/log/messages
+
+# The authpriv file has restricted access.
+authpriv.* /var/log/secure
+
+# Log all the mail messages in one place.
+mail.* -/var/log/maillog
+
+
+# Log cron stuff
+cron.* /var/log/cron
+
+# Everybody gets emergency messages
+*.emerg *
+
+# Save news errors of level crit and higher in a special file.
+uucp,news.crit /var/log/spooler
+
+# Save boot messages also to boot.log
+local7.* /var/log/boot.log
diff --git a/redhat/rsyslog.init b/redhat/rsyslog.init
new file mode 100644
index 0000000..6b6f064
--- /dev/null
+++ b/redhat/rsyslog.init
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# rsyslog Starts rsyslogd/rklogd.
+#
+#
+# chkconfig: 2345 12 88
+# description: Syslog is the facility by which many daemons use to log \
+# messages to various system log files. It is a good idea to always \
+# run rsyslog.
+### BEGIN INIT INFO
+# Provides: $syslog
+# Short-Description: Enhanced system logging and kernel message trapping daemons
+# Description: Rsyslog is an enhanced multi-threaded syslogd supporting,
+# among others, MySQL, syslog/tcp, RFC 3195, permitted
+# sender lists, filtering on any message part, and fine
+# grain output format control.
+### END INIT INFO
+
+# Source function library.
+. /etc/init.d/functions
+
+RETVAL=0
+
+start() {
+ [ -x /sbin/rsyslogd ] || exit 5
+ [ -x /sbin/rklogd ] || exit 5
+
+ # Source config
+ if [ -f /etc/sysconfig/rsyslog ] ; then
+ . /etc/sysconfig/rsyslog
+ else
+ SYSLOGD_OPTIONS="-m 0"
+ KLOGD_OPTIONS="-2"
+ fi
+
+ umask 077
+
+ echo -n $"Starting system logger (rsyslog): "
+ daemon rsyslogd $SYSLOGD_OPTIONS
+ RETVAL=$?
+ echo
+ echo -n $"Starting kernel logger (rklogd): "
+ daemon rklogd $KLOGD_OPTIONS
+ echo
+ [ $RETVAL -eq 0 ] && touch /var/lock/subsys/rsyslog
+ return $RETVAL
+}
+stop() {
+ echo -n $"Shutting down kernel logger (rklogd): "
+ killproc rklogd
+ echo
+ echo -n $"Shutting down system logger (rsyslog): "
+ killproc rsyslogd
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/rsyslog
+ return $RETVAL
+}
+rhstatus() {
+ status rsyslogd
+ status rklogd
+}
+restart() {
+ stop
+ start
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ status)
+ rhstatus
+ ;;
+ restart|reload)
+ restart
+ ;;
+ condrestart)
+ [ -f /var/lock/subsys/rsyslog ] && restart || :
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart}"
+ exit 2
+esac
+
+exit $?
diff --git a/redhat/rsyslog.log b/redhat/rsyslog.log
new file mode 100644
index 0000000..e0593a2
--- /dev/null
+++ b/redhat/rsyslog.log
@@ -0,0 +1,6 @@
+/var/log/messages /var/log/secure /var/log/maillog /var/log/spooler /var/log/boot.log /var/log/cron {
+ sharedscripts
+ postrotate
+ /bin/kill -HUP `cat /var/run/rsyslogd.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
diff --git a/redhat/rsyslog.sysconfig b/redhat/rsyslog.sysconfig
new file mode 100644
index 0000000..ee9be79
--- /dev/null
+++ b/redhat/rsyslog.sysconfig
@@ -0,0 +1,12 @@
+# Options to syslogd
+# -m 0 disables 'MARK' messages.
+# -r enables logging from remote machines
+# -x disables DNS lookups on messages recieved with -r
+# See syslogd(8) for more details
+SYSLOGD_OPTIONS="-m 0"
+# Options to klogd
+# -2 prints all kernel oops messages twice; once for klogd to decode, and
+# once for processing with 'ksymoops'
+# -x disables all klogd processing of oops messages entirely
+# See klogd(8) for more details
+KLOGD_OPTIONS="-x"
diff --git a/rfc3195d.8 b/rfc3195d.8
new file mode 100644
index 0000000..2fef91b
--- /dev/null
+++ b/rfc3195d.8
@@ -0,0 +1,85 @@
+.\" Copyright 2005 Rainer Gerhards and Adiscon for the rsyslog modifications
+.\" Distributed under the GNU General Public License.
+.\"
+.TH RSYSLOGD 8 "03 July 2007" "Version 1.14.2 (devel)" "Linux System Administration"
+.SH NAME
+rfc3195d \- RFC 3195 listener
+.SH SYNOPSIS
+.B rfc3195d
+.RB [ " \-d " ]
+.RB [ " \-p"
+.IB socket
+]
+.RB [ " \-r"
+.IB port
+]
+.RB [ " \-v " ]
+.LP
+.SH DESCRIPTION
+.B Rfc3195d
+is a utility for receiving syslog messages via RFC 3195. Both
+RAW and COOKED profiles are supported (but COOKED only without
+relay-specific PATH elements).
+rfc3195d accepts messages via RFC 3195 and forwards them to
+the local domain socket specified in the -p option
+(/dev/log3195 by default). There, the messages can be picked up
+by the system syslogd. While rfc3195d can work with any syslogd,
+we highly recommend using
+.B rsyslogd,
+because it has special handling
+for the messages forwarded by rfc3195d. To enable message
+reception in
+.B rsyslogd,
+use the "-a :/dev/log3195" command line
+option (the colon in front of the socket name tells
+.B rsyslogd
+that the messages contain hostnames - this is vital to get the
+right sender name into your logs).
+
+.B Rfc3195d
+currently has very limited functionality. Most importantly,
+it does not allow to limit the senders it receives messages from.
+Documentation is also very sparse. The situation should improve over
+time as the rsyslog project is continously being enhanced.
+.LP
+.SH OPTIONS
+.TP
+.BI "\-p " "socket"
+The socket the received messages are to be sent to. If not specified,
+/dev/log3195 is used.
+.TP
+.BI "\-r " "port"
+The listen port to use. If not specified, IANA-assigned port 601 is used.
+.TP
+.B "\-d"
+Turns on debug mode. In it, rfc3195d spits out diagnostic information
+to stdout.
+.TP
+.B "\-v"
+Print version and exit.
+.SH SIGNALS
+.B Rfc3195d
+reacts to a set of signals.
+.TP
+.B SIGTERM
+.B Rfc3195d
+terminates.
+.TP
+.B SIGUSR1
+.B Rfc3195d
+terminates.
+.LP
+.SH SEE ALSO
+.BR rsyslog.conf (5),
+.BR rsyslogd (8)
+.LP
+.SH MORE INFORMATION
+Is available on the project home page at http://www.rsyslog.com
+.LP
+.SH COLLABORATORS
+Rfc3195d uses liblogging (http://www.liblogging.org) for RFC 3195
+protocol handling.
+.PD 0
+.TP
+Rainer Gerhards <rgerhards@adiscon.com>
+.zZ
diff --git a/rfc3195d.c b/rfc3195d.c
new file mode 100644
index 0000000..ee7891b
--- /dev/null
+++ b/rfc3195d.c
@@ -0,0 +1,275 @@
+/**
+ * rfc3195d.c
+ * This is an RFC 3195 listener. All data received is forwarded to
+ * local UNIX domain socket, where it can be picked up by a
+ * syslog daemon (like rsyslogd ;)).
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ *
+ * Copyright 2003-2005 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#ifndef FEATURE_RFC3195
+/* this is a trick: if RFC3195 is not to be supported, we just do an
+ * error message.
+ */
+int main()
+{
+ fprintf(stderr, "error: not compiled with FEATURE_RFC3195 - terminating.\n");
+ return(1);
+}
+#else
+#include <unistd.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include "rsyslog.h"
+#include "liblogging.h"
+#include "srAPI.h"
+#include "syslogmessage.h"
+
+/* configurable params! */
+static char* pPathLogname = "/dev/log3195";
+static char *PidFile;
+static int NoFork = 0;
+static int Debug = 0;
+static int listenPort = 601;
+
+/* we use a global API object below, because this listener is
+ * not very complex. As such, this hack should not harm anything.
+ * rgerhards, 2005-10-12
+ */
+static srAPIObj* pAPI;
+
+static int LogFile = -1; /* fd for log */
+static int connected; /* have done connect */
+static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */
+
+/* small usage info */
+static int usage()
+{
+ /* The following usage line is what we intend to have - it
+ * is commented out as a reminder. The one below is what we
+ * currently actually do...
+ fprintf(stderr, "usage: rfc3195d [-dv] [-i pidfile] [-n] [-p path]\n");
+ */
+ fprintf(stderr, "usage: rfc3195d [-dv] [-r port] [-p path]\n");
+ exit(1);
+}
+
+/* CLOSELOG -- close the system log
+ */
+static void closelog(void)
+{
+ close(LogFile);
+ LogFile = -1;
+ connected = 0;
+}
+
+/* OPENLOG -- open system log
+ */
+static void openlog()
+{
+ if (LogFile == -1) {
+ SyslogAddr.sa_family = AF_UNIX;
+ strncpy(SyslogAddr.sa_data, pPathLogname,
+ sizeof(SyslogAddr.sa_data));
+ LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(LogFile < 0)
+ printf("error opening '%s': %s\n",
+ pPathLogname, strerror(errno));
+ }
+ if (LogFile != -1 && !connected &&
+ connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+
+ strlen(SyslogAddr.sa_data)) != -1)
+ connected = 1;
+ else
+ printf("error connecting '%s': %s\n",
+ pPathLogname, strerror(errno));
+}
+
+
+/* This method is called when a message has been fully received.
+ * It passes the received message to the specified unix domain
+ * socket. Please note that this callback is synchronous, thus
+ * liblogging will be on hold until it returns. This is important
+ * to note because in an error case we might stay in this code
+ * for an extended amount of time. So far, we think this is the
+ * best solution, but real-world experience might tell us a
+ * different truth ;)
+ * rgerhards 2005-10-12
+ */
+void OnReceive(srAPIObj* pAPI, srSLMGObj* pSLMG)
+{
+ unsigned char *pszRawMsg;
+ int iRetries; /* number of retries connecting to log socket */
+ int iSleep;
+ int iWriteOffset;
+ ssize_t nToWrite;
+ ssize_t nWritten;
+
+ srSLMGGetRawMSG(pSLMG, &pszRawMsg);
+
+ /* we need to loop writing the message. At least in
+ * theory, a single write might not send all data to the
+ * syslogd. So we need to continue until everything is written.
+ * Also, we need to check if there are any socket erros, in
+ * which case we reconect. We will re-try indefinitely, if this
+ * is not acceptable, you need to change the code.
+ * rgerhards 2005-10-12
+ */
+ iRetries = 0;
+ nToWrite = strlen(pszRawMsg);
+ iWriteOffset = 0;
+ while(nToWrite != 0) {
+ if(LogFile < 0 || !connected)
+ openlog();
+ if(LogFile < 0 || !connected) {
+ /* still not connected, retry */
+ if(iRetries > 0) {
+ iSleep = (iRetries < 30) ? iRetries : 30;
+ /* we sleep a little to prevent a thight loop */
+ if(Debug)
+ printf("multiple retries connecting to log socket"
+ " - doing sleep(%d)\n", iSleep);
+ sleep(iSleep);
+ }
+ ++iRetries;
+ } else {
+ nWritten = write(LogFile, pszRawMsg, strlen(pszRawMsg));
+ if(nWritten < 0) {
+ /* error, recover! */
+ printf("error writing to domain socket: %s\r\n", strerror(errno));
+ closelog();
+ } else {
+ /* prepare for (potential) next write */
+ nToWrite -= nWritten;
+ iWriteOffset += nWritten;
+ }
+ }
+ }
+
+ if(Debug) {
+ static int largest = 0;
+ int sz = strlen(pszRawMsg);
+ if(sz > largest)
+ largest = sz;
+ printf("Msg(%d/%d):%s\n\n", largest, sz, pszRawMsg);
+ }
+}
+
+
+/* As we are single-threaded in this example, we need
+ * one way to shut down the listener running on this
+ * single thread. We use SIG_INT to do so - it effectively
+ * provides a short-lived second thread ;-)
+ */
+void doShutdown(int i)
+{
+ printf("Shutting down rfc3195d. Be patient, this can take up to 30 seconds...\n");
+ srAPIShutdownListener(pAPI);
+}
+
+
+/* on the the real program ;) */
+int main(int argc, char* argv[])
+{
+ srRetVal iRet;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "di:np:r:v")) != EOF)
+ switch((char)ch) {
+ case 'd': /* debug */
+ Debug = 1;
+ break;
+ case 'i': /* pid file name */
+ PidFile = optarg;
+ break;
+ case 'n': /* don't fork */
+ NoFork = 1;
+ break;
+ case 'p': /* path to regular log socket */
+ pPathLogname = optarg;
+ break;
+ case 'r': /* listen port */
+ listenPort = atoi(optarg);
+ if(listenPort < 1 || listenPort > 65535) {
+ printf("Error: invalid listen port '%s', using 601 instead\n",
+ optarg);
+ listenPort = 601;
+ }
+ break;
+ case 'v':
+ printf("rfc3195d %s.%s (using liblogging version %d.%d.%d).\n",
+ VERSION, PATCHLEVEL,
+ LIBLOGGING_VERSION_MAJOR, LIBLOGGING_VERSION_MINOR,
+ LIBLOGGING_VERSION_SUBMINOR);
+ printf("See http://www.rsyslog.com for more information.\n");
+ exit(0);
+ case '?':
+ default:
+ usage();
+ }
+ if ((argc -= optind))
+ usage();
+
+ if(!Debug)
+ signal(SIGINT, SIG_IGN);
+ signal(SIGUSR1, doShutdown);
+ signal(SIGTERM, doShutdown);
+
+ if((pAPI = srAPIInitLib()) == NULL)
+ {
+ printf("Error initializing liblogging - aborting!\n");
+ exit(1);
+ }
+
+ if((iRet = srAPISetOption(pAPI, srOPTION_BEEP_LISTENPORT, listenPort)) != SR_RET_OK)
+ {
+ printf("Error %d setting listen port - aborting\n", iRet);
+ exit(100);
+ }
+
+ if((iRet = srAPISetupListener(pAPI, OnReceive)) != SR_RET_OK)
+ {
+ printf("Error %d setting up listener - aborting\n", iRet);
+ exit(101);
+ }
+
+ /* now move the listener to running state. Control will only
+ * return after SIGUSR1.
+ */
+ if((iRet = srAPIRunListener(pAPI)) != SR_RET_OK)
+ {
+ printf("Error %d running the listener - aborting\n", iRet);
+ exit(102);
+ }
+
+ /** control will reach this point after shutdown */
+
+ srAPIExitLib(pAPI);
+ return 0;
+}
+#endif /* #ifndef FEATURE_RFC3195 - main wrapper */
+
+/*
+ * vi:set ai:
+ */
diff --git a/rklogd.8 b/rklogd.8
new file mode 100644
index 0000000..0bc7d76
--- /dev/null
+++ b/rklogd.8
@@ -0,0 +1,441 @@
+.\" Copyright 1994 Dr. Greg Wettstein, Enjellic Systems Development.
+.\" May be distributed under the GNU General Public License
+.\" Sun Jul 30 01:35:55 MET: Martin Schulze: Updates
+.\" Sun Nov 19 23:22:21 MET: Martin Schulze: Updates
+.\" Mon Aug 19 09:42:08 CDT 1996: Dr. G.W. Wettstein: Updates
+.\"
+.TH RKLOGD 8 "03 JULY 2007" "Version 1.14.2 (devel)" "Linux System Administration"
+.SH NAME
+rklogd \- Kernel Log Daemon
+.LP
+.SH SYNOPSIS
+.B rklogd
+.RB [ " \-c "
+.I n
+]
+.RB [ " \-d " ]
+.RB [ " \-f "
+.I fname
+]
+.RB [ " \-iI " ]
+.RB [ " \-n " ]
+.RB [ " \-o " ]
+.RB [ " \-p " ]
+.RB [ " \-s " ]
+.RB [ " \-k "
+.I fname
+]
+.RB [ " \-v " ]
+.RB [ " \-x " ]
+.RB [ " \-2 " ]
+.LP
+.SH DESCRIPTION
+.B rklogd
+is a system daemon which intercepts and logs Linux kernel
+messages.
+.LP
+.SH OPTIONS
+.TP
+.BI "\-c " n
+Sets the default log level of console messages to \fIn\fR.
+.TP
+.B "\-d"
+Enable debugging mode. This will generate \fBLOTS\fR of output to
+stderr.
+.TP
+.BI "\-f " file
+Log messages to the specified filename rather than to the syslog facility.
+.TP
+.BI "\-i \-I"
+Signal the currently executing rklogd daemon. Both of these switches control
+the loading/reloading of symbol information. The \-i switch signals the
+daemon to reload the kernel module symbols. The \-I switch signals for a
+reload of both the static kernel symbols and the kernel module symbols.
+.TP
+.B "\-n"
+Avoid auto-backgrounding. This is needed especially if the
+.B rklogd
+is started and controlled by
+.BR init (8).
+.TP
+.B "-o"
+Execute in 'one\-shot' mode. This causes \fBrklogd\fP to read and log
+all the messages that are found in the kernel message buffers. After
+a single read and log cycle the daemon exits.
+.TP
+.B "-p"
+Enable paranoia. This option controls when rklogd loads kernel module symbol
+information. Setting this switch causes rklogd to load the kernel module
+symbol information whenever an Oops string is detected in the kernel message
+stream.
+.TP
+.B "-s"
+Force \fBrklogd\fP to use the system call interface to the kernel message
+buffers.
+.TP
+.BI "\-k " file
+Use the specified file as the source of kernel symbol information.
+.TP
+.B "\-v"
+Print version and exit.
+.TP
+.B "\-x"
+Omits EIP translation and therefore doesn't read the System.map file.
+.TP
+.B "\-2"
+When symbols are expanded, print the line twice. Once with addresses
+converted to symbols, once with the raw text. This allows external
+programs such as ksymoops do their own processing on the original
+data.
+.LP
+.SH OVERVIEW
+The functionality of rklogd has been typically incorporated into other
+versions of syslogd but this seems to be a poor place for it. In the
+modern Linux kernel a number of kernel messaging issues such as
+sourcing, prioritization and resolution of kernel addresses must be
+addressed. Incorporating kernel logging into a separate process
+offers a cleaner separation of services.
+
+In Linux there are two potential sources of kernel log information: the
+.I /proc
+file system and the syscall (sys_syslog) interface, although
+ultimately they are one and the same. Klogd is designed to choose
+whichever source of information is the most appropriate. It does this
+by first checking for the presence of a mounted
+.I /proc
+file system. If this is found the
+.I /proc/kmsg
+file is used as the source of kernel log
+information. If the proc file system is not mounted
+.B rklogd
+uses a
+system call to obtain kernel messages. The command line switch
+.RB ( "\-s" )
+can be used to force rklogd to use the system call interface as its
+messaging source.
+
+If kernel messages are directed through the
+.BR syslogd " daemon the " rklogd
+daemon, as of version 1.1, has the ability to properly prioritize
+kernel messages. Prioritization of the kernel messages was added to it
+at approximately version 0.99pl13 of the kernel. The raw kernel messages
+are of the form:
+.IP
+\<[0\-7]\>Something said by the kernel.
+.PP
+The priority of the kernel message is encoded as a single numeric
+digit enclosed inside the <> pair. The definitions of these values is
+given in the kernel include file kernel.h. When a message is received
+from the kernel the rklogd daemon reads this priority level and assigns
+the appropriate priority level to the syslog message. If file output
+(\fB-f\fR) is used the prioritization sequence is left pre\-pended to the
+kernel message.
+
+The
+.B rklogd
+daemon also allows the ability to alter the presentation of
+kernel messages to the system console. Consequent with the
+prioritization of kernel messages was the inclusion of default
+messaging levels for the kernel. In a stock kernel the the default
+console log level is set to 7. Any messages with a priority level
+numerically lower than 7 (higher priority) appear on the console.
+
+Messages of priority level 7 are considered to be 'debug' messages and
+will thus not appear on the console. Many administrators,
+particularly in a multi\-user environment, prefer that all kernel
+messages be handled by rklogd and either directed to a file or to
+the syslogd daemon. This prevents 'nuisance' messages such as line
+printer out of paper or disk change detected from cluttering the
+console.
+
+When
+.B \-c
+is given on the commandline the
+.B rklogd
+daemon will execute a system call to inhibit all kernel messages from
+being displayed on the console. Former versions always issued this
+system call and defaulted to all kernel messages except for panics.
+This is handled differently nowardays so
+.B rklogd
+doesn't need to set this value anymore. The
+argument given to the \fB\-c\fR switch specifies the priority level of
+messages which will be directed to the console. Note that messages of
+a priority value LOWER than the indicated number will be directed to
+the console.
+.IP
+For example, to have the kernel display all messages with a
+priority level of 3
+.BR "" ( KERN_ERR )
+or more severe the following
+command would be executed:
+.IP
+.nf
+ rklogd \-c 4
+.fi
+.PP
+The definitions of the numeric values for kernel messages are given in
+the file
+.IR kernel.h " which can be found in the " /usr/include/linux
+directory if the kernel sources are installed. These values parallel
+the syslog priority values which are defined in the file
+.IR syslog.h " found in the " /usr/include/sys " sub\-directory."
+
+The rklogd daemon can also be used in a 'one\-shot' mode for reading the
+kernel message buffers. One shot mode is selected by specifying the
+\fB\-o\fR switch on the command line. Output will be directed to either the
+syslogd daemon or to an alternate file specified by the \fB-f\fR switch.
+.IP
+For example, to read all the kernel messages after a system
+boot and record them in a file called krnl.msg the following
+command would be given.
+.IP
+.nf
+ rklogd -o -f ./krnl.msg
+.fi
+.PP
+.SH KERNEL ADDRESS RESOLUTION
+If the kernel detects an internal error condition a general protection
+fault will be triggered. As part of the GPF handling procedure the
+kernel prints out a status report indicating the state of the
+processor at the time of the fault. Included in this display are the
+contents of the microprocessor's registers, the contents of the kernel
+stack and a tracing of what functions were being executed at the time
+of the fault.
+
+This information is
+.B EXTREMELY IMPORTANT
+in determining what caused the internal error condition. The
+difficulty comes when a kernel developer attempts to analyze this
+information. The raw numeric information present in the protection
+fault printout is of very little use to the developers. This is due
+to the fact that kernels are not identical and the addresses of
+variable locations or functions will not be the same in all kernels.
+In order to correctly diagnose the cause of failure a kernel developer
+needs to know what specific kernel functions or variable locations
+were involved in the error.
+
+As part of the kernel compilation process a listing is created which
+specified the address locations of important variables and function in
+the kernel being compiled. This listing is saved in a file called
+System.map in the top of the kernel directory source tree. Using this
+listing a kernel developer can determine exactly what the kernel was
+doing when the error condition occurred.
+
+The process of resolving the numeric addresses from the protection
+fault printout can be done manually or by using the
+.B ksymoops
+program which is included in the kernel sources.
+
+As a convenience
+.B rklogd
+will attempt to resolve kernel numeric addresses to their symbolic
+forms if a kernel symbol table is available at execution time. If you
+require the original address of the symbol, use the
+.B -2
+switch to preserve the numeric address. A
+symbol table may be specified by using the \fB\-k\fR switch on the
+command line. If a symbol file is not explicitly specified the
+following filenames will be tried:
+
+.nf
+.I /boot/System.map
+.I /System.map
+.I /usr/src/linux/System.map
+.fi
+
+Version information is supplied in the system maps as of kernel
+1.3.43. This version information is used to direct an intelligent
+search of the list of symbol tables. This feature is useful since it
+provides support for both production and experimental kernels.
+
+For example a production kernel may have its map file stored in
+/boot/System.map. If an experimental or test kernel is compiled with
+the sources in the 'standard' location of /usr/src/linux the system
+map will be found in /usr/src/linux/System.map. When rklogd starts
+under the experimental kernel the map in /boot/System.map will be
+bypassed in favor of the map in /usr/src/linux/System.map.
+
+Modern kernels as of 1.3.43 properly format important kernel addresses
+so that they will be recognized and translated by rklogd. Earlier
+kernels require a source code patch be applied to the kernel sources.
+This patch is supplied with the sysrklogd sources.
+
+The process of analyzing kernel protections faults works very well
+with a static kernel. Additional difficulties are encountered when
+attempting to diagnose errors which occur in loadable kernel modules.
+Loadable kernel modules are used to implement kernel functionality in
+a form which can be loaded or unloaded at will. The use of loadable
+modules is useful from a debugging standpoint and can also be useful
+in decreasing the amount of memory required by a kernel.
+
+The difficulty with diagnosing errors in loadable modules is due to
+the dynamic nature of the kernel modules. When a module is loaded the
+kernel will allocate memory to hold the module, when the module is
+unloaded this memory will be returned back to the kernel. This
+dynamic memory allocation makes it impossible to produce a map file
+which details the addresses of the variable and functions in a kernel
+loadable module. Without this location map it is not possible for a
+kernel developer to determine what went wrong if a protection fault
+involves a kernel module.
+
+.B rklogd
+has support for dealing with the problem of diagnosing protection
+faults in kernel loadable modules. At program start time or in
+response to a signal the daemon will interrogate the kernel for a
+listing of all modules loaded and the addresses in memory they are
+loaded at. Individual modules can also register the locations of
+important functions when the module is loaded. The addresses of these
+exported symbols are also determined during this interrogation
+process.
+
+When a protection fault occurs an attempt will be made to resolve
+kernel addresses from the static symbol table. If this fails the
+symbols from the currently loaded modules are examined in an attempt
+to resolve the addresses. At the very minimum this allows rklogd to
+indicate which loadable module was responsible for generating the
+protection fault. Additional information may be available if the
+module developer chose to export symbol information from the module.
+
+Proper and accurate resolution of addresses in kernel modules requires
+that
+.B rklogd
+be informed whenever the kernel module status changes. The
+.B \-i
+and
+.B \-I
+switches can be used to signal the currently executing daemon that
+symbol information be reloaded. Of most importance to proper
+resolution of module symbols is the
+.B \-i
+switch. Each time a kernel module is loaded or removed from the
+kernel the following command should be executed:
+
+.nf
+.I rklogd \-i
+.fi
+
+The
+.B \-p
+switch can also be used to insure that module symbol information is up
+to date. This switch instructs
+.B rklogd
+to reload the module symbol information whenever a protection fault
+is detected. Caution should be used before invoking the program in
+\'paranoid\' mode. The stability of the kernel and the operating
+environment is always under question when a protection fault occurs.
+Since the rklogd daemon must execute system calls in order to read the
+module symbol information there is the possibility that the system may
+be too unstable to capture useful information. A much better policy
+is to insure that rklogd is updated whenever a module is loaded or
+unloaded. Having uptodate symbol information loaded increases the
+probability of properly resolving a protection fault if it should occur.
+
+Included in the sysrklogd source distribution is a patch to the
+modules-2.0.0 package which allows the
+.B insmod,
+.B rmmod
+and
+.B modprobe
+utilities to automatically signal
+.B rklogd
+whenever a module is inserted or removed from the kernel. Using this
+patch will insure that the symbol information maintained in rklogd is
+always consistent with the current kernel state.
+.PP
+.SH SIGNAL HANDLING
+The
+.B rklogd
+will respond to eight signals:
+.BR SIGHUP ", " SIGINT ", " SIGKILL ", " SIGTERM ", " SIGTSTP ", "
+.BR SIGUSR1 ", "SIGUSR2 " and " SIGCONT ". The"
+.BR SIGINT ", " SIGKILL ", " SIGTERM " and " SIGHUP
+signals will cause the daemon to close its kernel log sources and
+terminate gracefully.
+
+The
+.BR SIGTSTP " and " SIGCONT
+signals are used to start and stop kernel logging. Upon receipt of a
+.B SIGTSTP
+signal the daemon will close its
+log sources and spin in an idle loop. Subsequent receipt of a
+.B SIGCONT
+signal will cause the daemon to go through its initialization sequence
+and re-choose an input source. Using
+.BR SIGSTOP " and " SIGCONT
+in combination the kernel log input can be re-chosen without stopping and
+restarting the daemon. For example if the \fI/proc\fR file system is to be
+un-mounted the following command sequence should be used:
+.PP
+.PD 0
+.TP
+ # kill -TSTP pid
+.TP
+ # umount /proc
+.TP
+ # kill -CONT pid
+.PD
+.PP
+Notations will be made in the system logs with
+.B LOG_INFO
+priority
+documenting the start/stop of logging.
+
+The
+.BR SIGUSR1 " and " SIGUSR2
+signals are used to initiate loading/reloading of kernel symbol information.
+Receipt of the
+.B SIGUSR1
+signal will cause the kernel module symbols to be reloaded. Signaling the
+daemon with
+.B SIGUSR2
+will cause both the static kernel symbols and the kernel module symbols to
+be reloaded.
+
+Provided that the System.map file is placed in an appropriate location the
+signal of generally greatest usefulness is the
+.B SIGUSR1
+signal. This signal is designed to be used to signal the daemon when kernel
+modules are loaded/unloaded. Sending this signal to the daemon after a
+kernel module state change will insure that proper resolution of symbols will
+occur if a protection fault occurs in the address space occupied by a kernel
+module.
+.LP
+.SH FILES
+.PD 0
+.TP
+.I /proc/kmsg
+One Source for kernel messages
+.B rklogd
+.TP
+.I /var/run/rklogd.pid
+The file containing the process id of
+.B rklogd
+.TP
+.I /boot/System.map, /System.map, /usr/src/linux/System.map
+Default locations for kernel system maps.
+.PD
+.SH BUGS
+Probably numerous. Well formed context diffs appreciated.
+.LP
+.SH AUTHOR
+The
+.B rklogd
+was originally written by Steve Lord (lord@cray.com), Greg Wettstein
+made major improvements.
+
+.PD 0
+.TP
+Dr. Greg Wettstein (greg@wind.enjellic.com)
+.TP
+Enjellic Systems Development
+.PD
+.PP
+.PD 0
+.TP
+Oncology Research Divsion Computing Facility
+.TP
+Roger Maris Cancer Center
+.TP
+Fargo, ND 58122
+.PD
+.zZ
diff --git a/rsyslog.conf.5 b/rsyslog.conf.5
new file mode 100644
index 0000000..731580c
--- /dev/null
+++ b/rsyslog.conf.5
@@ -0,0 +1,62 @@
+.\" rsyslog.conf - rsyslogd(8) configuration file
+.\" Copyright 2003-2005 Rainer Gerhards and Adiscon GmbH.
+.\"
+.\" This file is part of the rsyslog package, an enhanced system log daemon.
+.\"
+.\" This program 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 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program 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 this program; if not, write to the Free Software
+.\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+.\"
+.TH RSYSLOG.CONF 5 "04 October 2006" "Version 1.12.3" "Linux System Administration"
+.SH NAME
+rsyslog.conf \- rsyslogd(8) configuration file
+.SH DESCRIPTION
+The
+.I rsyslog.conf
+file is the main configuration file for the
+.BR rsyslogd (8)
+which logs system messages on *nix systems. This file specifies rules
+for logging. For special features see the
+.BR rsyslogd (8)
+manpage.
+
+While rsyslogd contains enhancements over standard syslogd, efforts
+have been made to keep the configuration file as compatible as
+possible. While, for obvious reasons, enhanced features require
+a different config file syntax, rsyslogd should be able to work with
+a standard syslog.conf file. This is especially useful while you
+are migrating from syslogd to rsyslogd.
+
+This man page is now a stub. Full documentation can be found in
+the doc folder of the rsyslog distribution. If in doubt, you
+can also view it online at
+
+ http://www.rsyslog.com/doc
+
+.SH FILES
+.PD 0
+.TP
+.I /etc/rsyslog.conf
+Configuration file for
+.B rsyslogd
+
+.SH SEE ALSO
+.BR syslogd (8),
+.BR logger (1),
+.BR syslog (3)
+
+.SH AUTHORS
+The
+.B rsyslogd
+is taken from sysklogd sources, which have been heavily modified
+by Rainer Gerhards (rgerhards@adiscon.com) and others.
diff --git a/rsyslog.h b/rsyslog.h
new file mode 100644
index 0000000..bc70581
--- /dev/null
+++ b/rsyslog.h
@@ -0,0 +1,147 @@
+/* Header file with global definitions for the whole
+ * rsyslog project (including all subprojects like
+ * rfc3195d).
+ * Begun 2005-09-15 RGerhards
+*/
+#ifndef INCLUDED_RSYSLOG_H
+#define INCLUDED_RSYSLOG_H
+
+/* ############################################################# *
+ * # Config Settings # *
+ * ############################################################# */
+#define RS_STRINGBUF_ALLOC_INCREMENT 128
+
+/* ############################################################# *
+ * # End Config Settings # *
+ * ############################################################# */
+
+#ifndef NOLARGEFILE
+# undef _LARGEFILE_SOURCE
+# undef _LARGEFILE64_SOURCE
+# undef _FILE_OFFSET_BITS
+# define _LARGEFILE_SOURCE
+# define _LARGEFILE64_SOURCE
+# define _FILE_OFFSET_BITS 64
+#endif
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+/* The error codes below are orginally "borrowed" from
+ * liblogging. As such, we reserve values up to -2999
+ * just in case we need to borrow something more ;)
+*/
+enum rsRetVal_ /** return value. All methods return this if not specified otherwise */
+{
+ RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */
+ RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */
+ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50,/**< the caller provided a buffer, but the called function sees the size of this buffer is too small - operation not carried out */
+ RS_RET_TRUE = -1,
+ RS_RET_FALSE = -2,
+ RS_RET_ERR = -3000, /**< generic failure */
+ RS_TRUNCAT_TOO_LARGE = -3001, /**< truncation operation where too many chars should be truncated */
+ RS_RET_FOUND_AT_STRING_END = -3002, /**< some value found, but at the last pos of string */
+ RS_RET_NOT_FOUND = -3003, /**< some requested value not found */
+ RS_RET_MISSING_TRAIL_QUOTE = -3004, /**< an expected trailing quote is missing */
+ RS_RET_NO_DIGIT = -3005, /**< an digit was expected, but none found (mostly parsing) */
+ RS_RET_NO_MORE_DATA = -3006, /**< insufficient data, e.g. end of string during parsing */
+ RS_RET_INVALID_IP = -3007, /**< invalid ip found where valid was expected */
+ RS_RET_OBJ_CREATION_FAILED = - 3008, /**< the creation of an object failed (no details available) */
+ RS_RET_PARAM_ERROR = -1000, /**< invalid parameter in call to function */
+ RS_RET_MISSING_INTERFACE = -1001,/**< interface version mismatch, required missing */
+ /* return states for config file processing */
+ RS_RET_NONE = -2000, /**< some value is not available - not necessarily an error */
+ RS_RET_CONFLINE_UNPROCESSED = -2001,/**< config line was not processed, pass to other module */
+ RS_RET_DISCARDMSG = -2002, /**< discard message (no error state, processing request!) */
+ RS_RET_INCOMPATIBLE = -2003, /**< function not compatible with requested feature */
+ RS_RET_NOENTRY = -2004, /**< do not create an entry for (whatever) - not necessary an error */
+ RS_RET_NO_SQL_STRING = -2005, /**< string is not suitable for use as SQL */
+ RS_RET_DISABLE_ACTION = -2006, /**< action requests that it be disabled */
+ RS_RET_SUSPENDED = -2007, /**< something was suspended, not neccesarily an error */
+ RS_RET_RQD_TPLOPT_MISSING = -2008,/**< a required template option is missing */
+ RS_RET_INVALID_VALUE = -2009,/**< some value is invalid (e.g. user-supplied data) */
+ RS_RET_INVALID_INT = -2010,/**< invalid integer */
+ RS_RET_INVALID_CMD = -2011,/**< invalid command */
+ RS_RET_VAL_OUT_OF_RANGE = -2012, /**< value out of range */
+ RS_RET_FOPEN_FAILURE = -2013, /**< failure during fopen, for example file not found - see errno */
+ RS_RET_END_OF_LINKEDLIST = -2014, /**< end of linked list, not an error, but a status */
+ RS_RET_CHAIN_NOT_PERMITTED = -2015, /**< chaining (e.g. of config command handlers) not permitted */
+ RS_RET_INVALID_PARAMS = -2016,/**< supplied parameters are invalid */
+ RS_RET_EMPTY_LIST = -2017, /**< linked list is empty */
+ RS_RET_FINISHED = -2018, /**< some opertion is finished, not an error state */
+ RS_RET_OK = 0 /**< operation successful */
+};
+typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
+
+/* some helpful macros to work with srRetVals.
+ * Be sure to call the to-be-returned variable always "iRet" and
+ * the function finalizer always "finalize_it".
+ */
+#define CHKiRet(code) if((iRet = code) != RS_RET_OK) goto finalize_it
+/* macro below is to be used if we need our own handling, eg for cleanup */
+#define CHKiRet_Hdlr(code) if((iRet = code) != RS_RET_OK)
+#define DEFiRet rsRetVal iRet = RS_RET_OK
+#define ABORT_FINALIZE(errCode) \
+ iRet = errCode;\
+ goto finalize_it;
+
+/** Object ID. These are for internal checking. Each
+ * object is assigned a specific ID. This is contained in
+ * all Object structs (just like C++ RTTI). We can use
+ * this field to see if we have been passed a correct ID.
+ * Other than that, there is currently no other use for
+ * the object id.
+ */
+enum rsObjectID
+{
+ OIDrsFreed = -1, /**< assigned, when an object is freed. If this
+ * is seen during a method call, this is an
+ * invalid object pointer!
+ */
+ OIDrsInvalid = 0, /**< value created by calloc(), so do not use ;) */
+ /* The 0xEFCD is a debug aid. It helps us find object IDs in memory
+ * dumps (on X86, this is CDEF in the dump ;)
+ * If you are on an embedded device and you would like to save space
+ * make them 1 byte only.
+ */
+ OIDrsCStr = 0xEFCD0001,
+ OIDrsPars = 0xEFCD0002
+};
+typedef enum rsObjectID rsObjID;
+
+/* support to set object types */
+#ifdef NDEBUG
+#define rsSETOBJTYPE(pObj, type)
+#define rsCHECKVALIDOBJECT(x, type)
+#else
+#define rsSETOBJTYPE(pObj, type) pObj->OID = type;
+#define rsCHECKVALIDOBJECT(x, type) {assert(x != NULL); assert(x->OID == type);}
+#endif
+
+/**
+ * This macro should be used to free objects.
+ * It aids in interpreting dumps during debugging.
+ */
+#ifdef NDEBUG
+#define RSFREEOBJ(x) free(x)
+#else
+#define RSFREEOBJ(x) {(x)->OID = OIDrsFreed; free(x);}
+#endif
+
+/* get rid of the unhandy "unsigned char"
+ */
+typedef unsigned char uchar;
+
+/* for the time being, we do our own portability handling here. It
+ * looks like autotools either does not yet support checks for it, or
+ * I wasn't smart enough to find them ;) rgerhards, 2007-07-18
+ */
+#ifndef __GNUC__
+# define __attribute__(x) /*NOTHING*/
+#endif
+
+#endif /* multi-include protection */
+/*
+ * vi:set ai:
+ */
diff --git a/rsyslogd.8 b/rsyslogd.8
new file mode 100644
index 0000000..2ae44f6
--- /dev/null
+++ b/rsyslogd.8
@@ -0,0 +1,586 @@
+.\" Copyright 2004-2005 Rainer Gerhards and Adiscon for the rsyslog modifications
+.\" May be distributed under the GNU General Public License
+.\"
+.TH RSYSLOGD 8 "17 July 2007" "Version 1.16.1 (devel)" "Linux System Administration"
+.SH NAME
+rsyslogd \- reliable and extended syslogd
+.SH SYNOPSIS
+.B rsyslogd
+.RB [ " \-4 " ]
+.RB [ " \-6 " ]
+.RB [ " \-A " ]
+.RB [ " \-a "
+.I socket
+]
+.RB [ " \-d " ]
+.RB [ " \-e " ]
+.br
+.RB [ " \-f "
+.I config file
+]
+.RB [ " \-h " ]
+.RB [ " \-i "
+.I pid file
+]
+.RB [ " \-l "
+.I hostlist
+]
+.br
+.RB [ " \-m "
+.I interval
+]
+.RB [ " \-n " ]
+.RB [ " \-o " ]
+.RB [ " \-p"
+.IB socket
+]
+.br
+.RB [ " \-r "
+.I [port]
+]
+.RB [ " \-s "
+.I domainlist
+]
+.RB [ " \-t "
+.I port,max-nbr-of-sessions
+]
+.br
+.RB [ " \-v " ]
+.RB [ " \-w " ]
+.RB [ " \-x " ]
+.LP
+.SH DESCRIPTION
+.B Rsyslogd
+is a system utility providing support for message logging.
+Support of both internet and
+unix domain sockets enables this utility to support both local
+and remote logging (via UDP and TCP).
+
+.BR Rsyslogd (8)
+is derived from the sysklogd package which in turn is derived from the
+stock BSD sources.
+
+.B Rsyslogd
+provides a kind of logging that many modern programs use. Every logged
+message contains at least a time and a hostname field, normally a
+program name field, too, but that depends on how trusty the logging
+program is. The rsyslog package supports free definition of output formats
+via templates. It also supports precise timestamps and writing directly
+to MySQL databases. If the database option is used, tools like phpLogCon can
+be used to view the log data.
+
+While the
+.B rsyslogd
+sources have been heavily modified a couple of notes
+are in order. First of all there has been a systematic attempt to
+insure that rsyslogd follows its default, standard BSD behavior. Of course,
+some configuration file changes are necessary in order to support the
+template system. However, rsyslogd should be able to use a standard
+syslog.conf and act like the orginal syslogd. However, an original syslogd
+will not work correctly with a rsyslog-enhanced configuration file. At
+best, it will generate funny looking file names.
+The second important concept to note is that this version of rsyslogd
+interacts transparently with the version of syslog found in the
+standard libraries. If a binary linked to the standard shared
+libraries fails to function correctly we would like an example of the
+anomalous behavior.
+
+The main configuration file
+.I /etc/rsyslog.conf
+or an alternative file, given with the
+.B "\-f"
+option, is read at startup. Any lines that begin with the hash mark
+(``#'') and empty lines are ignored. If an error occurs during parsing
+the error element is ignored. It is tried to parse the rest of the line.
+
+For details and configuration examples, see the
+.B rsyslog.conf (5)
+man page.
+
+.LP
+.SH OPTIONS
+.TP
+.BI "\-A"
+When sending UDP messages, there are potentially multiple pathes to
+the target destination. By default,
+.B rsyslogd
+only sends to the first target it can successfully send to. If -A
+is given, messages are sent to all targets. This may improve
+reliability, but may also cause message duplicaton. This option
+should enabled only if it is fully understood.
+.TP
+.BI "\-4"
+Causes
+.B rsyslogd
+to listen to IPv4 addresses only.
+If neither -4 nor -6 is given,
+.B rsyslogd
+listens to all configured addresses of the system.
+.TP
+.BI "\-6"
+Causes
+.B rsyslogd
+to listen to IPv6 addresses only.
+If neither -4 nor -6 is given,
+.B rsyslogd
+listens to all configured addresses of the system.
+.TP
+.BI "\-a " "socket"
+Using this argument you can specify additional sockets from that
+.B rsyslogd
+has to listen to. This is needed if you're going to let some daemon
+run within a chroot() environment. You can use up to 19 additional
+sockets. If your environment needs even more, you have to increase
+the symbol
+.B MAXFUNIX
+within the syslogd.c source file. An example for a chroot() daemon is
+described by the people from OpenBSD at
+http://www.psionic.com/papers/dns.html.
+.TP
+.B "\-d"
+Turns on debug mode. Using this the daemon will not proceed a
+.BR fork (2)
+to set itself in the background, but opposite to that stay in the
+foreground and write much debug information on the current tty. See the
+DEBUGGING section for more information.
+.TP
+.B "\-e"
+Set the default of $RepeatedMsgReduction config option to "off".
+Hine: "e" like "every message". For further information, see there.
+.TP
+.BI "\-f " "config file"
+Specify an alternative configuration file instead of
+.IR /etc/rsyslog.conf ","
+which is the default.
+.TP
+.BI "\-h "
+By default rsyslogd will not forward messages it receives from remote hosts.
+Specifying this switch on the command line will cause the log daemon to
+forward any remote messages it receives to forwarding hosts which have been
+defined.
+.TP
+.BI "\-i " "pid file"
+Specify an alternative pid file instead of the default one.
+This option must be used if multiple instances of rsyslogd should
+run on a single machine.
+.TP
+.BI "\-l " "hostlist"
+Specify a hostname that should be logged only with its simple hostname
+and not the fqdn. Multiple hosts may be specified using the colon
+(``:'') separator.
+
+Note: At the moment, this option is only available for command
+line comptability. It has, however, NO effect and is ignored.
+.TP
+.BI "\-m " "interval"
+The
+.B rsyslogd
+logs a mark timestamp regularly. The default
+.I interval
+between two \fI-- MARK --\fR lines is 20 minutes. This can be changed
+with this option. Setting the
+.I interval
+to zero turns it off entirely.
+.TP
+.B "\-n"
+Avoid auto-backgrounding. This is needed especially if the
+.B rsyslogd
+is started and controlled by
+.BR init (8).
+.TP
+.B "\-o"
+Omit reading the standard local log socket. This option is most
+useful for running multiple instances of rsyslogd on a single
+machine. When specified, no local log socket is opened at all.
+.TP
+.BI "\-p " "socket"
+You can specify an alternative unix domain socket instead of
+.IR /dev/log "."
+.TP
+.BI "\-r " ["port"]
+Activates the syslog/udp listener service. The listener
+will listen to the specified port. If no port is specified,
+0 is used as port number, which in turn will lead to a
+lookup of the system default syslog port. If there is
+no system default, 514 is used. Please note that the port
+must immediately follow the -r option. Thus "-r514" is valid
+while "-r 514" is invalid (note the space).
+.TP
+.BI "\-s " "domainlist"
+Specify a domainname that should be stripped off before
+logging. Multiple domains may be specified using the colon (``:'')
+separator.
+Please be advised that no sub-domains may be specified but only entire
+domains. For example if
+.B "\-s north.de"
+is specified and the host logging resolves to satu.infodrom.north.de
+no domain would be cut, you will have to specify two domains like:
+.BR "\-s north.de:infodrom.north.de" .
+.TP
+.BI "\-t " "port,max-nbr-of-sessions"
+Activates the syslog/tcp listener service. The listener will listen to
+the specified port. If max-nbr-of-sessions is specified, that becomes
+the maximum number of concurrent tcp sessions. If not specified, the
+default is 200. Please note that syslog/tcp is not standardized,
+but the implementation in rsyslogd follows common practice and is
+compatible with e.g. Cisco PIX, syslog-ng and MonitorWare (Windows).
+Please note that the port
+must immediately follow the -t option. Thus "-t514" is valid
+while "-t 514" is invalid (note the space).
+.TP
+.B "\-v"
+Print version and exit.
+.TP
+.B "\-w"
+Supress warnings issued when messages are received from non-authorized
+machines (those, that are in no AllowedSender list).
+.TP
+.B "\-x"
+Disable DNS for remote messages.
+.LP
+.SH SIGNALS
+.B Rsyslogd
+reacts to a set of signals. You may easily send a signal to
+.B rsyslogd
+using the following:
+.IP
+.nf
+kill -SIGNAL `cat /var/run/rsyslogd.pid`
+.fi
+.PP
+.TP
+.B SIGHUP
+This lets
+.B rsyslogd
+perform a re-initialization. All open files are closed, the
+configuration file (default is
+.IR /etc/rsyslog.conf ")"
+will be reread and the
+.BR rsyslog (3)
+facility is started again.
+.TP
+.B SIGTERM
+.B Rsyslogd
+will die.
+.TP
+.BR SIGINT ", " SIGQUIT
+If debugging is enabled these are ignored, otherwise
+.B rsyslogd
+will die.
+.TP
+.B SIGUSR1
+Switch debugging on/off. This option can only be used if
+.B rsyslogd
+is started with the
+.B "\-d"
+debug option.
+.TP
+.B SIGCHLD
+Wait for childs if some were born, because of wall'ing messages.
+.LP
+.SH SUPPORT FOR REMOTE LOGGING
+.B Rsyslogd
+provides network support to the syslogd facility.
+Network support means that messages can be forwarded from one node
+running rsyslogd to another node running rsyslogd (or a
+compatible syslog implementation) where they will be
+actually logged to a disk file.
+
+To enable this you have to specify either the
+.B "\-r"
+or
+.B "\-t"
+option on the command line. The default behavior is that
+.B rsyslogd
+won't listen to the network. You can also combine these two
+options if you want rsyslogd to listen to both TCP and UDP
+messages.
+
+The strategy is to have rsyslogd listen on a unix domain socket for
+locally generated log messages. This behavior will allow rsyslogd to
+inter-operate with the syslog found in the standard C library. At the
+same time rsyslogd listens on the standard syslog port for messages
+forwarded from other hosts. To have this work correctly the
+.BR services (5)
+files (typically found in
+.IR /etc )
+must have the following
+entry:
+.IP
+.nf
+ syslog 514/udp
+.fi
+.PP
+If this entry is missing
+.B rsyslogd
+will use the well known port of 514 (so in most cases, it's not
+really needed).
+
+To cause messages to be forwarded to another host replace
+the normal file line in the
+.I rsyslog.conf
+file with the name of the host to which the messages is to be sent
+prepended with an @ (for UDP delivery) or the sequence @@ (for
+TCP delivery). The host name can also be followed by a colon and
+a port number, in which case the message is sent to the specified
+port on the remote host.
+.IP
+For example, to forward
+.B ALL
+messages to a remote host use the
+following
+.I rsyslog.conf
+entry:
+.IP
+.nf
+ # Sample rsyslogd configuration file to
+ # messages to a remote host forward all.
+ *.* @hostname
+.fi
+More samples can be found in sample.conf.
+
+If the remote hostname cannot be resolved at startup, because the
+name-server might not be accessible (it may be started after rsyslogd)
+you don't have to worry.
+.B Rsyslogd
+will retry to resolve the name ten times and then complain. Another
+possibility to avoid this is to place the hostname in
+.IR /etc/hosts .
+
+With normal
+.BR syslogd s
+you would get syslog-loops if you send out messages that were received
+from a remote host to the same host (or more complicated to a third
+host that sends it back to the first one, and so on).
+
+To avoid this no messages that were received from a
+remote host are sent out to another (or the same) remote host. You can
+disable this feature by the
+.B \-h
+option.
+
+If the remote host is located in the same domain as the host,
+.B rsyslogd
+is running on, only the simple hostname will be logged instead of
+the whole fqdn.
+
+In a local network you may provide a central log server to have all
+the important information kept on one machine. If the network consists
+of different domains you don't have to complain about logging fully
+qualified names instead of simple hostnames. You may want to use the
+strip-domain feature
+.B \-s
+of this server. You can tell
+.B rsyslogd
+to strip off several domains other than the one the server is located
+in and only log simple hostnames.
+
+Using the
+.B \-l
+option there's also a possibility to define single hosts as local
+machines. This, too, results in logging only their simple hostnames
+and not the fqdns.
+
+.SH OUTPUT TO DATABASES
+.B Rsyslogd
+has support for writing data to MySQL database tables. The exact specifics
+are described in the
+.B rsyslog.conf (5)
+man page. Be sure to read it if you plan to use database logging.
+
+While it is often handy to have the data in a database, you must be aware
+of the implications. Most importantly, database logging takes far
+longer than logging to a text file. A system that can handle a large
+log volume when writing to text files can most likely not handle
+a similar large volume when writing to a database table.
+
+.SH OUTPUT TO NAMED PIPES (FIFOs)
+.B Rsyslogd
+has support for logging output to named pipes
+(fifos). A fifo or named pipe can be used as a destination for log
+messages by prepending a pipy symbol (``|'') to the name of the
+file. This is handy for debugging. Note that the fifo must be created
+with the mkfifo command before
+.B rsyslogd
+is started.
+.IP
+The following configuration file routes debug messages from the
+kernel to a fifo:
+.IP
+.nf
+ # Sample configuration to route kernel debugging
+ # messages ONLY to /usr/adm/debug which is a
+ # named pipe.
+ kern.=debug |/usr/adm/debug
+.fi
+.LP
+.SH INSTALLATION CONCERNS
+There is probably one important consideration when installing
+rsyslogd. It is dependent on proper
+formatting of messages by the syslog function. The functioning of the
+syslog function in the shared libraries changed somewhere in the
+region of libc.so.4.[2-4].n. The specific change was to
+null-terminate the message before transmitting it to the
+.I /dev/log
+socket. Proper functioning of this version of rsyslogd is dependent on
+null-termination of the message.
+
+This problem will typically manifest itself if old statically linked
+binaries are being used on the system. Binaries using old versions of
+the syslog function will cause empty lines to be logged followed by
+the message with the first character in the message removed.
+Relinking these binaries to newer versions of the shared libraries
+will correct this problem.
+
+The
+.BR rsyslogd (8)
+can be run from
+.BR init (8)
+or started as part of the rc.*
+sequence. If it is started from init the option \fI\-n\fR must be set,
+otherwise you'll get tons of syslog daemons started. This is because
+.BR init (8)
+depends on the process ID.
+.LP
+.SH SECURITY THREATS
+There is the potential for the rsyslogd daemon to be
+used as a conduit for a denial of service attack.
+A rogue program(mer) could very easily flood the rsyslogd daemon with
+syslog messages resulting in the log files consuming all the remaining
+space on the filesystem. Activating logging over the inet domain
+sockets will of course expose a system to risks outside of programs or
+individuals on the local machine.
+
+There are a number of methods of protecting a machine:
+.IP 1.
+Implement kernel firewalling to limit which hosts or networks have
+access to the 514/UDP socket.
+.IP 2.
+Logging can be directed to an isolated or non-root filesystem which,
+if filled, will not impair the machine.
+.IP 3.
+The ext2 filesystem can be used which can be configured to limit a
+certain percentage of a filesystem to usage by root only. \fBNOTE\fP
+that this will require rsyslogd to be run as a non-root process.
+\fBALSO NOTE\fP that this will prevent usage of remote logging since
+rsyslogd will be unable to bind to the 514/UDP socket.
+.IP 4.
+Disabling inet domain sockets will limit risk to the local machine.
+.IP 5.
+Use step 4 and if the problem persists and is not secondary to a rogue
+program/daemon get a 3.5 ft (approx. 1 meter) length of sucker rod*
+and have a chat with the user in question.
+
+Sucker rod def. \(em 3/4, 7/8 or 1in. hardened steel rod, male
+threaded on each end. Primary use in the oil industry in Western
+North Dakota and other locations to pump 'suck' oil from oil wells.
+Secondary uses are for the construction of cattle feed lots and for
+dealing with the occasional recalcitrant or belligerent individual.
+.SS Message replay and spoofing
+If remote logging is enabled, messages can easily be spoofed and replayed.
+As the messages are transmitted in clear-text, an attacker might use
+the information obtained from the packets for malicious things. Also, an
+attacker might reply recorded messages or spoof a sender's IP address,
+which could lead to a wrong preception of system activity. Be sure to think
+about syslog network security before enabling it.
+.LP
+.SH DEBUGGING
+When debugging is turned on using
+.B "\-d"
+option then
+.B rsyslogd
+will be very verbose by writing much of what it does on stdout. Whenever
+the configuration file is reread and re-parsed you'll see a tabular,
+corresponding to the internal data structure. This tabular consists of
+four fields:
+.TP
+.I number
+This field contains a serial number starting by zero. This number
+represents the position in the internal data structure (i.e. the
+array). If one number is left out then there might be an error in the
+corresponding line in
+.IR /etc/rsyslog.conf .
+.TP
+.I pattern
+This field is tricky and represents the internal structure
+exactly. Every column stands for a facility (refer to
+.BR syslog (3)).
+As you can see, there are still some facilities left free for former
+use, only the left most are used. Every field in a column represents
+the priorities (refer to
+.BR syslog (3)).
+.TP
+.I action
+This field describes the particular action that takes place whenever a
+message is received that matches the pattern. Refer to the
+.BR syslog.conf (5)
+manpage for all possible actions.
+.TP
+.I arguments
+This field shows additional arguments to the actions in the last
+field. For file-logging this is the filename for the logfile; for
+user-logging this is a list of users; for remote logging this is the
+hostname of the machine to log to; for console-logging this is the
+used console; for tty-logging this is the specified tty; wall has no
+additional arguments.
+.TP
+.SS templates
+There will also be a second internal structure which lists all
+defined templates and there contents. This also enables you to see
+the internally-defined, hardcoded templates.
+.SH FILES
+.PD 0
+.TP
+.I /etc/rsyslog.conf
+Configuration file for
+.BR rsyslogd .
+See
+.BR rsyslog.conf (5)
+for exact information.
+.TP
+.I /dev/log
+The Unix domain socket to from where local syslog messages are read.
+.TP
+.I /var/run/rsyslogd.pid
+The file containing the process id of
+.BR rsyslogd .
+.PD
+.SH BUGS
+Please review the file BUGS for up-to-date information on known
+bugs and annouyances.
+.SH Further Information
+Please visit
+.BR http://www.rsyslog.com/doc
+for additional information, tutorials and a support forum.
+.SH SEE ALSO
+.BR rsyslog.conf (5),
+.BR logger (1),
+.BR syslog (2),
+.BR syslog (3),
+.BR services (5),
+.BR savelog (8)
+.LP
+.SH COLLABORATORS
+.B rsyslogd
+is derived from sysklogd sources, which in turn was taken from
+the BSD sources. Special thanks to Greg Wettstein (greg@wind.enjellic.com)
+and Martin Schulze (joey@linux.de) for the fine sysklogd package.
+
+.PD 0
+.TP
+Rainer Gerhards
+.TP
+Adiscon GmbH
+.TP
+Grossrinderfeld, Germany
+.TP
+rgerhards@adiscon.com
+
+.TP
+Michael Meckelein
+.TP
+Adiscon GmbH
+.TP
+mmeckelein@adiscon.com
+.PD
+.zZ
diff --git a/slackware/rc.rsyslogd b/slackware/rc.rsyslogd
new file mode 100755
index 0000000..10a2791
--- /dev/null
+++ b/slackware/rc.rsyslogd
@@ -0,0 +1,68 @@
+#!/bin/sh
+# Start/stop/restart the system logging daemons.
+#
+# Written for Slackware Linux by Patrick J. Volkerding <volkerdi@slackware.com>.
+# Modded for rsyslogd by Chris Elvidge <chris@lowe.ae> Sept 2005
+#
+
+create_xconsole()
+{
+ if [ ! -e /dev/xconsole ]; then
+ mknod -m 640 /dev/xconsole p
+ else
+ chmod 0640 /dev/xconsole
+ fi
+ chown 0:0 /dev/xconsole
+}
+
+rsyslogd_start() {
+ if [ -x /usr/sbin/rsyslogd -a -x /usr/sbin/klogd ]; then
+ echo "Starting rsyslogd / klogd daemons: "
+# this one listens on the "usual" socket /dev/log
+ echo "/usr/sbin/rsyslogd -i $pidfile1"
+ /usr/sbin/rsyslogd -i "$pidfile1"
+# this one listens only to the UDP port
+ sleep 1
+ echo "/usr/sbin/rsyslogd -o -r 0 -f $confile2 -i $pidfile2"
+ /usr/sbin/rsyslogd -o -r 0 -f "$confile2" -i "$pidfile2"
+ sleep 1 # prevent syslogd/klogd race condition on SMP kernels
+ echo "/usr/sbin/klogd -c 3 -x"
+ # '-c 3' = display level 'error' or higher messages on console
+ # '-x' = turn off broken EIP translation
+ /usr/sbin/klogd -c 3 -x
+ fi
+}
+
+rsyslogd_stop() {
+ killall rsyslogd 2> /dev/null
+ killall klogd 2> /dev/null
+ /usr/bin/rm pidfile1 2> /dev/null
+ /usr/bin/rm pidfile2 2> /dev/null
+}
+
+rsyslogd_restart() {
+ rsyslogd_stop
+ sleep 1
+ rsyslogd_start
+}
+
+confile1=/etc/rsyslog.conf
+pidfile1=/var/run/rsyslogd.pid
+
+confile2=/etc/rsyslog.udp.conf
+pidfile2=/var/run/rsyslogd.udp.pid
+
+case "$1" in
+'start')
+ create_xconsole
+ rsyslogd_start
+ ;;
+'stop')
+ rsyslogd_stop
+ ;;
+'restart')
+ rsyslogd_restart
+ ;;
+*)
+ echo "usage $0 start|stop|restart"
+esac
diff --git a/srUtils.c b/srUtils.c
new file mode 100755
index 0000000..0aed9de
--- /dev/null
+++ b/srUtils.c
@@ -0,0 +1,235 @@
+/**\file srUtils.c
+ * \brief General utilties that fit nowhere else.
+ *
+ * The namespace for this file is "srUtil".
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding begun.
+ *
+ * Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include "rsyslog.h" /* THIS IS A MODIFICATION FOR RSYSLOG! 2004-11-18 rgerards */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <assert.h>
+#include <wait.h>
+#include <ctype.h>
+#include "liblogging-stub.h" /* THIS IS A MODIFICATION FOR RSYSLOG! 2004-11-18 rgerards */
+#define TRUE 1
+#define FALSE 0
+#include "srUtils.h"
+#include "syslogd.h"
+
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+/* As this is not a "real" object, there won't be any private
+ * members in this file.
+ */
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+rsRetVal srUtilItoA(char *pBuf, int iLenBuf, int iToConv)
+{
+ int i;
+ int bIsNegative;
+ char szBuf[32]; /* sufficiently large for my lifespan and those of my children... ;) */
+
+ assert(pBuf != NULL);
+ assert(iLenBuf > 1); /* This is actually an app error and as thus checked for... */
+
+ if(iToConv < 0)
+ {
+ bIsNegative = TRUE;
+ iToConv *= -1;
+ }
+ else
+ bIsNegative = FALSE;
+
+ /* first generate a string with the digits in the reverse direction */
+ i = 0;
+ do
+ {
+ szBuf[i] = iToConv % 10 + '0';
+ iToConv /= 10;
+ } while(iToConv > 0); /* warning: do...while()! */
+
+ /* make sure we are within bounds... */
+ if(i + 2 > iLenBuf) /* +2 because: a) i starts at zero! b) the \0 byte */
+ return RS_RET_PROVIDED_BUFFER_TOO_SMALL;
+
+ /* then move it to the right direction... */
+ if(bIsNegative == TRUE)
+ *pBuf++ = '-';
+ while(i >= 0)
+ *pBuf++ = szBuf[i--];
+ *pBuf = '\0'; /* terminate it!!! */
+
+ return RS_RET_OK;
+}
+
+uchar *srUtilStrDup(uchar *pOld, size_t len)
+{
+ uchar *pNew;
+
+ assert(pOld != NULL);
+
+ if((pNew = malloc(len + 1)) != NULL)
+ memcpy(pNew, pOld, len + 1);
+
+ return pNew;
+}
+
+
+/* creates a path recursively
+ * Return 0 on success, -1 otherwise. On failure, errno
+ * hold the last OS error.
+ * Param "mode" holds the mode that all non-existing directories
+ * are to be created with.
+ */
+int makeFileParentDirs(uchar *szFile, size_t lenFile, mode_t mode,
+ uid_t uid, gid_t gid, int bFailOnChownFail)
+{
+ uchar *p;
+ uchar *pszWork;
+ size_t len;
+ int bErr = 0;
+
+ assert(szFile != NULL);
+ assert(lenFile > 0);
+
+ len = lenFile + 1; /* add one for '\0'-byte */
+ if((pszWork = malloc(sizeof(uchar) * len)) == NULL)
+ return -1;
+ memcpy(pszWork, szFile, len);
+ for(p = pszWork+1 ; *p ; p++)
+ if(*p == '/') {
+ /* temporarily terminate string, create dir and go on */
+ *p = '\0';
+ if(access((char*)pszWork, F_OK)) {
+ if(mkdir((char*)pszWork, mode) == 0) {
+ if(uid != (uid_t) -1 || gid != (gid_t) -1) {
+ /* we need to set owner/group */
+ if(chown((char*)pszWork, uid, gid) != 0)
+ if(bFailOnChownFail)
+ bErr = 1;
+ /* silently ignore if configured
+ * to do so.
+ */
+ }
+ } else
+ bErr = 1;
+ if(bErr) {
+ int eSave = errno;
+ free(pszWork);
+ errno = eSave;
+ return -1;
+ }
+ }
+ *p = '/';
+ }
+ free(pszWork);
+ return 0;
+}
+
+
+/* execute a program with a single argument
+ * returns child pid if everything ok, 0 on failure. if
+ * it fails, errno is set. if it fails after the fork(), the caller
+ * can not be notfied for obvious reasons. if bwait is set to 1,
+ * the code waits until the child terminates - that potentially takes
+ * a lot of time.
+ * implemented 2007-07-20 rgerhards
+ */
+int execProg(uchar *program, int bWait, uchar *arg)
+{
+ int pid;
+ int sig;
+
+ dbgprintf("exec program '%s' with param '%s'\n", program, arg);
+ pid = fork();
+ if (pid < 0) {
+ return 0;
+ }
+
+ if(pid) { /* Parent */
+ if(bWait)
+ if(waitpid(pid, NULL, 0) == -1)
+ if(errno != ECHILD) {
+ /* we do not use logerror(), because
+ * that might bring us into an endless
+ * loop. At some time, we may
+ * reconsider this behaviour.
+ */
+ dbgprintf("could not wait on child after executing '%s'",
+ (char*)program);
+ }
+ return pid;
+ }
+ /* Child */
+ alarm(0); /* create a clean environment before we exec the real child */
+ for(sig = 0 ; sig < 32 ; ++sig)
+ signal(sig, SIG_DFL);
+ execlp((char*)program, (char*) program, (char*)arg, NULL);
+ /* In the long term, it's a good idea to implement some enhanced error
+ * checking here. However, it can not easily be done. For starters, we
+ * may run into endless loops if we log to syslog. The next problem is
+ * that output is typically not seen by the user. For the time being,
+ * we use no error reporting, which is quite consitent with the old
+ * system() way of doing things. rgerhards, 2007-07-20
+ */
+ perror("exec");
+ exit(1); /* not much we can do in this case */
+}
+
+
+/* skip over whitespace in a standard C string. The
+ * provided pointer is advanced to the first non-whitespace
+ * charater or the \0 byte, if there is none. It is never
+ * moved past the \0.
+ */
+void skipWhiteSpace(uchar **pp)
+{
+ register uchar *p;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ p = *pp;
+ while(*p && isspace((int) *p))
+ ++p;
+ *pp = p;
+}
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/srUtils.h b/srUtils.h
new file mode 100755
index 0000000..a4e7021
--- /dev/null
+++ b/srUtils.h
@@ -0,0 +1,66 @@
+/*! \file srUtils.h
+ * \brief General, small utilities that fit nowhere else.
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding begun.
+ *
+ * Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef __SRUTILS_H_INCLUDED__
+#define __SRUTILS_H_INCLUDED__ 1
+
+/**
+ * A reimplementation of itoa(), as this is not available
+ * on all platforms. We used the chance to make an interface
+ * that fits us well, so it is no longer plain itoa().
+ *
+ * This method works with the US-ASCII alphabet. If you port this
+ * to e.g. EBCDIC, you need to make a small adjustment. Keep in mind,
+ * that on the wire it MUST be US-ASCII, so basically all you need
+ * to do is replace the constant '0' with 0x30 ;).
+ *
+ * \param pBuf Caller-provided buffer that will receive the
+ * generated ASCII string.
+ *
+ * \param iLenBuf Length of the caller-provided buffer.
+ *
+ * \param iToConv The integer to be converted.
+ */
+rsRetVal srUtilItoA(char *pBuf, int iLenBuf, int iToConv);
+
+/**
+ * A method to duplicate a string for which the length is known.
+ * Len must be the length in characters WITHOUT the trailing
+ * '\0' byte.
+ * rgerhards, 2007-07-10
+ */
+unsigned char *srUtilStrDup(unsigned char *pOld, size_t len);
+/**
+ * A method to create a directory and all its missing parents for
+ * a given file name. Please not that the rightmost element is
+ * considered to be a file name and thus NO directory is being created
+ * for it.
+ * added 2007-07-17 by rgerhards
+ */
+int makeFileParentDirs(uchar *szFile, size_t lenFile, mode_t mode, uid_t uid, gid_t gid, int bFailOnChown);
+
+int execProg(uchar *program, int wait, uchar *arg);
+void skipWhiteSpace(uchar **pp);
+#endif
diff --git a/stringbuf.c b/stringbuf.c
new file mode 100755
index 0000000..c737e3f
--- /dev/null
+++ b/stringbuf.c
@@ -0,0 +1,743 @@
+/* This is the byte-counted string class for rsyslog. It is a replacement
+ * for classical \0 terminated string functions. We introduce it in
+ * the hope it will make the program more secure, obtain some performance
+ * and, most importantly, lay they foundation for syslog-protocol, which
+ * requires strings to be able to handle embedded \0 characters.
+ * Please see syslogd.c for license information.
+ * All functions in this "class" start with rsCStr (rsyslog Counted String).
+ * This code is placed under the GPL.
+ * begun 2005-09-07 rgerhards
+ */
+#include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+#include "rsyslog.h"
+#include "stringbuf.h"
+#include "srUtils.h"
+
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+
+rsCStrObj *rsCStrConstruct(void)
+{
+ rsCStrObj *pThis;
+
+ if((pThis = (rsCStrObj*) calloc(1, sizeof(rsCStrObj))) == NULL)
+ return NULL;
+
+ rsSETOBJTYPE(pThis, OIDrsCStr);
+ pThis->pBuf = NULL;
+ pThis->pszBuf = NULL;
+ pThis->iBufSize = 0;
+ pThis->iStrLen = 0;
+ pThis->iAllocIncrement = RS_STRINGBUF_ALLOC_INCREMENT;
+
+ return pThis;
+}
+
+/* construct from sz string
+ * rgerhards 2005-09-15
+ */
+rsRetVal rsCStrConstructFromszStr(rsCStrObj **ppThis, uchar *sz)
+{
+ rsCStrObj *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ pThis->iBufSize = pThis->iStrLen = strlen((char*)(char *) sz);
+ if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) {
+ RSFREEOBJ(pThis);
+ return RS_RET_OUT_OF_MEMORY;
+ }
+
+ /* we do NOT need to copy the \0! */
+ memcpy(pThis->pBuf, sz, pThis->iStrLen);
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+/* construct from CStr object. only the counted string is
+ * copied, not the szString.
+ * rgerhards 2005-10-18
+ */
+rsRetVal rsCStrConstructFromCStr(rsCStrObj **ppThis, rsCStrObj *pFrom)
+{
+ rsCStrObj *pThis;
+
+ assert(ppThis != NULL);
+ rsCHECKVALIDOBJECT(pFrom, OIDrsCStr);
+
+ if((pThis = rsCStrConstruct()) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+
+ pThis->iBufSize = pThis->iStrLen = pFrom->iStrLen;
+ if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) {
+ RSFREEOBJ(pThis);
+ return RS_RET_OUT_OF_MEMORY;
+ }
+
+ /* copy properties */
+ memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen);
+
+ *ppThis = pThis;
+ return RS_RET_OK;
+}
+
+
+void rsCStrDestruct(rsCStrObj *pThis)
+{
+ /* rgerhards 2005-10-19: The free of pBuf was contained in conditional compilation.
+ * The code was only compiled if STRINGBUF_TRIM_ALLOCSIZE was set to 1. I honestly
+ * do not know why it was so, I think it was an artifact. Anyhow, I have changed this
+ * now. Should there any issue occur, this comment hopefully will shed some light
+ * on what happened. I re-verified, and this function has never before been called
+ * by anyone. So changing it can have no impact for obvious reasons...
+ */
+ if(pThis->pBuf != NULL) {
+ free(pThis->pBuf);
+ }
+
+ if(pThis->pszBuf != NULL) {
+ free(pThis->pszBuf);
+ }
+
+ RSFREEOBJ(pThis);
+}
+
+
+rsRetVal rsCStrAppendStrWithLen(rsCStrObj *pThis, uchar* psz, size_t iStrLen)
+{
+ rsRetVal iRet;
+ int iOldAllocInc;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(psz != NULL);
+
+ /* we first check if the to-be-added string is larger than the
+ * alloc increment. If so, we temporarily increase the alloc
+ * increment to the length of the string. This will ensure that
+ * one string copy will be needed at most. As this is a very
+ * costly operation, it outweights the cost of the strlen((char*)) and
+ * related stuff - at least I think so.
+ * rgerhards 2005-09-22
+ */
+ /* We save the current alloc increment in any case, so we can just
+ * overwrite it below, this is faster than any if-construct.
+ */
+ iOldAllocInc = pThis->iAllocIncrement;
+ if(iStrLen > pThis->iAllocIncrement) {
+ pThis->iAllocIncrement = iStrLen;
+ }
+
+ while(*psz)
+ if((iRet = rsCStrAppendChar(pThis, *psz++)) != RS_RET_OK)
+ return iRet;
+
+ pThis->iAllocIncrement = iOldAllocInc; /* restore */
+ return RS_RET_OK;
+}
+
+
+/* changed to be a wrapper to rsCStrAppendStrWithLen() so that
+ * we can save some time when we have the length but do not
+ * need to change existing code.
+ * rgerhards, 2007-07-03
+ */
+rsRetVal rsCStrAppendStr(rsCStrObj *pThis, uchar* psz)
+{
+ return rsCStrAppendStrWithLen(pThis, psz, strlen((char*)(char*) psz));
+}
+
+
+rsRetVal rsCStrAppendInt(rsCStrObj *pThis, int i)
+{
+ rsRetVal iRet;
+ uchar szBuf[32];
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if((iRet = srUtilItoA((char*) szBuf, sizeof(szBuf), i)) != RS_RET_OK)
+ return iRet;
+
+ return rsCStrAppendStr(pThis, szBuf);
+}
+
+
+rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c)
+{
+ uchar* pNewBuf;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->iStrLen >= pThis->iBufSize)
+ { /* need more memory! */
+ if((pNewBuf = (uchar*) malloc((pThis->iBufSize + pThis->iAllocIncrement) * sizeof(uchar))) == NULL)
+ return RS_RET_OUT_OF_MEMORY;
+ memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize);
+ pThis->iBufSize += pThis->iAllocIncrement;
+ if(pThis->pBuf != NULL) {
+ free(pThis->pBuf);
+ }
+ pThis->pBuf = pNewBuf;
+ }
+
+ /* ok, when we reach this, we have sufficient memory */
+ *(pThis->pBuf + pThis->iStrLen++) = c;
+
+ /* check if we need to invalidate an sz representation! */
+ if(pThis->pszBuf != NULL) {
+ free(pThis->pszBuf);
+ pThis->pszBuf = NULL;
+ }
+
+ return RS_RET_OK;
+}
+
+
+/* Sets the string object to the classigal sz-string provided.
+ * Any previously stored vlaue is discarded. If a NULL pointer
+ * the the new value (pszNew) is provided, an empty string is
+ * created (this is NOT an error!). Property iAllocIncrement is
+ * not modified by this function.
+ * rgerhards, 2005-10-18
+ */
+rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, uchar *pszNew)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->pBuf != NULL)
+ free(pThis->pBuf);
+ if(pThis->pszBuf != NULL)
+ free(pThis->pszBuf);
+ if(pszNew == NULL) {
+ pThis->iStrLen = 0;
+ pThis->iBufSize = 0;
+ pThis->pBuf = NULL;
+ pThis->pszBuf = NULL;
+ } else {
+ pThis->iStrLen = strlen((char*)pszNew);
+ pThis->iBufSize = pThis->iStrLen;
+ pThis->pszBuf = NULL;
+ /* iAllocIncrement is NOT modified! */
+
+ /* now save the new value */
+ if((pThis->pBuf = (uchar*) malloc(sizeof(uchar) * pThis->iStrLen)) == NULL) {
+ RSFREEOBJ(pThis);
+ return RS_RET_OUT_OF_MEMORY;
+ }
+
+ /* we do NOT need to copy the \0! */
+ memcpy(pThis->pBuf, pszNew, pThis->iStrLen);
+ }
+
+ return RS_RET_OK;
+}
+
+/* Converts the CStr object to a classical sz string and returns that.
+ * Same restrictions as in rsCStrGetSzStr() applies (see there!). This
+ * function here guarantees that a valid string is returned, even if
+ * the CStr object currently holds a NULL pointer string buffer. If so,
+ * "" is returned.
+ * rgerhards 2005-10-19
+ */
+uchar* rsCStrGetSzStrNoNULL(rsCStrObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ if(pThis->pBuf == NULL)
+ return (uchar*) "";
+ else
+ return rsCStrGetSzStr(pThis);
+}
+
+
+/* Converts the CStr object to a classical zero-terminated C string
+ * and returns that string. The caller must not free it and must not
+ * destroy the CStr object as long as the ascii string is used.
+ * This function may return NULL, if the string is currently NULL. This
+ * is a feature, not a bug. If you need non-NULL in any case, use
+ * rsCStrGetSzStrNoNULL() instead.
+ * rgerhards, 2005-09-15
+ */
+uchar* rsCStrGetSzStr(rsCStrObj *pThis)
+{
+ size_t i;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->pBuf != NULL)
+ if(pThis->pszBuf == NULL) {
+ /* we do not yet have a usable sz version - so create it... */
+ if((pThis->pszBuf = malloc(pThis->iStrLen + 1 * sizeof(uchar))) == NULL) {
+ /* TODO: think about what to do - so far, I have no bright
+ * idea... rgerhards 2005-09-07
+ */
+ }
+ else { /* we can create the sz String */
+ /* now copy it while doing a sanity check. The string might contain a
+ * \0 byte. There is no way how a sz string can handle this. For
+ * the time being, we simply replace it with space - something that
+ * could definitely be improved (TODO).
+ * 2005-09-15 rgerhards
+ */
+ for(i = 0 ; i < pThis->iStrLen ; ++i) {
+ if(pThis->pBuf[i] == '\0')
+ pThis->pszBuf[i] = ' ';
+ else
+ pThis->pszBuf[i] = pThis->pBuf[i];
+ }
+ /* write terminator... */
+ pThis->pszBuf[i] = '\0';
+ }
+ }
+
+ return(pThis->pszBuf);
+}
+
+
+/* Converts the CStr object to a classical zero-terminated C string,
+ * returns that string and destroys the CStr object. The returned string
+ * MUST be freed by the caller. The function might return NULL if
+ * no memory can be allocated.
+ *
+ * TODO:
+ * This function should at some time become special. The base idea is to
+ * add one extra byte to the end of the regular buffer, so that we can
+ * convert it to an szString without the need to copy. The extra memory
+ * footprint is not hefty, but the performance gain is potentially large.
+ * To get it done now, I am not doing the optimiziation right now.
+ *
+ * rgerhards, 2005-09-07
+ */
+uchar* rsCStrConvSzStrAndDestruct(rsCStrObj *pThis)
+{
+ uchar* pRetBuf;
+
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ pRetBuf = rsCStrGetSzStr(pThis);
+
+ /* We got it, now free the object ourselfs. Please note
+ * that we can NOT use the rsCStrDestruct function as it would
+ * also free the sz String buffer, which we pass on to the user.
+ */
+ if(pThis->pBuf != NULL)
+ free(pThis->pBuf);
+ RSFREEOBJ(pThis);
+
+ return(pRetBuf);
+}
+
+
+rsRetVal rsCStrFinish(rsCStrObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+# if STRINGBUF_TRIM_ALLOCSIZE == 1
+ /* in this mode, we need to trim the string. To do
+ * so, we must allocate a new buffer of the exact
+ * string size, and then copy the old one over.
+ * This new buffer is then to be returned.
+ */
+ if((pRetBuf = malloc((pThis->iBufSize) * sizeof(uchar))) == NULL)
+ { /* OK, in this case we use the previous buffer. At least
+ * we have it ;)
+ */
+ }
+ else
+ { /* got the new buffer, so let's use it */
+ uchar* pBuf;
+ memcpy(pBuf, pThis->pBuf, pThis->iBufPtr + 1);
+ pThis->pBuf = pBuf;
+ }
+# else
+ /* here, we need to do ... nothing ;)
+ */
+# endif
+ return RS_RET_OK;
+}
+
+void rsCStrSetAllocIncrement(rsCStrObj *pThis, int iNewIncrement)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(iNewIncrement > 0);
+
+ pThis->iAllocIncrement = iNewIncrement;
+}
+
+
+/* return the length of the current string
+ * 2005-09-09 rgerhards
+ * Please note: this is only a function in a debug build.
+ * For release builds, it is a macro defined in stringbuf.h.
+ * This is due to performance reasons.
+ */
+#ifndef NDEBUG
+int rsCStrLen(rsCStrObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ return(pThis->iStrLen);
+}
+#endif
+
+/* Truncate characters from the end of the string.
+ * rgerhards 2005-09-15
+ */
+rsRetVal rsCStrTruncate(rsCStrObj *pThis, size_t nTrunc)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(pThis->iStrLen < nTrunc)
+ return RS_TRUNCAT_TOO_LARGE;
+
+ pThis->iStrLen -= nTrunc;
+
+ if(pThis->pszBuf != NULL) {
+ /* in this case, we adjust the psz representation
+ * by writing a new \0 terminator - this is by far
+ * the fastest way and outweights the additional memory
+ * required. 2005-9-19 rgerhards.
+ */
+ pThis->pszBuf[pThis->iStrLen] = '\0';
+ }
+
+ return RS_RET_OK;
+}
+
+/* Trim trailing whitespace from a given string
+ */
+rsRetVal rsCStrTrimTrailingWhiteSpace(rsCStrObj *pThis)
+{
+ register int i;
+ register uchar *pC;
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ i = pThis->iStrLen;
+ pC = pThis->pBuf + i - 1;
+ while(i > 0 && isspace((int)*pC)) {
+ --pC;
+ --i;
+ }
+ /* i now is the new string length! */
+ pThis->iStrLen = i;
+
+ return RS_RET_OK;
+}
+
+/* compare two string objects - works like strcmp(), but operates
+ * on CStr objects. Please note that this version here is
+ * faster in the majority of cases, simply because it can
+ * rely on StrLen.
+ * rgerhards 2005-09-19
+ * fixed bug, in which only the last byte was actually compared
+ * in equal-size strings.
+ * rgerhards, 2005-09-26
+ */
+int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ rsCHECKVALIDOBJECT(pCS2, OIDrsCStr);
+ if(pCS1->iStrLen == pCS2->iStrLen)
+ if(pCS1->iStrLen == 0)
+ return 0; /* zero-sized string are equal ;) */
+ else { /* we now have two non-empty strings of equal
+ * length, so we need to actually check if they
+ * are equal.
+ */
+ register size_t i;
+ for(i = 0 ; i < pCS1->iStrLen ; ++i) {
+ if(pCS1->pBuf[i] != pCS2->pBuf[i])
+ return pCS1->pBuf[i] - pCS2->pBuf[i];
+ }
+ /* if we arrive here, the strings are equal */
+ return 0;
+ }
+ else
+ return pCS1->iStrLen - pCS2->iStrLen;
+}
+
+
+/* check if a sz-type string start with a CStr object. This function
+ * is initially written to support the "startswith" property-filter
+ * comparison operation. Maybe it also has other needs.
+ * rgerhards 2005-10-19
+ */
+int rsCStrSzStrStartsWithCStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
+{
+ register int i;
+ int iMax;
+
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if(iLenSz >= pCS1->iStrLen) {
+ /* we need to checkusing pCS1->iStrLen charactes at maximum, thus
+ * we move it to iMax.
+ */
+ iMax = pCS1->iStrLen;
+ if(iMax == 0)
+ return 0; /* yes, it starts with a zero-sized string ;) */
+ else { /* we now have something to compare, so let's do it... */
+ for(i = 0 ; i < iMax ; ++i) {
+ if(psz[i] != pCS1->pBuf[i])
+ return psz[i] - pCS1->pBuf[i];
+ }
+ /* if we arrive here, the string actually starts with pCS1 */
+ return 0;
+ }
+ }
+ else
+ return -1; /* pCS1 is less then psz */
+}
+
+
+/* check if a CStr object starts with a sz-type string.
+ * rgerhards 2005-09-26
+ */
+int rsCStrStartsWithSzStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
+{
+ register size_t i;
+
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if(pCS1->iStrLen >= iLenSz) {
+ /* we are using iLenSz below, because we need to check
+ * iLenSz characters at maximum (start with!)
+ */
+ if(iLenSz == 0)
+ return 0; /* yes, it starts with a zero-sized string ;) */
+ else { /* we now have something to compare, so let's do it... */
+ for(i = 0 ; i < iLenSz ; ++i) {
+ if(pCS1->pBuf[i] != psz[i])
+ return pCS1->pBuf[i] - psz[i];
+ }
+ /* if we arrive here, the string actually starts with psz */
+ return 0;
+ }
+ }
+ else
+ return -1; /* pCS1 is less then psz */
+}
+
+/* check if a CStr object matches a regex.
+ * msamia@redhat.com 2007-07-12
+ * @return returns 0 if matched
+ * bug: doesn't work for CStr containing \0
+ * rgerhards, 2007-07-16: bug is no real bug, because rsyslogd ensures there
+ * never is a \0 *inside* a property string.
+ */
+int rsCStrSzStrMatchRegex(rsCStrObj *pCS1, uchar *psz)
+{
+ regex_t preq;
+ regcomp(&preq, (char*) rsCStrGetSzStr(pCS1), 0);
+ int iRet = regexec(&preq, (char*) psz, 0, NULL, 0);
+ regfree(&preq);
+ return iRet;
+}
+
+/* compare a rsCStr object with a classical sz string. This function
+ * is almost identical to rsCStrZsStrCmp(), but it also takes an offset
+ * to the CStr object from where the comparison is to start.
+ * I have thought quite a while if it really makes sense to more or
+ * less duplicate the code. After all, if you call it with an offset of
+ * zero, the functionality is exactly the same. So it looks natural to
+ * just have a single function. However, supporting the offset requires
+ * some (few) additional integer operations. While they are few, they
+ * happen at places in the code that is run very frequently. All in all,
+ * I have opted for performance and thus duplicated the code. I hope
+ * this is a good, or at least acceptable, compromise.
+ * rgerhards, 2005-09-26
+ * This function also has an offset-pointer which allows to
+ * specify *where* the compare operation should begin in
+ * the CStr. If everything is to be compared, it must be set
+ * to 0. If some leading bytes are to be skipped, it must be set
+ * to the first index that is to be compared. It must not be
+ * set higher than the string length (this is considered a
+ * program bug and will lead to unpredictable results and program aborts).
+ * rgerhards 2005-09-26
+ */
+int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLenSz)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(iOffset < pCS1->iStrLen);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if((pCS1->iStrLen - iOffset) == iLenSz) {
+ /* we are using iLenSz below, because the lengths
+ * are equal and iLenSz is faster to access
+ */
+ if(iLenSz == 0)
+ return 0; /* zero-sized strings are equal ;) */
+ else { /* we now have two non-empty strings of equal
+ * length, so we need to actually check if they
+ * are equal.
+ */
+ register size_t i;
+ for(i = 0 ; i < iLenSz ; ++i) {
+ if(pCS1->pBuf[i+iOffset] != psz[i])
+ return pCS1->pBuf[i+iOffset] - psz[i];
+ }
+ /* if we arrive here, the strings are equal */
+ return 0;
+ }
+ }
+ else
+ return pCS1->iStrLen - iOffset - iLenSz;
+}
+
+
+/* compare a rsCStr object with a classical sz string.
+ * Just like rsCStrCStrCmp, just for a different data type.
+ * There must not only the sz string but also its length be
+ * provided. If the caller does not know the length he can
+ * call with
+ * rsCstrSzStrCmp(pCS, psz, strlen((char*)psz));
+ * we are not doing the strlen((char*)) ourselfs as the caller might
+ * already know the length and in such cases we can save the
+ * overhead of doing it one more time (strelen() is costly!).
+ * The bottom line is that the provided length MUST be correct!
+ * The to sz string pointer must not be NULL!
+ * rgerhards 2005-09-26
+ */
+int rsCStrSzStrCmp(rsCStrObj *pCS1, uchar *psz, size_t iLenSz)
+{
+ rsCHECKVALIDOBJECT(pCS1, OIDrsCStr);
+ assert(psz != NULL);
+ assert(iLenSz == strlen((char*)psz)); /* just make sure during debugging! */
+ if(pCS1->iStrLen == iLenSz)
+ /* we are using iLenSz below, because the lengths
+ * are equal and iLenSz is faster to access
+ */
+ if(iLenSz == 0)
+ return 0; /* zero-sized strings are equal ;) */
+ else { /* we now have two non-empty strings of equal
+ * length, so we need to actually check if they
+ * are equal.
+ */
+ register size_t i;
+ for(i = 0 ; i < iLenSz ; ++i) {
+ if(pCS1->pBuf[i] != psz[i])
+ return pCS1->pBuf[i] - psz[i];
+ }
+ /* if we arrive here, the strings are equal */
+ return 0;
+ }
+ else
+ return pCS1->iStrLen - iLenSz;
+}
+
+
+/* Locate the first occurence of this rsCStr object inside a standard sz string.
+ * Returns the offset (0-bound) of this first occurrence. If not found, -1 is
+ * returned. Both parameters MUST be given (NULL is not allowed).
+ * rgerhards 2005-09-19
+ */
+int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz)
+{
+ int i;
+ int iMax;
+ int bFound;
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ assert(sz != NULL);
+
+ if(pThis->iStrLen == 0)
+ return 0;
+
+ /* compute the largest index where a match could occur - after all,
+ * the to-be-located string must be able to be present in the
+ * searched string (it needs its size ;)).
+ */
+ iMax = strlen((char*)sz) - pThis->iStrLen;
+
+ bFound = 0;
+ i = 0;
+ while(i <= iMax && !bFound) {
+ size_t iCheck;
+ uchar *pComp = sz + i;
+ for(iCheck = 0 ; iCheck < pThis->iStrLen ; ++iCheck)
+ if(*(pComp + iCheck) != *(pThis->pBuf + iCheck))
+ break;
+ if(iCheck == pThis->iStrLen)
+ bFound = 1; /* found! - else it wouldn't be equal */
+ else
+ ++i; /* on to the next try */
+ }
+
+ return(bFound ? i : -1);
+}
+
+
+/* locate the first occurence of a standard sz string inside a rsCStr object.
+ * Returns the offset (0-bound) of this first occurrence. If not found, -1 is
+ * returned.
+ * rgerhards 2005-09-19
+ * WARNING: i accidently created this function (I later noticed I didn't relly
+ * need it... I will not remove the function, as it probably is useful
+ * some time later. However, it is not fully tested, so start with testing
+ * it before you put it to first use).
+ */
+int rsCStrLocateSzStr(rsCStrObj *pThis, uchar *sz)
+{
+ int iLenSz;
+ int i;
+ int iMax;
+ int bFound;
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+
+ if(sz == NULL)
+ return 0;
+
+ iLenSz = strlen((char*)sz);
+ if(iLenSz == 0)
+ return 0;
+
+ /* compute the largest index where a match could occur - after all,
+ * the to-be-located string must be able to be present in the
+ * searched string (it needs its size ;)).
+ */
+ iMax = pThis->iStrLen - iLenSz;
+
+ bFound = 0;
+ i = 0;
+ while(i < iMax && !bFound) {
+ int iCheck;
+ uchar *pComp = pThis->pBuf + i;
+ for(iCheck = 0 ; iCheck < iLenSz ; ++iCheck)
+ if(*(pComp + iCheck) != *(sz + iCheck))
+ break;
+ if(iCheck == iLenSz)
+ bFound = 1; /* found! - else it wouldn't be equal */
+ else
+ ++i; /* on to the next try */
+ }
+
+ return(bFound ? i : -1);
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/stringbuf.h b/stringbuf.h
new file mode 100755
index 0000000..c007b59
--- /dev/null
+++ b/stringbuf.h
@@ -0,0 +1,135 @@
+/*! \file stringbuf.h
+ * \brief The counted string object
+ *
+ * This is the byte-counted string class for rsyslog. It is a replacement
+ * for classical \0 terminated string functions. We introduce it in
+ * the hope it will make the program more secure, obtain some performance
+ * and, most importantly, lay they foundation for syslog-protocol, which
+ * requires strings to be able to handle embedded \0 characters.
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2005-09-07
+ * Initial version begun.
+ *
+ * All functions in this "class" start with rsCStr (rsyslog Counted String).
+ * Copyright 2005
+ * Rainer Gerhards and Adiscon GmbH. All Rights Reserved.
+ * This code is placed under the GPL.
+ */
+#ifndef _STRINGBUF_H_INCLUDED__
+#define _STRINGBUF_H_INCLUDED__ 1
+
+/**
+ * The dynamic string buffer object.
+ */
+struct rsCStrObject
+{
+#ifndef NDEBUG
+ rsObjID OID; /**< object ID */
+#endif
+ uchar *pBuf; /**< pointer to the string buffer, may be NULL if string is empty */
+ uchar *pszBuf; /**< pointer to the sz version of the string (after it has been created )*/
+ size_t iBufSize; /**< current maximum size of the string buffer */
+ size_t iStrLen; /**< length of the string in characters. */
+ size_t iAllocIncrement; /**< the amount of bytes the string should be expanded if it needs to */
+};
+typedef struct rsCStrObject rsCStrObj;
+
+
+/**
+ * Construct a rsCStr object.
+ */
+rsCStrObj *rsCStrConstruct(void);
+rsRetVal rsCStrConstructFromszStr(rsCStrObj **ppThis, uchar *sz);
+rsRetVal rsCStrConstructFromCStr(rsCStrObj **ppThis, rsCStrObj *pFrom);
+
+/**
+ * Destruct the string buffer object.
+ */
+void rsCStrDestruct(rsCStrObj *pThis);
+
+/**
+ * Append a character to an existing string. If necessary, the
+ * method expands the string buffer.
+ *
+ * \param c Character to append to string.
+ */
+rsRetVal rsCStrAppendChar(rsCStrObj *pThis, uchar c);
+
+/**
+ * Finish the string buffer dynamic allocation.
+ */
+rsRetVal rsCStrFinish(rsCStrObj *pThis);
+
+/**
+ * Truncate "n" number of characters from the end of the
+ * string. The buffer remains unchanged, just the
+ * string length is manipulated. This is for performance
+ * reasons.
+ */
+rsRetVal rsCStrTruncate(rsCStrObj *pThis, size_t nTrunc);
+
+rsRetVal rsCStrTrimTrailingWhiteSpace(rsCStrObj *pThis);
+
+/**
+ * Append a string to the buffer. For performance reasons,
+ * use rsCStrAppenStrWithLen() if you know the length.
+ *
+ * \param psz pointer to string to be appended. Must not be NULL.
+ */
+rsRetVal rsCStrAppendStr(rsCStrObj *pThis, uchar* psz);
+
+/**
+ * Append a string to the buffer.
+ *
+ * \param psz pointer to string to be appended. Must not be NULL.
+ * \param iStrLen the length of the string pointed to by psz
+ */
+rsRetVal rsCStrAppendStrWithLen(rsCStrObj *pThis, uchar* psz, size_t iStrLen);
+
+/**
+ * Set a new allocation incremet. This will influence
+ * the allocation the next time the string will be expanded.
+ * It can be set and changed at any time. If done immediately
+ * after custructing the StrB object, this will also be
+ * the inital allocation.
+ *
+ * \param iNewIncrement The new increment size
+ *
+ * \note It is possible to use a very low increment, e.g. 1 byte.
+ * This can generate a considerable overhead. We highly
+ * advise not to use an increment below 32 bytes, except
+ * if you are very well aware why you are doing it ;)
+ */
+void rsCStrSetAllocIncrement(rsCStrObj *pThis, int iNewIncrement);
+
+/**
+ * Append an integer to the string. No special formatting is
+ * done.
+ */
+rsRetVal rsCStrAppendInt(rsCStrObj *pThis, int i);
+
+
+uchar* rsCStrGetSzStr(rsCStrObj *pThis);
+uchar* rsCStrGetSzStrNoNULL(rsCStrObj *pThis);
+rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, uchar *pszNew);
+uchar* rsCStrConvSzStrAndDestruct(rsCStrObj *pThis);
+int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2);
+int rsCStrSzStrCmp(rsCStrObj *pCS1, uchar *psz, size_t iLenSz);
+int rsCStrOffsetSzStrCmp(rsCStrObj *pCS1, size_t iOffset, uchar *psz, size_t iLenSz);
+int rsCStrLocateSzStr(rsCStrObj *pCStr, uchar *sz);
+int rsCStrLocateInSzStr(rsCStrObj *pThis, uchar *sz);
+int rsCStrStartsWithSzStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz);
+int rsCStrSzStrStartsWithCStr(rsCStrObj *pCS1, uchar *psz, size_t iLenSz);
+int rsCStrSzStrMatchRegex(rsCStrObj *pCS1, uchar *psz);
+
+/* now come inline-like functions */
+#ifdef NDEBUG
+# define rsCStrLen(x) ((x)->iStrLen)
+#else
+ int rsCStrLen(rsCStrObj *pThis);
+#endif
+
+#define rsCStrGetBufBeg(x) ((x)->pBuf)
+
+#endif /* single include */
diff --git a/syslog.c b/syslog.c
new file mode 100644
index 0000000..225b6f7
--- /dev/null
+++ b/syslog.c
@@ -0,0 +1,140 @@
+/* logger.c
+ * Helper routines for klogd. It replaces the regular glibc syslog()
+ * call. The reason is that the glibc version does not support
+ * logging with the kernel facility. This file is a re-implementation
+ * of the functions with only the functionality required for klogd.
+ * So it can NOT be used as a general-purpose replacment.
+ * Thanks to being special, this version is deemed to be considerable
+ * faster than its glibc counterpart.
+ * To avoid confusion, the syslog() replacement is named writeSyslog().
+ * all other functions are just helpers to it.
+ * RGerhards, 2007-06-14
+ *
+ * Copyright (C) 2007 Rainer Gerhards
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#define PATH_LOGNAME "/dev/log" /* be sure you know what you do if you change this! */
+
+static struct sockaddr LoggerAddr; /* AF_UNIX address of local logger */
+static int connected; /* have done connect */
+static int fdLog = -1; /* fd for log - -1 if closed */
+
+/* klogOpenLog
+ * opens the system log for writing. The log is opened immediately.
+ * If it is already open, no action is taken)
+ */
+static void klogOpenlog(void)
+{
+ if (fdLog == -1) {
+ LoggerAddr.sa_family = AF_UNIX;
+ strncpy(LoggerAddr.sa_data, PATH_LOGNAME, sizeof(LoggerAddr.sa_data));
+ fdLog = socket(AF_UNIX, SOCK_DGRAM, 0);
+ }
+ if (fdLog != -1 && !connected)
+ if(connect(fdLog, &LoggerAddr, sizeof(LoggerAddr.sa_family) +
+ sizeof(PATH_LOGNAME) - 1 /* for \0 byte!*/ ) != -1)
+ connected = 1;
+}
+
+/* Close the log file if it is currently open.
+ */
+static void klogCloselog(void)
+{
+ if(fdLog != -1)
+ close(fdLog);
+ fdLog = -1;
+ connected = 0;
+}
+
+/* Write a message to the syslogd.
+ * returns -1 if it fails, something else otherwise
+ */
+int writeSyslogV(int iPRI, const char *szFmt, va_list va)
+{
+ int iChars;
+ int iLen;
+ time_t tNow;
+ int iWritten; /* number of bytes written */
+ char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */
+
+ assert(szFmt != NULL);
+
+ if (fdLog < 0 || !connected)
+ klogOpenlog();
+
+ /* build the message */
+ time(&tNow);
+ /* we can use sprintf safely below, because we know the size of the constants.
+ * By doing so, we save some cpu cycles and code complexity (for unnecessary
+ * error checking).
+ */
+ iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4);
+
+ iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va);
+ if(iChars > (int)(sizeof(msgBuf) / sizeof(char) - iLen))
+ iLen = sizeof(msgBuf) / sizeof(char) - 1; /* full buffer siz minus \0 byte */
+ else
+ iLen += iChars;
+
+ /* output the message to the local logger */
+ iWritten = write(fdLog, msgBuf, iLen);
+ /* Debug aid below - uncomment to use
+ printf("wrote to log(%d): '%s'\n", iWritten, msgBuf); */
+
+ if(iWritten == -1) {
+ /* retry */
+ klogCloselog();
+ klogOpenlog();
+ iWritten = write(fdLog, msgBuf, iLen);
+ }
+
+ return(iWritten);
+}
+
+/* And now the same with variable arguments */
+int writeSyslog(int iPRI, const char *szFmt, ...)
+{
+ int iRet;
+ va_list va;
+
+ assert(szFmt != NULL);
+ va_start(va, szFmt);
+ iRet = writeSyslogV(iPRI, szFmt, va);
+ va_end(va);
+
+ return(iRet);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vi:set ai:
+ */
diff --git a/syslogd-types.h b/syslogd-types.h
new file mode 100644
index 0000000..1eb7912
--- /dev/null
+++ b/syslogd-types.h
@@ -0,0 +1,117 @@
+/* syslogd-type.h
+ * This file contains type defintions used by syslogd and its modules.
+ * It is a required input for any module.
+ *
+ * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef SYSLOGD_TYPES_INCLUDED
+#define SYSLOGD_TYPES_INCLUDED 1
+#include "config.h" /* make sure we have autoconf macros */
+
+#include "stringbuf.h"
+#include "net.h"
+#include <sys/param.h>
+#include <sys/syslog.h>
+
+#define FALSE 0
+#define TRUE 1
+
+#ifdef UT_NAMESIZE
+# define UNAMESZ UT_NAMESIZE /* length of a login name */
+#else
+# define UNAMESZ 8 /* length of a login name */
+#endif
+#define MAXUNAMES 20 /* maximum number of user names */
+#define MAXFNAME 200 /* max file pathname length */
+
+#ifdef WITH_DB
+#include "mysql/mysql.h"
+#define _DB_MAXDBLEN 128 /* maximum number of db */
+#define _DB_MAXUNAMELEN 128 /* maximum number of user name */
+#define _DB_MAXPWDLEN 128 /* maximum number of user's pass */
+#define _DB_DELAYTIMEONERROR 20 /* If an error occur we stop logging until
+ a delayed time is over */
+#endif
+
+
+/* we define features of the syslog code. This features can be used
+ * to check if modules are compatible with them - and possible other
+ * applications I do not yet envision. -- rgerhards, 2007-07-24
+ */
+typedef enum _syslogFeature {
+ sFEATURERepeatedMsgReduction = 1
+} syslogFeature;
+
+/* we define our own facility and severities */
+/* facility and severity codes */
+typedef struct _syslogCode {
+ char *c_name;
+ int c_val;
+} syslogCODE;
+
+typedef enum _TCPFRAMINGMODE {
+ TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */
+ TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */
+ } TCPFRAMINGMODE;
+
+/* values for host comparisons specified with host selector blocks
+ * (+host, -host). rgerhards 2005-10-18.
+ */
+enum _EHostnameCmpMode {
+ HN_NO_COMP = 0, /* do not compare hostname */
+ HN_COMP_MATCH = 1, /* hostname must match */
+ HN_COMP_NOMATCH = 2 /* hostname must NOT match */
+};
+typedef enum _EHostnameCmpMode EHostnameCmpMode;
+
+/* rgerhards 2004-11-11: the following structure represents
+ * a time as it is used in syslog.
+ */
+struct syslogTime {
+ int timeType; /* 0 - unitinialized , 1 - RFC 3164, 2 - syslog-protocol */
+ int year;
+ int month;
+ int day;
+ int hour; /* 24 hour clock */
+ int minute;
+ int second;
+ int secfrac; /* fractional seconds (must be 32 bit!) */
+ int secfracPrecision;
+ char OffsetMode; /* UTC offset + or - */
+ char OffsetHour; /* UTC offset in hours */
+ int OffsetMinute; /* UTC offset in minutes */
+ /* full UTC offset minutes = OffsetHours*60 + OffsetMinute. Then use
+ * OffsetMode to know the direction.
+ */
+};
+
+#ifdef SYSLOG_INET
+struct AllowedSenders {
+ struct NetAddr allowedSender; /* ip address allowed */
+ uint8_t SignificantBits; /* defines how many bits should be discarded (eqiv to mask) */
+ struct AllowedSenders *pNext;
+};
+#endif
+
+#endif /* #ifndef SYSLOGD_TYPES_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/syslogd.c b/syslogd.c
new file mode 100644
index 0000000..78902d3
--- /dev/null
+++ b/syslogd.c
@@ -0,0 +1,6208 @@
+/**
+ * \brief This is the main file of the rsyslogd daemon.
+ *
+ * Please visit the rsyslog project at
+ *
+ * http://www.rsyslog.com
+ *
+ * to learn more about it and discuss any questions you may have.
+ *
+ * Please note that as of now, a lot of the code in this file stems
+ * from the sysklogd project. To learn more over this project, please
+ * visit
+ *
+ * http://www.infodrom.org/projects/sysklogd/
+ *
+ * I would like to express my thanks to the developers of the sysklogd
+ * package - without it, I would have had a much harder start...
+ *
+ * Please note that I made quite some changes to the orignal package.
+ * I expect to do even more changes - up
+ * to a full rewrite - to meet my design goals, which among others
+ * contain a (at least) dual-thread design with a memory buffer for
+ * storing received bursts of data. This is also the reason why I
+ * kind of "forked" a completely new branch of the package. My intension
+ * is to do many changes and only this initial release will look
+ * similar to sysklogd (well, one never knows...).
+ *
+ * As I have made a lot of modifications, please assume that all bugs
+ * in this package are mine and not those of the sysklogd team.
+ *
+ * As of this writing, there already exist heavy
+ * modifications to the orginal sysklogd package. I suggest to no
+ * longer rely too much on code knowledge you eventually have with
+ * sysklogd - rgerhards 2005-07-05
+ * The code is now almost completely different. Be careful!
+ * rgerhards, 2006-11-30
+ *
+ * I have decided to put my code under the GPL. The sysklog package
+ * is distributed under the BSD license. As such, this package here
+ * currently comes with two licenses. Both are given below. As it is
+ * probably hard for you to see what was part of the sysklogd package
+ * and what is part of my code, I suggest that you visit the
+ * sysklogd site on the URL above if you would like to base your
+ * development on a version that is not under the GPL.
+ *
+ * This Project was intiated and is maintained by
+ * Rainer Gerhards <rgerhards@hq.adiscon.com>. See
+ * AUTHORS to learn who helped make it become a reality.
+ *
+ * If you have questions about rsyslogd in general, please email
+ * info@adiscon.com. To learn more about rsyslogd, please visit
+ * http://www.rsyslog.com.
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-10-17
+ * Some initial modifications on the sysklogd package to support
+ * liblogging. These have actually not yet been merged to the
+ * source you see currently (but they hopefully will)
+ *
+ * \date 2004-10-28
+ * Restarted the modifications of sysklogd. This time, we
+ * focus on a simpler approach first. The initial goal is to
+ * provide MySQL database support (so that syslogd can log
+ * to the database).
+ *
+ * rsyslog - An Enhanced syslogd Replacement.
+ * Copyright 2003-2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+
+#ifdef __FreeBSD__
+#define BSD
+#endif
+
+/* change the following setting to e.g. 32768 if you would like to
+ * support large message sizes for IHE (32k is the current maximum
+ * needed for IHE). I was initially tempted to increase it to 32k,
+ * but there is a large memory footprint with the current
+ * implementation in rsyslog. This will change as the processing
+ * changes, but I have re-set it to 1k, because the vast majority
+ * of messages is below that and the memory savings is huge, at
+ * least compared to the overall memory footprint.
+ *
+ * If you intend to receive Windows Event Log data (e.g. via
+ * EventReporter - www.eventreporter.com), you might want to
+ * increase this number to an even higher value, as event
+ * log messages can be very lengthy.
+ * rgerhards, 2005-07-05
+ *
+ * during my recent testing, it showed that 4k seems to be
+ * the typical maximum for UDP based syslog. This is a IP stack
+ * restriction. Not always ... but very often. If you go beyond
+ * that value, be sure to test that rsyslogd actually does what
+ * you think it should do ;) Also, it is a good idea to check the
+ * doc set for anything on IHE - it most probably has information on
+ * message sizes.
+ * rgerhards, 2005-08-05
+ *
+ * I have increased the default message size to 2048 to be in sync
+ * with recent IETF syslog standardization efforts.
+ * rgerhards, 2006-11-30
+ *
+ * I have removed syslogdPanic(). That function was supposed to be used
+ * for logging in low-memory conditons. Ever since it was introduced, it
+ * was a wrapper for dbgprintf(). A more intelligent choice was hard to
+ * find. After all, if we are short on memory, doing anything fance will
+ * again cause memory problems. I have now modified the code so that
+ * those elements for which we do not get memory are simply discarded.
+ * That might be a single property like the TAG, but it might also be
+ * a complete message. The overall goal of this code change is to keep
+ * rsyslogd up and running, while we sacrifice some messages to reach
+ * that goal. It also keeps the code cleaner. A real out of memory
+ * condition is highly unlikely. If it happens, there will probably be
+ * much more trouble on the system in question. Anyhow - rsyslogd will
+ * most probably be able to survive it and carry on with processing
+ * once the situation has been resolved.
+ */
+#define DEFUPRI (LOG_USER|LOG_NOTICE)
+#define DEFSPRI (LOG_KERN|LOG_CRIT)
+#define TIMERINTVL 30 /* interval for checking flush, mark */
+
+#define CONT_LINE 1 /* Allow continuation lines */
+
+#ifdef MTRACE
+#include <mcheck.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <ctype.h>
+#define GNU_SOURCE
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <sys/syslog.h>
+#include <sys/param.h>
+#ifdef __sun
+#include <errno.h>
+#else
+#include <sys/errno.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#ifdef BSD
+# include <sys/timespec.h>
+#endif
+#include <sys/resource.h>
+#include <signal.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+#include <fnmatch.h>
+#include <dirent.h>
+
+#ifndef __sun
+#endif
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include "pidfile.h"
+
+#include <assert.h>
+
+#ifdef USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#if HAVE_PATHS_H
+#include <paths.h>
+#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
+
+#include "srUtils.h"
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "outchannel.h"
+#include "syslogd.h"
+#include "net.h" /* struct NetAddr */
+
+#include "parse.h"
+#include "msg.h"
+#include "modules.h"
+#include "action.h"
+#include "tcpsyslog.h"
+#include "iminternal.h"
+#include "cfsysline.h"
+#include "omshell.h"
+#include "omusrmsg.h"
+#include "ommysql.h"
+#include "omfwd.h"
+#include "omfile.h"
+#include "omdiscard.h"
+
+/* We define our own set of syslog defintions so that we
+ * do not need to rely on (possibly different) implementations.
+ * 2007-07-19 rgerhards
+ */
+/* missing definitions for solaris
+ * 2006-02-16 Rger
+ */
+#ifdef __sun
+# define LOG_AUTHPRIV LOG_AUTH
+#endif
+#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+#define LOG_FTP (11<<3) /* ftp daemon */
+#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+
+syslogCODE rs_prioritynames[] =
+ {
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "debug", LOG_DEBUG },
+ { "emerg", LOG_EMERG },
+ { "err", LOG_ERR },
+ { "error", LOG_ERR }, /* DEPRECATED */
+ { "info", LOG_INFO },
+ { "none", INTERNAL_NOPRI }, /* INTERNAL */
+ { "notice", LOG_NOTICE },
+ { "panic", LOG_EMERG }, /* DEPRECATED */
+ { "warn", LOG_WARNING }, /* DEPRECATED */
+ { "warning", LOG_WARNING },
+ { NULL, -1 }
+ };
+
+syslogCODE rs_facilitynames[] =
+ {
+ { "auth", LOG_AUTH },
+ { "authpriv", LOG_AUTHPRIV },
+ { "cron", LOG_CRON },
+ { "daemon", LOG_DAEMON },
+ { "ftp", LOG_FTP },
+ { "kern", LOG_KERN },
+ { "lpr", LOG_LPR },
+ { "mail", LOG_MAIL },
+ { "mark", INTERNAL_MARK }, /* INTERNAL */
+ { "news", LOG_NEWS },
+ { "security", LOG_AUTH }, /* DEPRECATED */
+ { "syslog", LOG_SYSLOG },
+ { "user", LOG_USER },
+ { "uucp", LOG_UUCP },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+ { NULL, -1 }
+ };
+
+
+#ifndef UTMP_FILE
+#ifdef UTMP_FILENAME
+#define UTMP_FILE UTMP_FILENAME
+#else
+#ifdef _PATH_UTMP
+#define UTMP_FILE _PATH_UTMP
+#else
+#define UTMP_FILE "/etc/utmp"
+#endif
+#endif
+#endif
+
+#ifndef _PATH_LOGCONF
+#define _PATH_LOGCONF "/etc/rsyslog.conf"
+#endif
+
+#if defined(SYSLOGD_PIDNAME)
+#undef _PATH_LOGPID
+#if defined(FSSTND)
+#ifdef BSD
+#define _PATH_VARRUN "/var/run/"
+#endif
+#ifdef __sun
+#define _PATH_VARRUN "/var/run/"
+#endif
+#define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
+#else
+#define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
+#endif
+#else
+#ifndef _PATH_LOGPID
+#if defined(FSSTND)
+#define _PATH_LOGPID _PATH_VARRUN "rsyslogd.pid"
+#else
+#define _PATH_LOGPID "/etc/rsyslogd.pid"
+#endif
+#endif
+#endif
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifndef _PATH_CONSOLE
+#define _PATH_CONSOLE "/dev/console"
+#endif
+
+#ifndef _PATH_TTY
+#define _PATH_TTY "/dev/tty"
+#endif
+
+#ifndef _PATH_LOG
+#ifdef BSD
+#define _PATH_LOG "/var/run/log"
+#else
+#define _PATH_LOG "/dev/log"
+#endif
+#endif
+
+
+/* IPv6 compatibility layer for older platforms
+ * We need to handle a few things different if we are running
+ * on an older platform which does not support all the glory
+ * of IPv6. We try to limit toll on features and reliability,
+ * but obviously it is better to run rsyslog on a platform that
+ * supports everything...
+ * rgerhards, 2007-06-22
+ */
+#ifndef AI_NUMERICSERV
+# define AI_NUMERICSERV 0
+#endif
+
+
+static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
+static char *PidFile = _PATH_LOGPID; /* read-only after startup */
+char ctty[] = _PATH_CONSOLE; /* this is read-only */
+
+int bModMySQLLoaded = 0; /* was a $ModLoad MySQL done? */
+static pid_t myPid; /* our pid for use in self-generated messages, e.g. on startup */
+/* mypid is read-only after the initial fork() */
+static int debugging_on = 0; /* read-only, except on sig USR1 */
+static int restart = 0; /* do restart (config read) - multithread safe */
+
+static int bRequestDoMark = 0; /* do mark processing? (multithread safe) */
+#define MAXFUNIX 20
+
+int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */
+int startIndexUxLocalSockets = 0; /* process funix from that index on (used to
+ * suppress local logging. rgerhards 2005-08-01
+ * read-only after startup
+ */
+int funixParseHost[MAXFUNIX] = { 0, }; /* should parser parse host name? read-only after startup */
+char *funixn[MAXFUNIX] = { _PATH_LOG }; /* read-only after startup */
+int funix[MAXFUNIX] = { -1, }; /* read-only after startup */
+
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+#define TABLE_NOPRI 0 /* Value to indicate no priority in f_pmask */
+#define TABLE_ALLPRI 0xFF /* Value to indicate all priorities in f_pmask */
+#define LOG_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */
+
+/* definitions used for doNameLine to differentiate between different command types
+ * (with otherwise identical code). This is a left-over from the previous config
+ * system. It stays, because it is still useful. So do not wonder why it looks
+ * somewhat strange (at least its name). -- rgerhards, 2007-08-01
+ */
+enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2};
+
+/* The following global variables are used for building
+ * tag and host selector lines during startup and config reload.
+ * This is stored as a global variable pool because of its ease. It is
+ * also fairly compatible with multi-threading as the stratup code must
+ * be run in a single thread anyways. So there can be no race conditions. These
+ * variables are no longer used once the configuration has been loaded (except,
+ * of course, during a reload). rgerhards 2005-10-18
+ */
+static EHostnameCmpMode eDfltHostnameCmpMode;
+static rsCStrObj *pDfltHostnameCmp;
+static rsCStrObj *pDfltProgNameCmp;
+
+/* supporting structures for multithreading */
+#ifdef USE_PTHREADS
+/* this is the first approach to a queue, this time with static
+ * memory.
+ */
+typedef struct {
+ void** pbuf;
+ long head, tail;
+ int full, empty;
+ pthread_mutex_t *mut;
+ pthread_cond_t *notFull, *notEmpty;
+} msgQueue;
+
+int iMainMsgQueueSize;
+int bRunningMultithreaded = 0; /* Is this program running in multithreaded mode? */
+msgQueue *pMsgQueue = NULL;
+static pthread_t thrdWorker;
+static int bGlblDone = 0;
+#endif
+/* END supporting structures for multithreading */
+
+static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
+ * parsed inside message - rgerhards, 2006-03-13 */
+static int bFinished = 0; /* used by termination signal handler, read-only except there
+ * is either 0 or the number of the signal that requested the
+ * termination.
+ */
+
+/*
+ * Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged. After each flush,
+ * we move to the next interval until we reach the largest.
+ */
+int repeatinterval[] = { 30, 60 }; /* # of secs before flush */
+#define MAXREPEAT ((int)((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1))
+#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
+#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
+ (f)->f_repeatcount = MAXREPEAT; \
+ }
+#ifdef SYSLOG_INET
+union sockunion {
+ struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ } su_si;
+ struct sockaddr_in su_sin;
+ struct sockaddr_in6 su_sin6;
+};
+#endif
+
+#define LIST_DELIMITER ':' /* delimiter between two hosts */
+
+struct filed *Files = NULL; /* read-only after init() (but beware of sigusr1!) */
+
+struct code {
+ char *c_name;
+ int c_val;
+};
+
+static struct code PriNames[] = {
+ {"alert", LOG_ALERT},
+ {"crit", LOG_CRIT},
+ {"debug", LOG_DEBUG},
+ {"emerg", LOG_EMERG},
+ {"err", LOG_ERR},
+ {"error", LOG_ERR}, /* DEPRECATED */
+ {"info", LOG_INFO},
+ {"none", INTERNAL_NOPRI}, /* INTERNAL */
+ {"notice", LOG_NOTICE},
+ {"panic", LOG_EMERG}, /* DEPRECATED */
+ {"warn", LOG_WARNING}, /* DEPRECATED */
+ {"warning", LOG_WARNING},
+ {"*", TABLE_ALLPRI},
+ {NULL, -1}
+};
+
+static struct code FacNames[] = {
+ {"auth", LOG_AUTH},
+ {"authpriv", LOG_AUTHPRIV},
+ {"cron", LOG_CRON},
+ {"daemon", LOG_DAEMON},
+ {"kern", LOG_KERN},
+ {"lpr", LOG_LPR},
+ {"mail", LOG_MAIL},
+ {"mark", LOG_MARK}, /* INTERNAL */
+ {"news", LOG_NEWS},
+ {"security", LOG_AUTH}, /* DEPRECATED */
+ {"syslog", LOG_SYSLOG},
+ {"user", LOG_USER},
+ {"uucp", LOG_UUCP},
+#if defined(LOG_FTP)
+ {"ftp", LOG_FTP},
+#endif
+ {"local0", LOG_LOCAL0},
+ {"local1", LOG_LOCAL1},
+ {"local2", LOG_LOCAL2},
+ {"local3", LOG_LOCAL3},
+ {"local4", LOG_LOCAL4},
+ {"local5", LOG_LOCAL5},
+ {"local6", LOG_LOCAL6},
+ {"local7", LOG_LOCAL7},
+ {NULL, -1},
+};
+
+/* global variables for config file state */
+static int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
+int Debug; /* debug flag - read-only after startup */
+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? */
+int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
+static uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
+static int bEscapeCCOnRcv; /* escape control characters on reception: 0 - no, 1 - yes */
+static int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
+static int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
+static int logEveryMsg = 0;/* no repeat message processing - read-only after startup
+ * 0 - suppress duplicate messages
+ * 1 - do NOT suppress duplicate messages
+ */
+/* end global config file state variables */
+
+static unsigned int Forwarding = 0;
+static int nfunix = 1; /* number of Unix sockets open / read-only after startup */
+char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */
+char *LocalDomain; /* our local domain name - read-only after startup */
+int *finet = NULL; /* Internet datagram sockets, first element is nbr of elements
+ * read-only after init(), but beware of restart! */
+static char *LogPort = "514"; /* port number for INET connections */
+static int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
+int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both), set via cmdline */
+int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
+static int MarkSeq = 0; /* mark sequence number - modified in domark() only */
+static int NoFork = 0; /* don't fork - don't run in daemon mode - read-only after startup */
+static int AcceptRemote = 0;/* receive messages that come via UDP - read-only after startup */
+int DisableDNS = 0; /* don't look up IP addresses of remote messages */
+char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u.*/
+char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup*/
+int NoHops = 1; /* Can we bounce syslog messages through an
+ intermediate host. Read-only after startup */
+static int Initialized = 0; /* set when we have initialized ourselves
+ * rgerhards 2004-11-09: and by initialized, we mean that
+ * the configuration file could be properly read AND the
+ * syslog/udp port could be obtained (the later is debatable).
+ * It is mainly a setting used for emergency logging: if
+ * something really goes wild, we can not do as indicated in
+ * the log file, but we still log messages to the system
+ * console. This is probably the best that can be done in
+ * such a case.
+ * read-only after startup, but modified during restart
+ */
+
+extern int errno;
+
+
+/* This structure represents the files that will have log
+ * copies printed.
+ * RGerhards 2004-11-08: Each instance of the filed structure
+ * describes what I call an "output channel". This is important
+ * to mention as we now allow database connections to be
+ * present in the filed structure. If helps immensely, if we
+ * think of it as the abstraction of an output channel.
+ * rgerhards, 2005-10-26: The structure below provides ample
+ * opportunity for non-thread-safety. Each of the variable
+ * accesses must be carefully evaluated, many of them probably
+ * be guarded by mutexes. But beware of deadlocks...
+ * rgerhards, 2007-08-01: as you can see, the structure has shrunk pretty much. I will
+ * remove some of the comments some time. It's still the structure that controls much
+ * of the processing that goes on in syslogd, but it now has lots of helpers.
+ */
+struct filed {
+ struct filed *f_next; /* next in linked list */
+ /* filter properties */
+ enum {
+ FILTER_PRI = 0, /* traditional PRI based filer */
+ FILTER_PROP = 1 /* extended filter, property based */
+ } f_filter_type;
+ EHostnameCmpMode eHostnameCmpMode;
+ rsCStrObj *pCSHostnameComp; /* hostname to check */
+ rsCStrObj *pCSProgNameComp; /* tag to check or NULL, if not to be checked */
+ union {
+ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
+ struct {
+ rsCStrObj *pCSPropName;
+ enum {
+ FIOP_NOP = 0, /* do not use - No Operation */
+ FIOP_CONTAINS = 1, /* contains string? */
+ FIOP_ISEQUAL = 2, /* is (exactly) equal? */
+ FIOP_STARTSWITH = 3, /* starts with a string? */
+ FIOP_REGEX = 4 /* matches a regular expression? */
+ } operation;
+ rsCStrObj *pCSCompValue; /* value to "compare" against */
+ char isNegated; /* actually a boolean ;) */
+ } prop;
+ } f_filterData;
+
+ linkedList_t llActList; /* list of configured actions */
+};
+typedef struct filed selector_t; /* new type name */
+
+
+/* support for simple textual representation of FIOP names
+ * rgerhards, 2005-09-27
+ */
+static char* getFIOPName(unsigned iFIOP)
+{
+ char *pRet;
+ switch(iFIOP) {
+ case FIOP_CONTAINS:
+ pRet = "contains";
+ break;
+ case FIOP_ISEQUAL:
+ pRet = "isequal";
+ break;
+ case FIOP_STARTSWITH:
+ pRet = "startswith";
+ break;
+ case FIOP_REGEX:
+ pRet = "regex";
+ break;
+ default:
+ pRet = "NOP";
+ break;
+ }
+ return pRet;
+}
+
+
+/* Reset config variables to default values.
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ cCCEscapeChar = '#';
+ bActExecWhenPrevSusp = 0;
+ bDebugPrintTemplateList = 1;
+ bDebugPrintCfSysLineHandlerList = 1;
+ bDebugPrintModuleList = 1;
+ bEscapeCCOnRcv = 1; /* default is to escape control characters */
+ bReduceRepeatMsgs = (logEveryMsg == 1) ? 0 : 1;
+ bDropMalPTRMsgs = 0;
+#ifdef USE_PTHREADS
+ iMainMsgQueueSize = 10000;
+#endif
+
+ return RS_RET_OK;
+}
+
+
+/* support for defining allowed TCP and UDP senders. We use the same
+ * structure to implement this (a linked list), but we define two different
+ * list roots, one for UDP and one for TCP.
+ * rgerhards, 2005-09-26
+ */
+#ifdef SYSLOG_INET
+/* All of the five below are read-only after startup */
+static struct AllowedSenders *pAllowedSenders_UDP = NULL; /* the roots of the allowed sender */
+struct AllowedSenders *pAllowedSenders_TCP = NULL; /* lists. If NULL, all senders are ok! */
+static struct AllowedSenders *pLastAllowedSenders_UDP = NULL; /* and now the pointers to the last */
+static struct AllowedSenders *pLastAllowedSenders_TCP = NULL; /* element in the respective list */
+#endif /* #ifdef SYSLOG_INET */
+
+int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
+
+
+/* hardcoded standard templates (used for defaults) */
+static uchar template_TraditionalFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
+static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
+static uchar template_StdFwdFmt[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%\"";
+static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
+static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
+/* end template */
+
+
+/* up to the next comment, prototypes that should be removed by reordering */
+#ifdef USE_PTHREADS
+static msgQueue *queueInit (void);
+static void *singleWorker(); /* REMOVEME later 2005-10-24 */
+#endif
+/* Function prototypes. */
+static char **crunch_list(char *list);
+static void printline(char *hname, char *msg, int iSource);
+static void logmsg(int pri, msg_t*, int flags);
+static rsRetVal fprintlog(action_t *pAction);
+static void reapchild();
+static void debug_switch();
+static rsRetVal cfline(uchar *line, selector_t **pfCurr);
+static int decode(uchar *name, struct code *codetab);
+static void sighup_handler();
+static void die(int sig);
+static void freeSelectors(void);
+static rsRetVal processConfFile(uchar *pConfFile);
+static rsRetVal selectorAddList(selector_t *f);
+static void processImInternal(void);
+
+/* Access functions for the selector_t. These functions are primarily
+ * necessary to make things thread-safe. Consequently, they are slim
+ * if we compile without pthread support.
+ * rgerhards 2005-10-24
+ */
+
+/* END Access functions for the selector_t */
+
+/* Code for handling allowed/disallowed senders
+ */
+#ifdef SYSLOG_INET
+static inline void MaskIP6 (struct in6_addr *addr, uint8_t bits) {
+ register uint8_t i;
+
+ assert (addr != NULL);
+ assert (bits <= 128);
+
+ i = bits/32;
+ if (bits%32)
+ addr->s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
+ for (; i < (sizeof addr->s6_addr32)/4; i++)
+ addr->s6_addr32[i] = 0;
+}
+
+static inline void MaskIP4 (struct in_addr *addr, uint8_t bits) {
+
+ assert (addr != NULL);
+ assert (bits <=32 );
+
+ addr->s_addr &= htonl(0xffffffff << (32 - bits));
+}
+
+#define SIN(sa) ((struct sockaddr_in *)(sa))
+#define SIN6(sa) ((struct sockaddr_in6 *)(sa))
+
+/* This function adds an allowed sender entry to the ACL linked list.
+ * In any case, a single entry is added. If an error occurs, the
+ * function does its error reporting itself. All validity checks
+ * must already have been done by the caller.
+ * This is a helper to AddAllowedSender().
+ * rgerhards, 2007-07-17
+ */
+static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
+ struct NetAddr *iAllow, uint8_t iSignificantBits)
+{
+ struct AllowedSenders *pEntry = NULL;
+
+ assert(ppRoot != NULL);
+ assert(ppLast != NULL);
+ assert(iAllow != NULL);
+
+ if((pEntry = (struct AllowedSenders*) calloc(1, sizeof(struct AllowedSenders))) == NULL) {
+ glblHadMemShortage = 1;
+ return RS_RET_OUT_OF_MEMORY; /* no options left :( */
+ }
+
+ memcpy(&(pEntry->allowedSender), iAllow, sizeof (struct NetAddr));
+ pEntry->pNext = NULL;
+ pEntry->SignificantBits = iSignificantBits;
+
+ /* enqueue */
+ if(*ppRoot == NULL) {
+ *ppRoot = pEntry;
+ } else {
+ (*ppLast)->pNext = pEntry;
+ }
+ *ppLast = pEntry;
+
+ return RS_RET_OK;
+}
+
+/* function to clear the allowed sender structure in cases where
+ * it must be freed (occurs most often when HUPed.
+ * TODO: reconsider recursive implementation
+ */
+static void clearAllowedSenders (struct AllowedSenders *pAllow) {
+ if (pAllow != NULL) {
+ if (pAllow->pNext != NULL)
+ clearAllowedSenders (pAllow->pNext);
+ else {
+ if (F_ISSET(pAllow->allowedSender.flags, ADDR_NAME))
+ free (pAllow->allowedSender.addr.HostWildcard);
+ else
+ free (pAllow->allowedSender.addr.NetAddr);
+
+ free (pAllow);
+ }
+ }
+}
+
+/* function to add an allowed sender to the allowed sender list. The
+ * root of the list is caller-provided, so it can be used for all
+ * supported lists. The caller must provide a pointer to the root,
+ * as it eventually needs to be updated. Also, a pointer to the
+ * pointer to the last element must be provided (to speed up adding
+ * list elements).
+ * rgerhards, 2005-09-26
+ * If a hostname is given there are possible multiple entries
+ * added (all addresses from that host).
+ */
+static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast,
+ struct NetAddr *iAllow, uint8_t iSignificantBits)
+{
+ DEFiRet;
+
+ assert(ppRoot != NULL);
+ assert(ppLast != NULL);
+ assert(iAllow != NULL);
+
+ if (!F_ISSET(iAllow->flags, ADDR_NAME)) {
+ if(iSignificantBits == 0)
+ /* we handle this seperatly just to provide a better
+ * error message.
+ */
+ logerror("You can not specify 0 bits of the netmask, this would "
+ "match ALL systems. If you really intend to do that, "
+ "remove all $AllowedSender directives.");
+
+ switch (iAllow->addr.NetAddr->sa_family) {
+ case AF_INET:
+ if((iSignificantBits < 1) || (iSignificantBits > 32)) {
+ logerrorInt("Invalid bit number in IPv4 address - adjusted to 32",
+ (int)iSignificantBits);
+ iSignificantBits = 32;
+ }
+
+ MaskIP4 (&(SIN(iAllow->addr.NetAddr)->sin_addr), iSignificantBits);
+ break;
+ case AF_INET6:
+ if((iSignificantBits < 1) || (iSignificantBits > 128)) {
+ logerrorInt("Invalid bit number in IPv6 address - adjusted to 128",
+ iSignificantBits);
+ iSignificantBits = 128;
+ }
+
+ MaskIP6 (&(SIN6(iAllow->addr.NetAddr)->sin6_addr), iSignificantBits);
+ break;
+ default:
+ /* rgerhards, 2007-07-16: We have an internal program error in this
+ * case. However, there is not much we can do against it right now. Of
+ * course, we could abort, but that would probably cause more harm
+ * than good. So we continue to run. We simply do not add this line - the
+ * worst thing that happens is that one host will not be allowed to
+ * log.
+ */
+ logerrorInt("Internal error caused AllowedSender to be ignored, AF = %d",
+ iAllow->addr.NetAddr->sa_family);
+ return RS_RET_ERR;
+ }
+ /* OK, entry constructed, now lets add it to the ACL list */
+ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
+ } else {
+ /* we need to process a hostname ACL */
+ if (DisableDNS) {
+ logerror ("Ignoring hostname based ACLs because DNS is disabled.");
+ return RS_RET_OK;
+ }
+
+ if (!strchr (iAllow->addr.HostWildcard, '*') &&
+ !strchr (iAllow->addr.HostWildcard, '?')) {
+ /* single host - in this case, we pull its IP addresses from DNS
+ * and add IP-based ACLs.
+ */
+ struct addrinfo hints, *res, *restmp;
+ struct NetAddr allowIP;
+
+ memset (&hints, 0, sizeof (struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if (getaddrinfo (iAllow->addr.HostWildcard, NULL, &hints, &res) != 0) {
+ logerrorSz("DNS error: Can't resolve \"%s\", not added as allowed sender", iAllow->addr.HostWildcard);
+ /* We could use the text name in this case - maybe this could become
+ * a user-defined option at some stage.
+ */
+ return RS_RET_ERR;
+ }
+
+ for (restmp = res ; res != NULL ; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET: /* add IPv4 */
+ iSignificantBits = 32;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
+ glblHadMemShortage = 1;
+ return RS_RET_OUT_OF_MEMORY;
+ }
+ memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits))
+ != RS_RET_OK)
+ return(iRet);
+ break;
+ case AF_INET6: /* IPv6 - but need to check if it is a v6-mapped IPv4 */
+ if(IN6_IS_ADDR_V4MAPPED (&SIN6(res->ai_addr)->sin6_addr)) {
+ /* extract & add IPv4 */
+
+ iSignificantBits = 32;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = malloc(sizeof(struct sockaddr_in)))
+ == NULL) {
+ glblHadMemShortage = 1;
+ return RS_RET_OUT_OF_MEMORY;
+ }
+ SIN(allowIP.addr.NetAddr)->sin_family = AF_INET;
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ SIN(allowIP.addr.NetAddr)->sin_len = sizeof (struct sockaddr_in);
+#endif
+ SIN(allowIP.addr.NetAddr)->sin_port = 0;
+ memcpy(&(SIN(allowIP.addr.NetAddr)->sin_addr.s_addr),
+ &(SIN6(res->ai_addr)->sin6_addr.s6_addr32[3]),
+ sizeof (struct sockaddr_in));
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
+ iSignificantBits))
+ != RS_RET_OK)
+ return(iRet);
+ } else {
+ /* finally add IPv6 */
+
+ iSignificantBits = 128;
+ allowIP.flags = 0;
+ if((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) {
+ glblHadMemShortage = 1;
+ return RS_RET_OUT_OF_MEMORY;
+ }
+ memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen);
+
+ if((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP,
+ iSignificantBits))
+ != RS_RET_OK)
+ return(iRet);
+ }
+ break;
+ }
+ }
+ freeaddrinfo (restmp);
+ } else {
+ /* wildcards in hostname - we need to add a text-based ACL.
+ * For this, we already have everything ready and just need
+ * to pass it along...
+ */
+ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits);
+ }
+ }
+
+ return iRet;
+}
+#endif /* #ifdef SYSLOG_INET */
+
+
+#ifdef SYSLOG_INET
+/* Print an allowed sender list. The caller must tell us which one.
+ * iListToPrint = 1 means UDP, 2 means TCP
+ * rgerhards, 2005-09-27
+ */
+static void PrintAllowedSenders(int iListToPrint)
+{
+ struct AllowedSenders *pSender;
+ uchar szIP[64];
+
+ assert((iListToPrint == 1) || (iListToPrint == 2));
+
+ printf("\nAllowed %s Senders:\n",
+ (iListToPrint == 1) ? "UDP" : "TCP");
+ pSender = (iListToPrint == 1) ?
+ pAllowedSenders_UDP : pAllowedSenders_TCP;
+ if(pSender == NULL) {
+ printf("\tNo restrictions set.\n");
+ } else {
+ while(pSender != NULL) {
+ if (F_ISSET(pSender->allowedSender.flags, ADDR_NAME))
+ printf ("\t%s\n", pSender->allowedSender.addr.HostWildcard);
+ else {
+ if(getnameinfo (pSender->allowedSender.addr.NetAddr,
+ SALEN(pSender->allowedSender.addr.NetAddr),
+ (char*)szIP, 64, NULL, 0, NI_NUMERICHOST) == 0) {
+ printf ("\t%s/%u\n", szIP, pSender->SignificantBits);
+ } else {
+ /* getnameinfo() failed - but as this is only a
+ * debug function, we simply spit out an error and do
+ * not care much about it.
+ */
+ dbgprintf("\tERROR in getnameinfo() - something may be wrong "
+ "- ignored for now\n");
+ }
+ }
+ pSender = pSender->pNext;
+ }
+ }
+}
+
+
+/* compares a host to an allowed sender list entry. Handles all subleties
+ * including IPv4/v6 as well as domain name wildcards.
+ * This is a helper to isAllowedSender. As it is only called once, it is
+ * declared inline.
+ * Returns 0 if they do not match, something else otherwise.
+ * contributed 1007-07-16 by mildew@gmail.com
+ */
+static inline int MaskCmp(struct NetAddr *pAllow, uint8_t bits, struct sockaddr *pFrom, const char *pszFromHost)
+{
+ assert(pAllow != NULL);
+ assert(pFrom != NULL);
+
+ if(F_ISSET(pAllow->flags, ADDR_NAME)) {
+ dbgprintf("MaskCmp: host=\"%s\"; pattern=\"%s\"\n", pszFromHost, pAllow->addr.HostWildcard);
+
+ return(fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE|FNM_CASEFOLD) == 0);
+ } else {/* We need to compare an IP address */
+ switch (pFrom->sa_family) {
+ case AF_INET:
+ if (AF_INET == pAllow->addr.NetAddr->sa_family)
+ return(( SIN(pFrom)->sin_addr.s_addr & htonl(0xffffffff << (32 - bits)) )
+ == SIN(pAllow->addr.NetAddr)->sin_addr.s_addr);
+ else
+ return 0;
+ break;
+ case AF_INET6:
+ switch (pAllow->addr.NetAddr->sa_family) {
+ case AF_INET6: {
+ struct in6_addr ip, net;
+ register uint8_t i;
+
+ memcpy (&ip, &(SIN6(pFrom))->sin6_addr, sizeof (struct in6_addr));
+ memcpy (&net, &(SIN6(pAllow->addr.NetAddr))->sin6_addr, sizeof (struct in6_addr));
+
+ i = bits/32;
+ if (bits % 32)
+ ip.s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32)));
+ for (; i < (sizeof ip.s6_addr32)/4; i++)
+ ip.s6_addr32[i] = 0;
+
+ return (memcmp (ip.s6_addr, net.s6_addr, sizeof ip.s6_addr) == 0 &&
+ (SIN6(pAllow->addr.NetAddr)->sin6_scope_id != 0 ?
+ SIN6(pFrom)->sin6_scope_id == SIN6(pAllow->addr.NetAddr)->sin6_scope_id : 1));
+ }
+ case AF_INET: {
+ struct in6_addr *ip6 = &(SIN6(pFrom))->sin6_addr;
+ struct in_addr *net = &(SIN(pAllow->addr.NetAddr))->sin_addr;
+
+ if ((ip6->s6_addr32[3] & (u_int32_t) htonl((0xffffffff << (32 - bits)))) == net->s_addr &&
+#if BYTE_ORDER == LITTLE_ENDIAN
+ (ip6->s6_addr32[2] == (u_int32_t)0xffff0000) &&
+#else
+ (ip6->s6_addr32[2] == (u_int32_t)0x0000ffff) &&
+#endif
+ (ip6->s6_addr32[1] == 0) && (ip6->s6_addr32[0] == 0))
+ return 1;
+ else
+ return 0;
+ }
+ default:
+ /* Unsupported AF */
+ return 0;
+ }
+ default:
+ /* Unsupported AF */
+ return 0;
+ }
+ }
+}
+
+
+/* check if a sender is allowed. The root of the the allowed sender.
+ * list must be proveded by the caller. As such, this function can be
+ * used to check both UDP and TCP allowed sender lists.
+ * returns 1, if the sender is allowed, 0 otherwise.
+ * rgerhards, 2005-09-26
+ */
+int isAllowedSender(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost)
+{
+ struct AllowedSenders *pAllow;
+
+ assert(pFrom != NULL);
+
+ if(pAllowRoot == NULL)
+ return 1; /* checking disabled, everything is valid! */
+
+ /* now we loop through the list of allowed senders. As soon as
+ * we find a match, we return back (indicating allowed). We loop
+ * until we are out of allowed senders. If so, we fall through the
+ * loop and the function's terminal return statement will indicate
+ * that the sender is disallowed.
+ */
+ for(pAllow = pAllowRoot ; pAllow != NULL ; pAllow = pAllow->pNext) {
+ if (MaskCmp (&(pAllow->allowedSender), pAllow->SignificantBits, pFrom, pszFromHost))
+ return 1;
+ }
+ dbgprintf("%s is not an allowed sender\n", pszFromHost);
+ return 0;
+}
+#endif /* #ifdef SYSLOG_INET */
+
+
+/* code to free all sockets within a socket table.
+ * A socket table is a descriptor table where the zero
+ * element has the count of elements. This is used for
+ * listening sockets. The socket table itself is also
+ * freed.
+ * A POINTER to this structure must be provided, thus
+ * double indirection!
+ * rgerhards, 2007-06-28
+ */
+void freeAllSockets(int **socks)
+{
+ assert(socks != NULL);
+ assert(*socks != NULL);
+ while(**socks) {
+ dbgprintf("Closing socket %d.\n", (*socks)[**socks]);
+ close((*socks)[**socks]);
+ (**socks)--;
+ }
+ free(*socks);
+ socks = NULL;
+}
+
+
+
+
+/*******************************************************************
+ * BEGIN CODE-LIBLOGGING *
+ *******************************************************************
+ * Code in this section is borrowed from liblogging. This is an
+ * interim solution. Once liblogging is fully integrated, this is
+ * to be removed (see http://www.monitorware.com/liblogging for
+ * more details. 2004-11-16 rgerhards
+ *
+ * Please note that the orginal liblogging code is modified so that
+ * it fits into the context of the current version of syslogd.c.
+ *
+ * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!!
+ */
+
+/**
+ * Parse a 32 bit integer number from a string.
+ *
+ * \param ppsz Pointer to the Pointer to the string being parsed. It
+ * must be positioned at the first digit. Will be updated
+ * so that on return it points to the first character AFTER
+ * the integer parsed.
+ * \retval The number parsed.
+ */
+
+static int srSLMGParseInt32(char** ppsz)
+{
+ int i;
+
+ i = 0;
+ while(isdigit((int) **ppsz))
+ {
+ i = i * 10 + **ppsz - '0';
+ ++(*ppsz);
+ }
+
+ return i;
+}
+
+
+/**
+ * Parse a TIMESTAMP-3339.
+ * updates the parse pointer position.
+ */
+static int srSLMGParseTIMESTAMP3339(struct syslogTime *pTime, char** ppszTS)
+{
+ char *pszTS = *ppszTS;
+
+ assert(pTime != NULL);
+ assert(ppszTS != NULL);
+ assert(pszTS != NULL);
+
+ pTime->year = srSLMGParseInt32(&pszTS);
+
+ /* We take the liberty to accept slightly malformed timestamps e.g. in
+ * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course,
+ * with the current state of affairs, we would never run into this code
+ * here because at postion 11, there is no "T" in such cases ;)
+ */
+ if(*pszTS++ != '-')
+ return FALSE;
+ pTime->month = srSLMGParseInt32(&pszTS);
+ if(pTime->month < 1 || pTime->month > 12)
+ return FALSE;
+
+ if(*pszTS++ != '-')
+ return FALSE;
+ pTime->day = srSLMGParseInt32(&pszTS);
+ if(pTime->day < 1 || pTime->day > 31)
+ return FALSE;
+
+ if(*pszTS++ != 'T')
+ return FALSE;
+
+ pTime->hour = srSLMGParseInt32(&pszTS);
+ if(pTime->hour < 0 || pTime->hour > 23)
+ return FALSE;
+
+ if(*pszTS++ != ':')
+ return FALSE;
+ pTime->minute = srSLMGParseInt32(&pszTS);
+ if(pTime->minute < 0 || pTime->minute > 59)
+ return FALSE;
+
+ if(*pszTS++ != ':')
+ return FALSE;
+ pTime->second = srSLMGParseInt32(&pszTS);
+ if(pTime->second < 0 || pTime->second > 60)
+ return FALSE;
+
+ /* Now let's see if we have secfrac */
+ if(*pszTS == '.')
+ {
+ char *pszStart = ++pszTS;
+ pTime->secfrac = srSLMGParseInt32(&pszTS);
+ pTime->secfracPrecision = (int) (pszTS - pszStart);
+ }
+ else
+ {
+ pTime->secfracPrecision = 0;
+ pTime->secfrac = 0;
+ }
+
+ /* check the timezone */
+ if(*pszTS == 'Z')
+ {
+ pszTS++; /* eat Z */
+ pTime->OffsetMode = 'Z';
+ pTime->OffsetHour = 0;
+ pTime->OffsetMinute = 0;
+ }
+ else if((*pszTS == '+') || (*pszTS == '-'))
+ {
+ pTime->OffsetMode = *pszTS;
+ pszTS++;
+
+ pTime->OffsetHour = srSLMGParseInt32(&pszTS);
+ if(pTime->OffsetHour < 0 || pTime->OffsetHour > 23)
+ return FALSE;
+
+ if(*pszTS++ != ':')
+ return FALSE;
+ pTime->OffsetMinute = srSLMGParseInt32(&pszTS);
+ if(pTime->OffsetMinute < 0 || pTime->OffsetMinute > 59)
+ return FALSE;
+ }
+ else
+ /* there MUST be TZ information */
+ return FALSE;
+
+ /* OK, we actually have a 3339 timestamp, so let's indicated this */
+ if(*pszTS == ' ')
+ ++pszTS;
+ else
+ return FALSE;
+
+ /* update parse pointer */
+ *ppszTS = pszTS;
+
+ return TRUE;
+}
+
+
+/**
+ * Parse a TIMESTAMP-3164.
+ * Returns TRUE on parse OK, FALSE on parse error.
+ */
+static int srSLMGParseTIMESTAMP3164(struct syslogTime *pTime, char* pszTS)
+{
+ assert(pTime != NULL);
+ assert(pszTS != NULL);
+
+ getCurrTime(pTime); /* obtain the current year and UTC offsets! */
+
+ /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec),
+ * we may see the following character sequences occur:
+ *
+ * J(an/u(n/l)), Feb, Ma(r/y), A(pr/ug), Sep, Oct, Nov, Dec
+ *
+ * We will use this for parsing, as it probably is the
+ * fastest way to parse it.
+ *
+ * 2005-07-18, well sometimes it pays to be a bit more verbose, even in C...
+ * Fixed a bug that lead to invalid detection of the data. The issue was that
+ * we had an if(++pszTS == 'x') inside of some of the consturcts below. However,
+ * there were also some elseifs (doing the same ++), which than obviously did not
+ * check the orginal character but the next one. Now removed the ++ and put it
+ * into the statements below. Was a really nasty bug... I didn't detect it before
+ * june, when it first manifested. This also lead to invalid parsing of the rest
+ * of the message, as the time stamp was not detected to be correct. - rgerhards
+ */
+ switch(*pszTS++)
+ {
+ case 'J':
+ if(*pszTS == 'a') {
+ ++pszTS;
+ if(*pszTS == 'n') {
+ ++pszTS;
+ pTime->month = 1;
+ } else
+ return FALSE;
+ } else if(*pszTS == 'u') {
+ ++pszTS;
+ if(*pszTS == 'n') {
+ ++pszTS;
+ pTime->month = 6;
+ } else if(*pszTS == 'l') {
+ ++pszTS;
+ pTime->month = 7;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'F':
+ if(*pszTS == 'e') {
+ ++pszTS;
+ if(*pszTS == 'b') {
+ ++pszTS;
+ pTime->month = 2;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'M':
+ if(*pszTS == 'a') {
+ ++pszTS;
+ if(*pszTS == 'r') {
+ ++pszTS;
+ pTime->month = 3;
+ } else if(*pszTS == 'y') {
+ ++pszTS;
+ pTime->month = 5;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'A':
+ if(*pszTS == 'p') {
+ ++pszTS;
+ if(*pszTS == 'r') {
+ ++pszTS;
+ pTime->month = 4;
+ } else
+ return FALSE;
+ } else if(*pszTS == 'u') {
+ ++pszTS;
+ if(*pszTS == 'g') {
+ ++pszTS;
+ pTime->month = 8;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'S':
+ if(*pszTS == 'e') {
+ ++pszTS;
+ if(*pszTS == 'p') {
+ ++pszTS;
+ pTime->month = 9;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'O':
+ if(*pszTS == 'c') {
+ ++pszTS;
+ if(*pszTS == 't') {
+ ++pszTS;
+ pTime->month = 10;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'N':
+ if(*pszTS == 'o') {
+ ++pszTS;
+ if(*pszTS == 'v') {
+ ++pszTS;
+ pTime->month = 11;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ case 'D':
+ if(*pszTS == 'e') {
+ ++pszTS;
+ if(*pszTS == 'c') {
+ ++pszTS;
+ pTime->month = 12;
+ } else
+ return FALSE;
+ } else
+ return FALSE;
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* done month */
+
+ if(*pszTS++ != ' ')
+ return FALSE;
+
+ /* we accept a slightly malformed timestamp when receiving. This is
+ * we accept one-digit days
+ */
+ if(*pszTS == ' ')
+ ++pszTS;
+
+ pTime->day = srSLMGParseInt32(&pszTS);
+ if(pTime->day < 1 || pTime->day > 31)
+ return FALSE;
+
+ if(*pszTS++ != ' ')
+ return FALSE;
+ pTime->hour = srSLMGParseInt32(&pszTS);
+ if(pTime->hour < 0 || pTime->hour > 23)
+ return FALSE;
+
+ if(*pszTS++ != ':')
+ return FALSE;
+ pTime->minute = srSLMGParseInt32(&pszTS);
+ if(pTime->minute < 0 || pTime->minute > 59)
+ return FALSE;
+
+ if(*pszTS++ != ':')
+ return FALSE;
+ pTime->second = srSLMGParseInt32(&pszTS);
+ if(pTime->second < 0 || pTime->second > 60)
+ return FALSE;
+ if(*pszTS++ != ':')
+
+ /* OK, we actually have a 3164 timestamp, so let's indicate this
+ * and fill the rest of the properties. */
+ pTime->timeType = 1;
+ pTime->secfracPrecision = 0;
+ pTime->secfrac = 0;
+ return TRUE;
+}
+
+/*******************************************************************
+ * END CODE-LIBLOGGING *
+ *******************************************************************/
+
+/**
+ * Format a syslogTimestamp into format required by MySQL.
+ * We are using the 14 digits format. For example 20041111122600
+ * is interpreted as '2004-11-11 12:26:00'.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occured.
+ */
+int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst)
+{
+ /* currently we do not consider localtime/utc. This may later be
+ * added. If so, I recommend using a property replacer option
+ * and/or a global configuration option. However, we should wait
+ * on user requests for this feature before doing anything.
+ * rgerhards, 2007-06-26
+ */
+ assert(ts != NULL);
+ assert(pDst != NULL);
+
+ if (iLenDst < 15) /* we need at least 14 bytes
+ 14 digits for timestamp + '\n' */
+ return(0);
+
+ return(snprintf(pDst, iLenDst, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d",
+ ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second));
+
+}
+
+/**
+ * Format a syslogTimestamp to a RFC3339 timestamp string (as
+ * specified in syslog-protocol).
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string terminator). If 0 is returend, an error occured.
+ */
+int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
+{
+ int iRet;
+ char szTZ[7]; /* buffer for TZ information */
+
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ if(iLenBuf < 20)
+ return(0); /* we NEED at least 20 bytes */
+
+ /* do TZ information first, this is easier to take care of "Z" zone in rfc3339 */
+ if(ts->OffsetMode == 'Z') {
+ szTZ[0] = 'Z';
+ szTZ[1] = '\0';
+ } else {
+ snprintf(szTZ, sizeof(szTZ) / sizeof(char), "%c%2.2d:%2.2d",
+ ts->OffsetMode, ts->OffsetHour, ts->OffsetMinute);
+ }
+
+ if(ts->secfracPrecision > 0)
+ { /* we now need to include fractional seconds. While doing so, we must look at
+ * the precision specified. For example, if we have millisec precision (3 digits), a
+ * secFrac value of 12 is not equivalent to ".12" but ".012". Obviously, this
+ * is a huge difference ;). To avoid this, we first create a format string with
+ * the specific precision and *then* use that format string to do the actual
+ * formating (mmmmhhh... kind of self-modifying code... ;)).
+ */
+ char szFmtStr[64];
+ /* be careful: there is ONE actual %d in the format string below ;) */
+ snprintf(szFmtStr, sizeof(szFmtStr),
+ "%%04d-%%02d-%%02dT%%02d:%%02d:%%02d.%%0%dd%%s",
+ ts->secfracPrecision);
+ iRet = snprintf(pBuf, iLenBuf, szFmtStr, ts->year, ts->month, ts->day,
+ ts->hour, ts->minute, ts->second, ts->secfrac, szTZ);
+ }
+ else
+ iRet = snprintf(pBuf, iLenBuf,
+ "%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d%s",
+ ts->year, ts->month, ts->day,
+ ts->hour, ts->minute, ts->second, szTZ);
+ return(iRet);
+}
+
+/**
+ * Format a syslogTimestamp to a RFC3164 timestamp sring.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string termnator). If 0 is returend, an error occured.
+ */
+int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
+{
+ static char* monthNames[13] = {"ERR", "Jan", "Feb", "Mar",
+ "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"};
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ if(iLenBuf < 16)
+ return(0); /* we NEED 16 bytes */
+ return(snprintf(pBuf, iLenBuf, "%s %2d %2.2d:%2.2d:%2.2d",
+ monthNames[ts->month], ts->day, ts->hour,
+ ts->minute, ts->second
+ ));
+}
+
+/**
+ * Format a syslogTimestamp to a text format.
+ * The caller must provide the timestamp as well as a character
+ * buffer that will receive the resulting string. The function
+ * returns the size of the timestamp written in bytes (without
+ * the string termnator). If 0 is returend, an error occured.
+ */
+#if 0 /* This method is currently not called, be we like to preserve it */
+static int formatTimestamp(struct syslogTime *ts, char* pBuf, size_t iLenBuf)
+{
+ assert(ts != NULL);
+ assert(pBuf != NULL);
+
+ if(ts->timeType == 1) {
+ return(formatTimestamp3164(ts, pBuf, iLenBuf));
+ }
+
+ if(ts->timeType == 2) {
+ return(formatTimestamp3339(ts, pBuf, iLenBuf));
+ }
+
+ return(0);
+}
+#endif
+
+
+/**
+ * Get the current date/time in the best resolution the operating
+ * system has to offer (well, actually at most down to the milli-
+ * second level.
+ *
+ * The date and time is returned in separate fields as this is
+ * most portable and removes the need for additional structures
+ * (but I have to admit it is somewhat "bulky";)).
+ *
+ * Obviously, all caller-provided pointers must not be NULL...
+ */
+void getCurrTime(struct syslogTime *t)
+{
+ struct timeval tp;
+ struct tm *tm;
+ long lBias;
+
+ assert(t != NULL);
+ gettimeofday(&tp, NULL);
+ tm = localtime((time_t*) &(tp.tv_sec));
+
+ t->year = tm->tm_year + 1900;
+ t->month = tm->tm_mon + 1;
+ t->day = tm->tm_mday;
+ t->hour = tm->tm_hour;
+ t->minute = tm->tm_min;
+ t->second = tm->tm_sec;
+ t->secfrac = tp.tv_usec;
+ t->secfracPrecision = 6;
+
+# if __sun
+ /* Solaris uses a different method of exporting the time zone.
+ * It is UTC - localtime, which is the opposite sign of mins east of GMT.
+ */
+ lBias = -(daylight ? altzone : timezone);
+# else
+ lBias = tm->tm_gmtoff;
+# endif
+ if(lBias < 0)
+ {
+ t->OffsetMode = '-';
+ lBias *= -1;
+ }
+ else
+ t->OffsetMode = '+';
+ t->OffsetHour = lBias / 3600;
+ t->OffsetMinute = lBias % 3600;
+}
+/* rgerhards 2004-11-09: end of helper routines. On to the
+ * "real" code ;)
+ */
+
+
+static int usage(void)
+{
+ fprintf(stderr, "usage: rsyslogd [-46Adhvw] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \
+ " [-s domainlist] [-r[port]] [-tport[,max-sessions]] [-f conffile] [-i pidfile] [-x]\n");
+ exit(1); /* "good" exit - done to terminate usage() */
+}
+
+#ifdef SYSLOG_UNIXAF
+static int create_unix_socket(const char *path)
+{
+ struct sockaddr_un sunx;
+ int fd;
+ char line[MAXLINE +1];
+
+ if (path[0] == '\0')
+ return -1;
+
+ (void) 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) {
+ snprintf(line, sizeof(line), "cannot create %s", path);
+ logerror(line);
+ dbgprintf("cannot create %s (%d).\n", path, errno);
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+#endif
+
+#ifdef SYSLOG_INET
+/* closes the UDP listen sockets (if they exist) and frees
+ * all dynamically assigned memory.
+ */
+static void closeUDPListenSockets()
+{
+ register int i;
+
+ if(finet != NULL) {
+ for (i = 0; i < *finet; i++)
+ close(finet[i+1]);
+ free(finet);
+ finet = NULL;
+ }
+}
+
+
+/* creates the UDP listen sockets
+ */
+static int *create_udp_socket()
+{
+ struct addrinfo hints, *res, *r;
+ int error, maxs, *s, *socks, on = 1;
+ int sockflags;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM;
+ error = getaddrinfo(NULL, LogPort, &hints, &res);
+ if(error) {
+ logerror((char*) gai_strerror(error));
+ logerror("UDP message reception disabled due to error logged in last message.\n");
+ return NULL;
+ }
+
+ /* Count max number of sockets we may open */
+ for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+ socks = malloc((maxs+1) * sizeof(int));
+ if (socks == NULL) {
+ logerror("couldn't allocate memory for UDP sockets, suspending UDP message reception");
+ freeaddrinfo(res);
+ return NULL;
+ }
+
+ *socks = 0; /* num of sockets counter at start of array */
+ s = socks + 1;
+ for (r = res; r != NULL ; r = r->ai_next) {
+ *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if (*s < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
+ logerror("create_udp_socket(), socket");
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ continue;
+ }
+
+# ifdef IPV6_V6ONLY
+ if (r->ai_family == AF_INET6) {
+ int ion = 1;
+ if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&ion, sizeof (ion)) < 0) {
+ logerror("setsockopt");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+ }
+# endif
+
+ /* if we have an error, we "just" suspend that socket. Eventually
+ * other sockets will work. At the end of this function, we check
+ * if we managed to open at least one socket. If not, we'll write
+ * a "inet suspended" message and declare failure. Else we use
+ * what we could obtain.
+ * rgerhards, 2007-06-22
+ */
+ if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &on, sizeof(on)) < 0 ) {
+ logerror("setsockopt(REUSEADDR)");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#ifndef BSD
+ if (should_use_so_bsdcompat()) {
+ if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ logerror("setsockopt(BSDCOMPAT)");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+ }
+#endif
+ /* We must not block on the network socket, in case a packet
+ * gets lost between select and recv, otherwise the process
+ * will stall until the timeout, and other processes trying to
+ * log will also stall.
+ * Patch vom Colin Phipps <cph@cph.demon.co.uk> to the original
+ * sysklogd source. Applied to rsyslogd on 2005-10-19.
+ */
+ if ((sockflags = fcntl(*s, F_GETFL)) != -1) {
+ sockflags |= O_NONBLOCK;
+ /* SETFL could fail too, so get it caught by the subsequent
+ * error check.
+ */
+ sockflags = fcntl(*s, F_SETFL, sockflags);
+ }
+ if (sockflags == -1) {
+ logerror("fcntl(O_NONBLOCK)");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+
+ /* rgerhards, 2007-06-22: if we run on a kernel that does not support
+ * the IPV6_V6ONLY socket option, we need to use a work-around. On such
+ * systems the IPv6 socket does also accept IPv4 sockets. So an IPv4
+ * socket can not listen on the same port as an IPv6 socket. The only
+ * workaround is to ignore the "socket in use" error. This is what we
+ * do if we have to.
+ */
+ if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
+# ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+# endif
+ ) {
+ logerror("bind");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+
+ (*socks)++;
+ s++;
+ }
+
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(Debug && *socks != maxs)
+ dbgprintf("We could initialize %d UDP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", *socks, maxs);
+
+ if(*socks == 0) {
+ logerror("No UDP listen socket could successfully be initialized, "
+ "message reception via UDP disabled.\n");
+ /* we do NOT need to free any sockets, because there were none... */
+ free(socks);
+ return(NULL);
+ }
+
+ return(socks);
+}
+#endif
+
+
+/* function to destruct a selector_t object
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal selectorDestruct(void *pVal)
+{
+ selector_t *pThis = (selector_t *) pVal;
+
+ assert(pThis != NULL);
+
+ llDestroy(&pThis->llActList);
+ free(pThis);
+
+ return RS_RET_OK;
+}
+
+
+/* function to construct a selector_t object
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal selectorConstruct(selector_t **ppThis)
+{
+ DEFiRet;
+ selector_t *pThis;
+
+ assert(ppThis != NULL);
+
+ if((pThis = (selector_t*) calloc(1, sizeof(selector_t))) == NULL) {
+ glblHadMemShortage = 1;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ CHKiRet(llInit(&pThis->llActList, actionDestruct, NULL, NULL));
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(pThis != NULL) {
+ selectorDestruct(pThis);
+ }
+ }
+ *ppThis = pThis;
+ return iRet;
+}
+
+
+/* rgerhards, 2005-10-24: crunch_list is called only during option processing. So
+ * it is never called once rsyslogd is running (not even when HUPed). This code
+ * contains some exits, but they are considered safe because they only happen
+ * during startup. Anyhow, when we review the code here, we might want to
+ * reconsider the exit()s.
+ */
+static char **crunch_list(char *list)
+{
+ int count, i;
+ char *p, *q;
+ char **result = NULL;
+
+ p = list;
+
+ /* strip off trailing delimiters */
+ while (p[strlen(p)-1] == LIST_DELIMITER) {
+ count--;
+ p[strlen(p)-1] = '\0';
+ }
+ /* cut off leading delimiters */
+ while (p[0] == LIST_DELIMITER) {
+ count--;
+ p++;
+ }
+
+ /* count delimiters to calculate elements */
+ for (count=i=0; p[i]; i++)
+ if (p[i] == LIST_DELIMITER) count++;
+
+ if ((result = (char **)malloc(sizeof(char *) * (count+2))) == NULL) {
+ printf ("Sorry, can't get enough memory, exiting.\n");
+ exit(0); /* safe exit, because only called during startup */
+ }
+
+ /*
+ * We now can assume that the first and last
+ * characters are different from any delimiters,
+ * so we don't have to care about this.
+ */
+ count = 0;
+ while ((q=strchr(p, LIST_DELIMITER))) {
+ result[count] = (char *) malloc((q - p + 1) * sizeof(char));
+ if (result[count] == NULL) {
+ printf ("Sorry, can't get enough memory, exiting.\n");
+ exit(0); /* safe exit, because only called during startup */
+ }
+ strncpy(result[count], p, q - p);
+ result[count][q - p] = '\0';
+ p = q; p++;
+ count++;
+ }
+ if ((result[count] = \
+ (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) {
+ printf ("Sorry, can't get enough memory, exiting.\n");
+ exit(0); /* safe exit, because only called during startup */
+ }
+ strcpy(result[count],p);
+ result[++count] = NULL;
+
+#if 0
+ count=0;
+ while (result[count])
+ dbgprintf("#%d: %s\n", count, StripDomains[count++]);
+#endif
+ return result;
+}
+
+
+void untty(void)
+#ifdef HAVE_SETSID
+{
+ if ( !Debug ) {
+ setsid();
+ }
+ return;
+}
+#else
+{
+ int i;
+
+ if ( !Debug ) {
+ i = open(_PATH_TTY, O_RDWR);
+ if (i >= 0) {
+ (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
+ (void) close(i);
+ }
+ }
+}
+#endif
+
+
+/* rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
+ * it tried to reassemble multi-part messages, which is a legacy stock
+ * sysklogd concept. In essence, that was that messages not ending with
+ * \0 were glued together. As far as I can see, this is a sysklogd
+ * specific feature and, from looking at the code, seems to be used
+ * pretty seldom (if at all). I remove this now, not the least because it is totally
+ * incompatible with upcoming IETF syslog standards. If you experience
+ * strange behaviour with messages beeing split across multiple lines,
+ * this function here might be the place to look at.
+ *
+ * Some previous history worth noting:
+ * I added the "iSource" parameter. This is needed to distinguish between
+ * messages that have a hostname in them (received from the internet) and
+ * those that do not have (most prominently /dev/log). rgerhards 2004-11-16
+ * And now I removed the "iSource" parameter and changed it to be "bParseHost",
+ * because all that it actually controls is whether the host is parsed or not.
+ * For rfc3195 support, we needed to modify the algo for host parsing, so we can
+ * no longer rely just on the source (rfc3195d forwarded messages arrive via
+ * unix domain sockets but contain the hostname). rgerhards, 2005-10-06
+ */
+void printchopped(char *hname, char *msg, int len, int fd, int bParseHost)
+{
+ register int iMsg;
+ char *pMsg;
+ char *pData;
+ char *pEnd;
+ char tmpline[MAXLINE + 1];
+# ifdef USE_NETZIP
+ char deflateBuf[MAXLINE + 1];
+ uLongf iLenDefBuf;
+# endif
+
+ assert(hname != NULL);
+ assert(msg != NULL);
+ assert(len >= 0);
+
+ dbgprintf("Message length: %d, File descriptor: %d.\n", len, fd);
+
+ /* we first check if we need to drop trailing LFs, which often make
+ * their way into syslog messages unintentionally. In order to remain
+ * compatible to recent IETF developments, we allow the user to
+ * turn on/off this handling. rgerhards, 2007-07-23
+ */
+ if(bDropTrailingLF && *(msg + len - 1) == '\n') {
+ *(msg + len - 1) = '\0';
+ len--;
+ }
+
+ iMsg = 0; /* initialize receiving buffer index */
+ pMsg = tmpline; /* set receiving buffer pointer */
+ pData = msg; /* set source buffer pointer */
+ pEnd = msg + len; /* this is one off, which is intensional */
+
+# ifdef USE_NETZIP
+ /* we first need to check if we have a compressed record. If so,
+ * we must decompress it.
+ */
+ if(len > 0 && *msg == 'z') { /* compressed data present? (do NOT change order if conditions!) */
+ /* we have compressed data, so let's deflate it. We support a maximum
+ * message size of MAXLINE. If it is larger, an error message is logged
+ * and the message is dropped. We do NOT try to decompress larger messages
+ * as such might be used for denial of service. It might happen to later
+ * builds that such functionality be added as an optional, operator-configurable
+ * feature.
+ */
+ int ret;
+ iLenDefBuf = MAXLINE;
+ ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) msg+1, len-1);
+ dbgprintf("Compressed message uncompressed with status %d, length: new %d, old %d.\n",
+ ret, iLenDefBuf, len-1);
+ /* Now check if the uncompression worked. If not, there is not much we can do. In
+ * that case, we log an error message but ignore the message itself. Storing the
+ * compressed text is dangerous, as it contains control characters. So we do
+ * not do this. If someone would like to have a copy, this code here could be
+ * modified to do a hex-dump of the buffer in question. We do not include
+ * this functionality right now.
+ * rgerhards, 2006-12-07
+ */
+ if(ret != Z_OK) {
+ logerrorInt("Uncompression of a message failed with return code %d "
+ "- enable debug logging if you need further information. "
+ "Message ignored.", ret);
+ return; /* unconditional exit, nothing left to do... */
+ }
+ pData = deflateBuf;
+ pEnd = deflateBuf + iLenDefBuf;
+ }
+# else /* ifdef USE_NETZIP */
+ /* in this case, we still need to check if the message is compressed. If so, we must
+ * tell the user we can not accept it.
+ */
+ if(len > 0 && *msg == 'z') {
+ logerror("Received a compressed message, but rsyslogd does not have compression "
+ "support enabled. The message will be ignored.");
+ return;
+ }
+# endif /* ifdef USE_NETZIP */
+
+ while(pData < pEnd) {
+ if(iMsg >= MAXLINE) {
+ /* emergency, we now need to flush, no matter if
+ * we are at end of message or not...
+ */
+ *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
+ printline(hname, tmpline, bParseHost);
+ return; /* in this case, we are done... nothing left we can do */
+ }
+ if(*pData == '\0') { /* guard against \0 characters... */
+ /* changed to the sequence (somewhat) proposed in
+ * draft-ietf-syslog-protocol-19. rgerhards, 2006-11-30
+ */
+ if(iMsg + 3 < MAXLINE) { /* do we have space? */
+ *(pMsg + iMsg++) = cCCEscapeChar;
+ *(pMsg + iMsg++) = '0';
+ *(pMsg + iMsg++) = '0';
+ *(pMsg + iMsg++) = '0';
+ } /* if we do not have space, we simply ignore the '\0'... */
+ /* 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)) {
+ /* 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
+ * Note: sysklogd logs octal values only for DEL and CCs above 127.
+ * For others, it logs ^n where n is the control char converted to an
+ * alphabet character. We like consistency and thus escape it to octal
+ * in all cases. If someone complains, we may change the mode. At least
+ * we known now what's going on.
+ * rgerhards, 2007-07-17
+ */
+ if(iMsg + 3 < MAXLINE) { /* do we have space? */
+ *(pMsg + iMsg++) = cCCEscapeChar;
+ *(pMsg + iMsg++) = '0' + ((*pData & 0300) >> 6);
+ *(pMsg + iMsg++) = '0' + ((*pData & 0070) >> 3);
+ *(pMsg + iMsg++) = '0' + ((*pData & 0007));
+ } /* again, if we do not have space, we ignore the char - see comment at '\0' */
+ ++pData;
+ } else {
+ *(pMsg + iMsg++) = *pData++;
+ }
+ }
+
+ *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
+
+ /* typically, we should end up here! */
+ printline(hname, tmpline, bParseHost);
+
+ return;
+}
+
+/* Take a raw input line, decode the message, and print the message
+ * on the appropriate log files.
+ * rgerhards 2004-11-08: Please note
+ * that this function does only a partial decoding. At best, it splits
+ * the PRI part. No further decode happens. The rest is done in
+ * logmsg(). Please note that printsys() calls logmsg() directly, so
+ * this is something we need to restructure once we are moving the
+ * real decoder in here. I now (2004-11-09) found that printsys() seems
+ * not to be called from anywhere. So we might as well decode the full
+ * message here.
+ * Added the iSource parameter so that we know if we have to parse
+ * HOSTNAME or not. rgerhards 2004-11-16.
+ * changed parameter iSource to bParseHost. For details, see comment in
+ * printchopped(). rgerhards 2005-10-06
+ */
+void printline(char *hname, char *msg, int bParseHost)
+{
+ register char *p;
+ int pri;
+ msg_t *pMsg;
+
+ /* Now it is time to create the message object (rgerhards)
+ */
+ if((pMsg = MsgConstruct()) == NULL){
+ /* rgerhards, 2007-06-21: if we can not get memory, we discard this
+ * message but continue to run (in the hope that things improve)
+ */
+ glblHadMemShortage = 1;
+ dbgprintf("Memory shortage in printline(): Could not construct Msg object.\n");
+ return;
+ }
+ MsgSetRawMsg(pMsg, msg);
+
+ pMsg->bParseHOSTNAME = bParseHost;
+ /* test for special codes */
+ pri = DEFUPRI;
+ p = msg;
+ if (*p == '<') {
+ pri = 0;
+ while (isdigit((int) *++p))
+ {
+ pri = 10 * pri + (*p - '0');
+ }
+ if (*p == '>')
+ ++p;
+ }
+ if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+ pri = DEFUPRI;
+ pMsg->iFacility = LOG_FAC(pri);
+ pMsg->iSeverity = LOG_PRI(pri);
+
+ /* Now we look at the HOSTNAME. That is a bit complicated...
+ * If we have a locally received message, it does NOT
+ * contain any hostname information in the message itself.
+ * As such, the HOSTNAME is the same as the system that
+ * the message was received from (that, for obvious reasons,
+ * being the local host). rgerhards 2004-11-16
+ */
+ if(bParseHost == 0)
+ MsgSetHOSTNAME(pMsg, hname);
+ MsgSetRcvFrom(pMsg, hname);
+
+ /* rgerhards 2004-11-19: well, well... we've now seen that we
+ * have the "hostname problem" also with the traditional Unix
+ * message. As we like to emulate it, we need to add the hostname
+ * to it.
+ */
+ if(MsgSetUxTradMsg(pMsg, p) != 0) return;
+
+ logmsg(pri, pMsg, SYNC_FILE);
+
+ /* rgerhards 2004-11-11:
+ * we are done with the message object. If it still is
+ * stored somewhere, we can call discard anyhow. This
+ * is handled via the reference count - see description
+ * of msg_t for details.
+ */
+ MsgDestruct(pMsg);
+ return;
+}
+
+time_t now;
+
+/* rgerhards 2004-11-09: the following is a function that can be used
+ * to log a message orginating from the syslogd itself. In sysklogd code,
+ * this is done by simply calling logmsg(). However, logmsg() is changed in
+ * rsyslog so that it takes a msg "object". So it can no longer be called
+ * directly. This method here solves the need. It provides an interface that
+ * allows to construct a locally-generated message. Please note that this
+ * function here probably is only an interim solution and that we need to
+ * think on the best way to do this.
+ */
+static void logmsgInternal(int pri, char *msg, int flags)
+{
+ msg_t *pMsg;
+
+ if((pMsg = MsgConstruct()) == NULL){
+ /* rgerhards 2004-11-09: calling panic might not be the
+ * brightest idea - however, it is the best I currently have
+ * (think a bit more about this).
+ * rgehards, 2007-06-21: I have now thought a bit more about
+ * it. If we are so low on memory, there is few we can do. calling
+ * panic so far only write a debug line - this is seomthing we keep.
+ * Other than that, however, we ignore the error and hope that
+ * memory shortage will be resolved while we continue to run. In any
+ * case, there is no valid point in aborting the syslogd for this
+ * reason - that would be counter-productive. So we ignore the
+ * to be logged message.
+ */
+ glblHadMemShortage = 1;
+ dbgprintf("Memory shortage in logmsgInternal: could not construct Msg object.\n");
+ return;
+ }
+
+ MsgSetUxTradMsg(pMsg, msg);
+ MsgSetRawMsg(pMsg, msg);
+ MsgSetHOSTNAME(pMsg, LocalHostName);
+ MsgSetTAG(pMsg, "rsyslogd:");
+ pMsg->iFacility = LOG_FAC(pri);
+ pMsg->iSeverity = LOG_PRI(pri);
+ pMsg->bParseHOSTNAME = 0;
+ getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
+ flags |= INTERNAL_MSG;
+
+#ifdef USE_PTHREADS
+ if(bRunningMultithreaded == 0) { /* not yet in queued mode */
+ iminternalAddMsg(pri, pMsg, flags);
+ } else {
+ /* we have the queue, so we can simply provide the
+ * message to the queue engine.
+ */
+ logmsg(pri, pMsg, flags);
+ MsgDestruct(pMsg);
+ }
+#else
+ iminternalAddMsg(pri, pMsg, flags);
+#endif
+}
+
+/*
+ * This functions looks at the given message and checks if it matches the
+ * provided filter condition. If so, it returns true, else it returns
+ * false. This is a helper to logmsg() and meant to drive the decision
+ * process if a message is to be processed or not. As I expect this
+ * decision code to grow more complex over time AND logmsg() is already
+ * a very lengthe function, I thought a separate function is more appropriate.
+ * 2005-09-19 rgerhards
+ */
+int shouldProcessThisMessage(selector_t *f, msg_t *pMsg)
+{
+ unsigned short pbMustBeFreed;
+ char *pszPropVal;
+ int iRet = 0;
+
+ assert(f != NULL);
+ assert(pMsg != NULL);
+
+ /* we first have a look at the global, BSD-style block filters (for tag
+ * and host). Only if they match, we evaluate the actual filter.
+ * rgerhards, 2005-10-18
+ */
+ if(f->eHostnameCmpMode == HN_NO_COMP) {
+ /* EMPTY BY INTENSION - we check this value first, because
+ * it is the one most often used, so this saves us time!
+ */
+ } else if(f->eHostnameCmpMode == HN_COMP_MATCH) {
+ if(rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
+ /* not equal, so we are already done... */
+ dbgprintf("hostname filter '+%s' does not match '%s'\n",
+ rsCStrGetSzStr(f->pCSHostnameComp), getHOSTNAME(pMsg));
+ return 0;
+ }
+ } else { /* must be -hostname */
+ if(!rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
+ /* not equal, so we are already done... */
+ dbgprintf("hostname filter '-%s' does not match '%s'\n",
+ rsCStrGetSzStr(f->pCSHostnameComp), getHOSTNAME(pMsg));
+ return 0;
+ }
+ }
+
+ if(f->pCSProgNameComp != NULL) {
+ if(rsCStrSzStrCmp(f->pCSProgNameComp, (uchar*) getProgramName(pMsg), getProgramNameLen(pMsg))) {
+ /* not equal, so we are already done... */
+ dbgprintf("programname filter '%s' does not match '%s'\n",
+ rsCStrGetSzStr(f->pCSProgNameComp), getProgramName(pMsg));
+ return 0;
+ }
+ }
+
+ /* done with the BSD-style block filters */
+
+ if(f->f_filter_type == FILTER_PRI) {
+ /* skip messages that are incorrect priority */
+ if ( (f->f_filterData.f_pmask[pMsg->iFacility] == TABLE_NOPRI) || \
+ ((f->f_filterData.f_pmask[pMsg->iFacility] & (1<<pMsg->iSeverity)) == 0) )
+ iRet = 0;
+ else
+ iRet = 1;
+ } else {
+ assert(f->f_filter_type == FILTER_PROP); /* assert() just in case... */
+ pszPropVal = MsgGetProp(pMsg, NULL,
+ f->f_filterData.prop.pCSPropName, &pbMustBeFreed);
+
+ /* Now do the compares (short list currently ;)) */
+ switch(f->f_filterData.prop.operation ) {
+ case FIOP_CONTAINS:
+ if(rsCStrLocateInSzStr(f->f_filterData.prop.pCSCompValue, (uchar*) pszPropVal) != -1)
+ iRet = 1;
+ break;
+ case FIOP_ISEQUAL:
+ if(rsCStrSzStrCmp(f->f_filterData.prop.pCSCompValue,
+ (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
+ iRet = 1; /* process message! */
+ break;
+ case FIOP_STARTSWITH:
+ if(rsCStrSzStrStartsWithCStr(f->f_filterData.prop.pCSCompValue,
+ (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
+ iRet = 1; /* process message! */
+ break;
+ case FIOP_REGEX:
+ if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
+ (unsigned char*) pszPropVal) == 0)
+ iRet = 1;
+ break;
+ default:
+ /* here, it handles NOP (for performance reasons) */
+ assert(f->f_filterData.prop.operation == FIOP_NOP);
+ iRet = 1; /* as good as any other default ;) */
+ break;
+ }
+
+ /* now check if the value must be negated */
+ if(f->f_filterData.prop.isNegated)
+ iRet = (iRet == 1) ? 0 : 1;
+
+ /* cleanup */
+ if(pbMustBeFreed)
+ free(pszPropVal);
+
+ if(Debug) {
+ char *pszPropValDeb;
+ unsigned short pbMustBeFreedDeb;
+ pszPropValDeb = MsgGetProp(pMsg, NULL,
+ f->f_filterData.prop.pCSPropName, &pbMustBeFreedDeb);
+ printf("Filter: check for property '%s' (value '%s') ",
+ rsCStrGetSzStr(f->f_filterData.prop.pCSPropName),
+ pszPropValDeb);
+ if(f->f_filterData.prop.isNegated)
+ printf("NOT ");
+ printf("%s '%s': %s\n",
+ getFIOPName(f->f_filterData.prop.operation),
+ rsCStrGetSzStr(f->f_filterData.prop.pCSCompValue),
+ iRet ? "TRUE" : "FALSE");
+ if(pbMustBeFreedDeb)
+ free(pszPropValDeb);
+ }
+ }
+
+ return(iRet);
+}
+
+
+/* doEmergencyLoggin()
+ * ... does exactly do that. It logs messages when the subsystem has not yet
+ * been initialized. This almost always happens during initial startup or
+ * during HUPing. -- rgerhards, 2007-07-25
+ * rgerhards, 2007-08-03: as of now, this can normally no longer happen. All
+ * startup messages are now buffered until the system is ready to run. I leave
+ * this minimal implementation here in in the very remote case that it might
+ * be needed in the future or due to a program bug. Do *not* excpect this
+ * code to be called.
+ */
+static void doEmergencyLogging(msg_t *pMsg)
+{
+ assert(pMsg != NULL);
+ fprintf(stderr, "rsyslog: %s\n", pMsg->pszMSG);
+}
+
+
+/* call the configured action. Does all necessary housekeeping.
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal callAction(msg_t *pMsg, action_t *pAction)
+{
+ DEFiRet;
+
+ assert(pMsg != NULL);
+ assert(pAction != NULL);
+
+ /* first, we need to check if this is a disabled
+ * entry. If so, we must not further process it.
+ * rgerhards 2005-09-26
+ * In the future, disabled modules may be re-probed from time
+ * to time. They are in a perfectly legal state, except that the
+ * doAction method indicated that it wanted to be disabled - but
+ * we do not consider this is a solution for eternity... So we
+ * should check from time to time if affairs have improved.
+ * rgerhards, 2007-07-24
+ */
+ if(pAction->bEnabled == 0) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ if(actionIsSuspended(pAction)) {
+ CHKiRet(actionTryResume(pAction));
+ }
+
+ /* don't output marks to recently written files */
+ if ((pMsg->msgFlags & MARK) && (now - pAction->f_time) < MarkInterval / 2) {
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ /* suppress duplicate lines to this file
+ */
+ if ((pAction->f_ReduceRepeated == 1) &&
+ (pMsg->msgFlags & MARK) == 0 && getMSGLen(pMsg) == getMSGLen(pAction->f_pMsg) &&
+ !strcmp(getMSG(pMsg), getMSG(pAction->f_pMsg)) &&
+ !strcmp(getHOSTNAME(pMsg), getHOSTNAME(pAction->f_pMsg))) {
+ pAction->f_prevcount++;
+ dbgprintf("msg repeated %d times, %ld sec of %d.\n",
+ pAction->f_prevcount, now - pAction->f_time,
+ repeatinterval[pAction->f_repeatcount]);
+ /* If domark would have logged this by now, flush it now (so we don't hold
+ * isolated messages), but back off so we'll flush less often in the future.
+ */
+ if (now > REPEATTIME(pAction)) {
+ iRet = fprintlog(pAction);
+ BACKOFF(pAction);
+ }
+ } else {
+ /* new line, save it */
+ /* first check if we have a previous message stored
+ * if so, emit and then discard it first
+ */
+ if(pAction->f_pMsg != NULL) {
+ if(pAction->f_prevcount > 0)
+ fprintlog(pAction);
+ /* we do not care about iRet above - I think it's right but if we have
+ * some troubles, you know where to look at ;) -- rgerhards, 2007-08-01
+ */
+ MsgDestruct(pAction->f_pMsg);
+ }
+ pAction->f_pMsg = MsgAddRef(pMsg);
+ /* call the output driver */
+ iRet = fprintlog(pAction);
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* helper to processMsg(), used to call the configured actions. It is
+ * executed from within llExecFunc() of the action list.
+ * rgerhards, 2007-08-02
+ */
+typedef struct processMsgDoActions_s {
+ int bPrevWasSuspended; /* was the previous action suspended? */
+ msg_t *pMsg;
+} processMsgDoActions_t;
+DEFFUNC_llExecFunc(processMsgDoActions)
+{
+ DEFiRet;
+ rsRetVal iRetMod; /* return of module - we do not always pass that */
+ action_t *pAction = (action_t*) pData;
+ processMsgDoActions_t *pDoActData = (processMsgDoActions_t*) pParam;
+
+ assert(pAction != NULL);
+
+ if((pAction->bExecWhenPrevSusp == 1) && (pDoActData->bPrevWasSuspended == 0)) {
+ dbgprintf("not calling action because the previous one is not suspended\n");
+ ABORT_FINALIZE(RS_RET_OK);
+ }
+
+ iRetMod = callAction(pDoActData->pMsg, pAction);
+ if(iRetMod == RS_RET_DISCARDMSG) {
+ ABORT_FINALIZE(RS_RET_DISCARDMSG);
+ } else if(iRetMod == RS_RET_SUSPENDED) {
+ /* indicate suspension for next module to be called */
+ pDoActData->bPrevWasSuspended = 1;
+ } else {
+ pDoActData->bPrevWasSuspended = 0;
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Process (consume) a received message. Calls the actions configured.
+ * Can some time later run in its own thread. To aid this, the calling
+ * parameters should be reduced to just pMsg.
+ * See comment dated 2005-10-13 in logmsg() on multithreading.
+ * rgerhards, 2005-10-13
+ */
+static void processMsg(msg_t *pMsg)
+{
+ selector_t *f;
+ int bContinue;
+ processMsgDoActions_t DoActData;
+
+ assert(pMsg != NULL);
+
+ /* log the message to the particular outputs */
+ if (!Initialized) {
+ doEmergencyLogging(pMsg);
+ return;
+ }
+
+ bContinue = 1;
+ for (f = Files; f != NULL && bContinue ; f = f->f_next) {
+ /* This is actually the "filter logic". Looks like we need
+ * to improve it a little for complex selector line conditions. We
+ * won't do that for now, but at least we now know where
+ * to look at.
+ * 2005-09-09 rgerhards
+ * ok, we are now ready to move to something more advanced. Because
+ * of this, I am moving the actual decision code to outside this function.
+ * 2005-09-19 rgerhards
+ */
+ if(!shouldProcessThisMessage(f, pMsg)) {
+ continue;
+ }
+
+ /* ok -- from here, we have action-specific code, nothing really selector-specific -- rger 2007-08-01 */
+ DoActData.pMsg = pMsg;
+ DoActData.bPrevWasSuspended = 0;
+ if(llExecFunc(&f->llActList, processMsgDoActions, (void*)&DoActData) == RS_RET_DISCARDMSG)
+ bContinue = 0;
+ }
+}
+
+
+#ifdef USE_PTHREADS
+/* This block contains code that is only present when USE_PTHREADS is
+ * enabled. I plan to move it to some other file, but for the time
+ * being, I include it here because that saves me from the need to
+ * do so many external definitons.
+ * rgerhards, 2005-10-24
+ */
+
+/* shuts down the worker process. The worker will first finish
+ * with the message queue. Control returns, when done.
+ * This function is intended to be called during syslogd shutdown
+ * AND restart (init()!).
+ * rgerhards, 2005-10-25
+ */
+static void stopWorker(void)
+{
+ if(bRunningMultithreaded) {
+ /* we could run single-threaded if there was an error
+ * during startup. Then, we obviously do not need to
+ * do anything to stop the worker ;)
+ */
+ dbgprintf("Initiating worker thread shutdown sequence...\n");
+ /* We are now done with all messages, so we need to wake up the
+ * worker thread and then wait for it to finish.
+ */
+ bGlblDone = 1;
+ /* It's actually not "not empty" below but awaking the worker. The worker
+ * then finds out that it shall terminate and does so.
+ */
+ pthread_cond_signal(pMsgQueue->notEmpty);
+ pthread_join(thrdWorker, NULL);
+ bRunningMultithreaded = 0;
+ dbgprintf("Worker thread terminated.\n");
+ }
+}
+
+
+/* starts the worker thread. It must be made sure that the queue is
+ * already existing and the worker is NOT already running.
+ * rgerhards 2005-10-25
+ */
+static void startWorker(void)
+{
+ int i;
+ if(pMsgQueue != NULL) {
+ bGlblDone = 0; /* we are NOT done (else worker would immediately terminate) */
+ i = pthread_create(&thrdWorker, NULL, singleWorker, NULL);
+ dbgprintf("Worker thread started with state %d.\n", i);
+ bRunningMultithreaded = 1;
+ } else {
+ dbgprintf("message queue not existing, remaining single-threaded.\n");
+ }
+}
+
+
+static msgQueue *queueInit (void)
+{
+ msgQueue *q;
+
+ q = (msgQueue *)malloc(sizeof(msgQueue));
+ if (q == NULL) return (NULL);
+ if((q->pbuf = malloc(sizeof(void *) * iMainMsgQueueSize)) == NULL) {
+ free(q);
+ return NULL;
+ }
+
+ q->empty = 1;
+ q->full = 0;
+ q->head = 0;
+ q->tail = 0;
+ q->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
+ pthread_mutex_init (q->mut, NULL);
+ q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ pthread_cond_init (q->notFull, NULL);
+ q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
+ pthread_cond_init (q->notEmpty, NULL);
+
+ return (q);
+}
+
+static void queueDelete (msgQueue *q)
+{
+ pthread_mutex_destroy (q->mut);
+ free (q->mut);
+ pthread_cond_destroy (q->notFull);
+ free (q->notFull);
+ pthread_cond_destroy (q->notEmpty);
+ free (q->notEmpty);
+ free(q->pbuf);
+ free (q);
+}
+
+static void queueAdd (msgQueue *q, void* in)
+{
+ q->pbuf[q->tail] = in;
+ q->tail++;
+ if (q->tail == iMainMsgQueueSize)
+ q->tail = 0;
+ if (q->tail == q->head)
+ q->full = 1;
+ q->empty = 0;
+
+ return;
+}
+
+static void queueDel (msgQueue *q, msg_t **out)
+{
+ *out = (msg_t*) q->pbuf[q->head];
+
+ q->head++;
+ if (q->head == iMainMsgQueueSize)
+ q->head = 0;
+ if (q->head == q->tail)
+ q->empty = 1;
+ q->full = 0;
+
+ return;
+}
+
+
+/* The worker thread (so far, we have dual-threading, so only one
+ * worker thread. Having more than one worker requires considerable
+ * additional code review in regard to thread-safety.
+ */
+static void *singleWorker()
+{
+ msgQueue *fifo = pMsgQueue;
+ msg_t *pMsg;
+
+ assert(fifo != NULL);
+
+ while(!bGlblDone || !fifo->empty) {
+ pthread_mutex_lock(fifo->mut);
+ while (fifo->empty && !bGlblDone) {
+ dbgprintf("singleWorker: queue EMPTY, waiting for next message.\n");
+ pthread_cond_wait (fifo->notEmpty, fifo->mut);
+ }
+ if(!fifo->empty) {
+ /* dequeue element (still protected from mutex) */
+ queueDel(fifo, &pMsg);
+ assert(pMsg != NULL);
+ pthread_mutex_unlock(fifo->mut);
+ pthread_cond_signal (fifo->notFull);
+ /* do actual processing (the lengthy part, runs in parallel) */
+ dbgprintf("Lone worker is running...\n");
+ processMsg(pMsg);
+ MsgDestruct(pMsg);
+ /* If you need a delay for testing, here do a */
+ /* sleep(1); */
+ } else { /* the mutex must be unlocked in any case (important for termination) */
+ pthread_mutex_unlock(fifo->mut);
+ }
+
+ if(debugging_on && bGlblDone && !fifo->empty)
+ dbgprintf("Worker does not yet terminate because it still has messages to process.\n");
+ }
+
+ dbgprintf("Worker thread terminates\n");
+ pthread_exit(0);
+}
+
+/* END threads-related code */
+#endif /* #ifdef USE_PTHREADS */
+
+
+/* This method enqueues a message into the the message buffer. It also
+ * the worker thread, so that the message will be processed. If we are
+ * compiled without PTHREADS support, we simply use this method as
+ * an alias for processMsg().
+ * See comment dated 2005-10-13 in logmsg() on multithreading.
+ * rgerhards, 2005-10-24
+ */
+#ifndef USE_PTHREADS
+#define enqueueMsg(x) processMsg((x))
+#else
+static void enqueueMsg(msg_t *pMsg)
+{
+ int iRet;
+ msgQueue *fifo = pMsgQueue;
+ struct timespec t;
+
+ assert(pMsg != NULL);
+
+ if(bRunningMultithreaded == 0) {
+ /* multi-threading is not yet initialized, happens e.g.
+ * during startup and restart. rgerhards, 2005-10-25
+ */
+ dbgprintf("enqueueMsg: not yet running on multiple threads\n");
+ processMsg(pMsg);
+ } else {
+ /* "normal" mode, threading initialized */
+ pthread_mutex_lock(fifo->mut);
+
+ while (fifo->full) {
+ dbgprintf("enqueueMsg: queue FULL.\n");
+
+ clock_gettime (CLOCK_REALTIME, &t);
+ t.tv_sec += 2;
+
+ if(pthread_cond_timedwait (fifo->notFull,
+ fifo->mut, &t) != 0) {
+ dbgprintf("enqueueMsg: cond timeout, dropping message!\n");
+ goto unlock;
+ }
+ }
+ queueAdd(fifo, MsgAddRef(pMsg));
+ unlock:
+ /* now activate the worker thread */
+ pthread_mutex_unlock(fifo->mut);
+ iRet = pthread_cond_signal(fifo->notEmpty);
+ dbgprintf("EnqueueMsg signaled condition (%d)\n", iRet);
+ }
+}
+#endif /* #ifndef USE_PTHREADS */
+
+
+/* Helper to parseRFCSyslogMsg. This function parses a field up to
+ * (and including) the SP character after it. The field contents is
+ * returned in a caller-provided buffer. The parsepointer is advanced
+ * to after the terminating SP. The caller must ensure that the
+ * provided buffer is large enough to hold the to be extracted value.
+ * Returns 0 if everything is fine or 1 if either the field is not
+ * SP-terminated or any other error occurs.
+ * rger, 2005-11-24
+ */
+static int parseRFCField(char **pp2parse, char *pResult)
+{
+ char *p2parse;
+ int iRet = 0;
+
+ assert(pp2parse != NULL);
+ assert(*pp2parse != NULL);
+ assert(pResult != NULL);
+
+ p2parse = *pp2parse;
+
+ /* this is the actual parsing loop */
+ while(*p2parse && *p2parse != ' ') {
+ *pResult++ = *p2parse++;
+ }
+
+ if(*p2parse == ' ')
+ ++p2parse; /* eat SP, but only if not at end of string */
+ else
+ iRet = 1; /* there MUST be an SP! */
+ *pResult = '\0';
+
+ /* set the new parse pointer */
+ *pp2parse = p2parse;
+ return 0;
+}
+
+
+/* Helper to parseRFCSyslogMsg. This function parses the structured
+ * data field of a message. It does NOT parse inside structured data,
+ * just gets the field as whole. Parsing the single entities is left
+ * to other functions. The parsepointer is advanced
+ * to after the terminating SP. The caller must ensure that the
+ * provided buffer is large enough to hold the to be extracted value.
+ * Returns 0 if everything is fine or 1 if either the field is not
+ * SP-terminated or any other error occurs.
+ * rger, 2005-11-24
+ */
+static int parseRFCStructuredData(char **pp2parse, char *pResult)
+{
+ char *p2parse;
+ int bCont = 1;
+ int iRet = 0;
+
+ assert(pp2parse != NULL);
+ assert(*pp2parse != NULL);
+ assert(pResult != NULL);
+
+ p2parse = *pp2parse;
+
+ /* this is the actual parsing loop
+ * Remeber: structured data starts with [ and includes any characters
+ * until the first ] followed by a SP. There may be spaces inside
+ * structured data. There may also be \] inside the structured data, which
+ * do NOT terminate an element.
+ */
+ if(*p2parse != '[')
+ return 1; /* this is NOT structured data! */
+
+ while(bCont) {
+ if(*p2parse == '\0') {
+ iRet = 1; /* this is not valid! */
+ bCont = 0;
+ } else if(*p2parse == '\\' && *(p2parse+1) == ']') {
+ /* this is escaped, need to copy both */
+ *pResult++ = *p2parse++;
+ *pResult++ = *p2parse++;
+ } else if(*p2parse == ']' && *(p2parse+1) == ' ') {
+ /* found end, just need to copy the ] and eat the SP */
+ *pResult++ = *p2parse;
+ p2parse += 2;
+ bCont = 0;
+ } else {
+ *pResult++ = *p2parse++;
+ }
+ }
+
+ if(*p2parse == ' ')
+ ++p2parse; /* eat SP, but only if not at end of string */
+ else
+ iRet = 1; /* there MUST be an SP! */
+ *pResult = '\0';
+
+ /* set the new parse pointer */
+ *pp2parse = p2parse;
+ return 0;
+}
+
+/* parse a RFC-formatted syslog message. This function returns
+ * 0 if processing of the message shall continue and 1 if something
+ * went wrong and this messe should be ignored. This function has been
+ * implemented in the effort to support syslog-protocol. Please note that
+ * the name (parse *RFC*) stems from the hope that syslog-protocol will
+ * some time become an RFC. Do not confuse this with informational
+ * RFC 3164 (which is legacy syslog).
+ *
+ * currently supported format:
+ *
+ * <PRI>VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG
+ *
+ * <PRI> is already stripped when this function is entered. VERSION already
+ * has been confirmed to be "1", but has NOT been stripped from the message.
+ *
+ * rger, 2005-11-24
+ */
+static int parseRFCSyslogMsg(msg_t *pMsg, int flags)
+{
+ char *p2parse;
+ char *pBuf;
+ int bContParse = 1;
+
+ assert(pMsg != NULL);
+ assert(pMsg->pszUxTradMsg != NULL);
+ p2parse = (char*) pMsg->pszUxTradMsg;
+
+ /* do a sanity check on the version and eat it */
+ assert(p2parse[0] == '1' && p2parse[1] == ' ');
+ p2parse += 2;
+
+ /* Now get us some memory we can use as a work buffer while parsing.
+ * We simply allocated a buffer sufficiently large to hold all of the
+ * message, so we can not run into any troubles. I think this is
+ * more wise then to use individual buffers.
+ */
+ if((pBuf = malloc(sizeof(char)* strlen(p2parse) + 1)) == NULL)
+ return 1;
+
+ /* IMPORTANT NOTE:
+ * Validation is not actually done below nor are any errors handled. I have
+ * NOT included this for the current proof of concept. However, it is strongly
+ * advisable to add it when this code actually goes into production.
+ * rgerhards, 2005-11-24
+ */
+
+ /* TIMESTAMP */
+ if(srSLMGParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == FALSE) {
+ dbgprintf("no TIMESTAMP detected!\n");
+ bContParse = 0;
+ flags |= ADDDATE;
+ }
+
+ if (flags & ADDDATE) {
+ getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
+ }
+
+ /* HOSTNAME */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf);
+ MsgSetHOSTNAME(pMsg, pBuf);
+ } else {
+ /* we can not parse, so we get the system we
+ * received the data from.
+ */
+ MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
+ }
+
+ /* APP-NAME */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf);
+ MsgSetAPPNAME(pMsg, pBuf);
+ }
+
+ /* PROCID */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf);
+ MsgSetPROCID(pMsg, pBuf);
+ }
+
+ /* MSGID */
+ if(bContParse) {
+ parseRFCField(&p2parse, pBuf);
+ MsgSetMSGID(pMsg, pBuf);
+ }
+
+ /* STRUCTURED-DATA */
+ if(bContParse) {
+ parseRFCStructuredData(&p2parse, pBuf);
+ MsgSetStructuredData(pMsg, pBuf);
+ }
+
+ /* MSG */
+ MsgSetMSG(pMsg, p2parse);
+
+ return 0; /* all ok */
+}
+/* parse a legay-formatted syslog message. This function returns
+ * 0 if processing of the message shall continue and 1 if something
+ * went wrong and this messe should be ignored. This function has been
+ * implemented in the effort to support syslog-protocol.
+ * rger, 2005-11-24
+ * As of 2006-01-10, I am removing the logic to continue parsing only
+ * when a valid TIMESTAMP is detected. Validity of other fields already
+ * is ignored. This is due to the fact that the parser has grown smarter
+ * and is now more able to understand different dialects of the syslog
+ * message format. I do not expect any bad side effects of this change,
+ * but I thought I log it in this comment.
+ * rgerhards, 2006-01-10
+ */
+static int parseLegacySyslogMsg(msg_t *pMsg, int flags)
+{
+ char *p2parse;
+ char *pBuf;
+ char *pWork;
+ rsCStrObj *pStrB;
+ int iCnt;
+ int bTAGCharDetected;
+
+ assert(pMsg != NULL);
+ assert(pMsg->pszUxTradMsg != NULL);
+ p2parse = (char*) pMsg->pszUxTradMsg;
+
+ /*
+ * Check to see if msg contains a timestamp
+ */
+ if(srSLMGParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
+ p2parse += 16;
+ else {
+ flags |= ADDDATE;
+ }
+
+ /* here we need to check if the timestamp is valid. If it is not,
+ * we can not continue to parse but must treat the rest as the
+ * MSG part of the message (as of RFC 3164).
+ * rgerhards 2004-12-03
+ */
+ (void) time(&now);
+ if (flags & ADDDATE) {
+ getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
+ }
+
+ /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we
+ * do this only when the user has not forbidden this. I now introduce some
+ * code that allows a user to configure rsyslogd to treat the rest of the
+ * message as MSG part completely. In this case, the hostname will be the
+ * machine that we received the message from and the tag will be empty. This
+ * is meant to be an interim solution, but for now it is in the code.
+ */
+
+ if(bParseHOSTNAMEandTAG && !(flags & INTERNAL_MSG)) {
+ /* parse HOSTNAME - but only if this is network-received!
+ * rger, 2005-11-14: we still have a problem with BSD messages. These messages
+ * do NOT include a host name. In most cases, this leads to the TAG to be treated
+ * as hostname and the first word of the message as the TAG. Clearly, this is not
+ * of advantage ;) I think I have now found a way to handle this situation: there
+ * are certain characters which are frequently used in TAG (e.g. ':'), which are
+ * *invalid* in host names. So while parsing the hostname, I check for these characters.
+ * If I find them, I set a simple flag but continue. After parsing, I check the flag.
+ * If it was set, then we most probably do not have a hostname but a TAG. Thus, I change
+ * the fields. I think this logic shall work with any type of syslog message.
+ */
+ bTAGCharDetected = 0;
+ if(pMsg->bParseHOSTNAME) {
+ /* TODO: quick and dirty memory allocation */
+ if((pBuf = malloc(sizeof(char)* strlen(p2parse) +1)) == NULL)
+ return 1;
+ pWork = pBuf;
+ /* this is the actual parsing loop */
+ while(*p2parse && *p2parse != ' ' && *p2parse != ':') {
+ if( *p2parse == '[' || *p2parse == ']' || *p2parse == '/')
+ bTAGCharDetected = 1;
+ *pWork++ = *p2parse++;
+ }
+ /* we need to handle ':' seperately, because it terminates the
+ * TAG - so we also need to terminate the parser here!
+ */
+ if(*p2parse == ':') {
+ bTAGCharDetected = 1;
+ ++p2parse;
+ } else if(*p2parse == ' ')
+ ++p2parse;
+ *pWork = '\0';
+ MsgAssignHOSTNAME(pMsg, pBuf);
+ }
+ /* check if we seem to have a TAG */
+ if(bTAGCharDetected) {
+ /* indeed, this smells like a TAG, so lets use it for this. We take
+ * the HOSTNAME from the sender system instead.
+ */
+ dbgprintf("HOSTNAME contains invalid characters, assuming it to be a TAG.\n");
+ moveHOSTNAMEtoTAG(pMsg);
+ MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
+ }
+
+ /* now parse TAG - that should be present in message from
+ * all sources.
+ * This code is somewhat not compliant with RFC 3164. As of 3164,
+ * the TAG field is ended by any non-alphanumeric character. In
+ * practice, however, the TAG often contains dashes and other things,
+ * which would end the TAG. So it is not desirable. As such, we only
+ * accept colon and SP to be terminators. Even there is a slight difference:
+ * a colon is PART of the TAG, while a SP is NOT part of the tag
+ * (it is CONTENT). Finally, we allow only up to 32 characters for
+ * TAG, as it is specified in RFC 3164.
+ */
+ /* The following code in general is quick & dirty - I need to get
+ * it going for a test, rgerhards 2004-11-16 */
+ /* lol.. we tried to solve it, just to remind ourselfs that 32 octets
+ * is the max size ;) we need to shuffle the code again... Just for
+ * the records: the code is currently clean, but we could optimize it! */
+ if(!bTAGCharDetected) {
+ char *pszTAG;
+ if((pStrB = rsCStrConstruct()) == NULL)
+ return 1;
+ rsCStrSetAllocIncrement(pStrB, 33);
+ pWork = pBuf;
+ iCnt = 0;
+ while(*p2parse && *p2parse != ':' && *p2parse != ' ' && iCnt < 32) {
+ rsCStrAppendChar(pStrB, *p2parse++);
+ ++iCnt;
+ }
+ if(*p2parse == ':') {
+ ++p2parse;
+ rsCStrAppendChar(pStrB, ':');
+ }
+ rsCStrFinish(pStrB);
+
+ pszTAG = (char*) rsCStrConvSzStrAndDestruct(pStrB);
+ if(pszTAG == NULL)
+ { /* rger, 2005-11-10: no TAG found - this implies that what
+ * we have considered to be the HOSTNAME is most probably the
+ * TAG. We consider it so probable, that we now adjust it
+ * that way. So we pick up the previously set hostname, assign
+ * it to tag and use the sender system (from IP stack) as
+ * the hostname. This situation is the standard case with
+ * stock BSD syslogd.
+ */
+ dbgprintf("No TAG in message, assuming that HOSTNAME is missing.\n");
+ moveHOSTNAMEtoTAG(pMsg);
+ MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
+ }
+ else
+ { /* we have a TAG, so we can happily set it ;) */
+ MsgAssignTAG(pMsg, pszTAG);
+ }
+ } else {
+ /* we have no TAG, so we ... */
+ /*DO NOTHING*/;
+ }
+ } else {
+ /* we enter this code area when the user has instructed rsyslog NOT
+ * to parse HOSTNAME and TAG - rgerhards, 2006-03-13
+ */
+ if(!(flags & INTERNAL_MSG))
+ {
+ dbgprintf("HOSTNAME and TAG not parsed by user configuraton.\n");
+ MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
+ }
+ }
+
+ /* The rest is the actual MSG */
+ MsgSetMSG(pMsg, p2parse);
+
+ return 0; /* all ok */
+}
+
+
+/*
+ * Log a message to the appropriate log files, users, etc. based on
+ * the priority.
+ * rgerhards 2004-11-08: actually, this also decodes all but the PRI part.
+ * rgerhards 2004-11-09: ... but only, if syslogd could properly be initialized
+ * if not, we use emergency logging to the console and in
+ * this case, no further decoding happens.
+ * changed to no longer receive a plain message but a msg object instead.
+ * rgerhards-2004-11-16: OK, we are now up to another change... This method
+ * actually needs to PARSE the message. How exactly this needs to happen depends on
+ * a number of things. Most importantly, it depends on the source. For example,
+ * locally received messages (SOURCE_UNIXAF) do NOT have a hostname in them. So
+ * we need to treat them differntly form network-received messages which have.
+ * Well, actually not all network-received message really have a hostname. We
+ * can just hope they do, but we can not be sure. So this method tries to find
+ * whatever can be found in the message and uses that... Obviously, there is some
+ * potential for misinterpretation, which we simply can not solve under the
+ * circumstances given.
+ */
+void logmsg(int pri, msg_t *pMsg, int flags)
+{
+ char *msg;
+ char PRItext[20];
+
+ assert(pMsg != NULL);
+ assert(pMsg->pszUxTradMsg != NULL);
+ msg = (char*) pMsg->pszUxTradMsg;
+ dbgprintf("logmsg: %s, flags %x, from '%s', msg %s\n",
+ textpri(PRItext, sizeof(PRItext) / sizeof(char), pri),
+ flags, getRcvFrom(pMsg), msg);
+
+ /* rger 2005-11-24 (happy thanksgiving!): we now need to check if we have
+ * a traditional syslog message or one formatted according to syslog-protocol.
+ * We need to apply different parsers depending on that. We use the
+ * -protocol VERSION field for the detection.
+ */
+ if(msg[0] == '1' && msg[1] == ' ') {
+ dbgprintf("Message has syslog-protocol format.\n");
+ setProtocolVersion(pMsg, 1);
+ if(parseRFCSyslogMsg(pMsg, flags) == 1)
+ return;
+ } else { /* we have legacy syslog */
+ dbgprintf("Message has legacy syslog format.\n");
+ setProtocolVersion(pMsg, 0);
+ if(parseLegacySyslogMsg(pMsg, flags) == 1)
+ return;
+ }
+
+ /* ---------------------- END PARSING ---------------- */
+
+ /* rgerhards, 2005-10-13: if we consider going multi-threaded, this
+ * is probably the best point to split between a producer and a consumer
+ * thread. In general, with the first multi-threaded approach, we should
+ * NOT try to do more than have a single producer and consumer, at least
+ * if both are from the current code base. The issue is that this code
+ * was definitely not written with reentrancy in mind and uses a lot of
+ * global variables. So it is very dangerous to simply go ahead and multi
+ * thread it. However, I think there is a clear distinction between
+ * producer (where data is received) and consumer (where the actions are).
+ * It should be fairly safe to create a single thread for each and run them
+ * concurrently, thightly coupled via an in-memory queue. Even with this
+ * limited multithraeding, benefits are immediate: the lengthy actions
+ * (database writes!) are de-coupled from the receivers, what should result
+ * in less likely message loss (loss due to receiver overrun). It also allows
+ * us to utilize 2-cpu systems, which will soon be common given the current
+ * advances in multicore CPU hardware. So this is well worth trying.
+ * Another plus of this two-thread-approach would be that it can easily be configured,
+ * so if there are compatibility issues with the threading libs, we could simply
+ * disable it (as a makefile feature).
+ * There is one important thing to keep in mind when doing this basic
+ * multithreading. The syslog/tcp message forwarder manipulates a structutre
+ * that is used by the main thread, which actually sends the data. This
+ * structure must be guarded by a mutex, else we will have race conditions and
+ * some very bad things could happen.
+ *
+ * Additional consumer threads might be added relatively easy for new receivers,
+ * e.g. if we decide to move RFC 3195 via liblogging natively into rsyslogd.
+ *
+ * To aid this functionality, I am moving the rest of the code (the actual
+ * consumer) to its own method, now called "processMsg()".
+ *
+ * rgerhards, 2005-10-25: as of now, the dual-threading code is now in place.
+ * It is an optional feature and even when enabled, rsyslogd will run single-threaded
+ * if it gets any errors during thread creation.
+ */
+
+ pMsg->msgFlags = flags;
+ enqueueMsg(pMsg);
+}
+
+
+/* rgerhards 2004-11-09: fprintlog() is the actual driver for
+ * the output channel. It receives the channel description (f) as
+ * well as the message and outputs them according to the channel
+ * semantics. The message is typically already contained in the
+ * channel save buffer (f->f_prevline). This is not only the case
+ * when a message was already repeated but also when a new message
+ * arrived.
+ * rgerhards 2007-08-01: interface changed to use action_t
+ */
+rsRetVal fprintlog(action_t *pAction)
+{
+ msg_t *pMsgSave; /* to save current message pointer, necessary to restore
+ it in case it needs to be updated (e.g. repeated msgs) */
+ pMsgSave = NULL; /* indicate message poiner not saved */
+ DEFiRet;
+ int i;
+
+ /* first check if this is a regular message or the repeation of
+ * a previous message. If so, we need to change the message text
+ * to "last message repeated n times" and then go ahead and write
+ * it. Please note that we can not modify the message object, because
+ * that would update it in other selectors as well. As such, we first
+ * need to create a local copy of the message, which we than can update.
+ * rgerhards, 2007-07-10
+ */
+ if(pAction->f_prevcount > 1) {
+ msg_t *pMsg;
+ uchar szRepMsg[64];
+ snprintf((char*)szRepMsg, sizeof(szRepMsg), "last message repeated %d times",
+ pAction->f_prevcount);
+
+ if((pMsg = MsgDup(pAction->f_pMsg)) == NULL) {
+ /* it failed - nothing we can do against it... */
+ dbgprintf("Message duplication failed, dropping repeat message.\n");
+ return RS_RET_ERR;
+ }
+
+ /* We now need to update the other message properties.
+ * ... RAWMSG is a problem ... Please note that digital
+ * signatures inside the message are also invalidated.
+ */
+ getCurrTime(&(pMsg->tRcvdAt));
+ getCurrTime(&(pMsg->tTIMESTAMP));
+ MsgSetMSG(pMsg, (char*)szRepMsg);
+ MsgSetRawMsg(pMsg, (char*)szRepMsg);
+
+ pMsgSave = pAction->f_pMsg; /* save message pointer for later restoration */
+ pAction->f_pMsg = pMsg; /* use the new msg (pointer will be restored below) */
+ }
+
+ dbgprintf("Called fprintlog, logging to %s", modGetStateName(pAction->pMod));
+
+ pAction->f_time = now; /* we need this for message repeation processing TODO: why must "now" be global? */
+
+ /* When we reach this point, we have a valid, non-disabled action.
+ * So let's execute it. -- rgerhards, 2007-07-24
+ */
+ /* here we must loop to process all requested strings */
+
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ if((pAction->ppMsgs[i] = tplToString(pAction->ppTpl[i], pAction->f_pMsg)) == NULL) {
+ dbgprintf("memory alloc failed while generating message strings - message ignored\n");
+ glblHadMemShortage = 1;
+ iRet = RS_RET_OUT_OF_MEMORY;
+ goto finalize_it;
+ }
+ }
+ /* call configured action */
+ iRet = pAction->pMod->mod.om.doAction(pAction->ppMsgs, pAction->f_pMsg->msgFlags, pAction->pModData);
+
+ if(iRet == RS_RET_DISABLE_ACTION) {
+ dbgprintf("Action requested to be disabled, done that.\n");
+ pAction->bEnabled = 0; /* that's it... */
+ }
+
+ if(iRet == RS_RET_SUSPENDED) {
+ dbgprintf("Action requested to be suspended, done that.\n");
+ actionSuspend(pAction);
+ }
+
+ if(iRet == RS_RET_OK)
+ pAction->f_prevcount = 0; /* message process, so we start a new cycle */
+
+finalize_it:
+ /* cleanup */
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ if(pAction->ppMsgs[i] != NULL) {
+ free(pAction->ppMsgs[i]);
+ pAction->ppMsgs[i] = NULL;
+ }
+ }
+
+ if(pMsgSave != NULL) {
+ /* we had saved the original message pointer. That was
+ * done because we needed to create a temporary one
+ * (most often for "message repeated n time" handling. If so,
+ * we need to restore the original one now, so that procesing
+ * can continue as normal. We also need to discard the temporary
+ * one, as we do not like memory leaks ;) Please note that the original
+ * message object will be discarded by our callers, so this is nothing
+ * of our buisiness. rgerhards, 2007-07-10
+ */
+ MsgDestruct(pAction->f_pMsg);
+ pAction->f_pMsg = pMsgSave; /* restore it */
+ }
+
+ return iRet;
+}
+
+
+static void reapchild()
+{
+ int saved_errno = errno;
+ signal(SIGCHLD, reapchild); /* reset signal handler -ASP */
+ while(waitpid(-1, NULL, WNOHANG) > 0);
+ errno = saved_errno;
+}
+
+
+/* helper to domark to flush the individual action links via llExecFunc
+ * rgerhards, 2007-08-02
+ */
+DEFFUNC_llExecFunc(domarkActions)
+{
+ action_t *pAction = (action_t*) pData;
+
+ assert(pAction != NULL);
+
+ if (pAction->f_prevcount && now >= REPEATTIME(pAction)) {
+ dbgprintf("flush %s: repeated %d times, %d sec.\n",
+ modGetStateName(pAction->pMod), pAction->f_prevcount,
+ repeatinterval[pAction->f_repeatcount]);
+ fprintlog(pAction);
+ BACKOFF(pAction);
+ }
+
+ return RS_RET_OK; /* we ignore errors, we can not do anything either way */
+}
+
+
+/* This method writes mark messages and - some time later - flushes reapeat
+ * messages.
+ * This method was initially called by an alarm handler. As such, it could potentially
+ * have race-conditons. For details, see
+ * http://lkml.org/lkml/2005/3/26/37
+ * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=301511
+ * I have now changed it so that the alarm handler only sets a global variable, telling
+ * the main thread that it must do mark processing. So domark() is now called from the
+ * main thread itself, which is the only thing to make sure rsyslogd will not do
+ * strange things. The way it originally was seemed to work because mark occurs very
+ * seldom. However, the code called was anything else but reentrant, so it was like
+ * russian roulette.
+ * rgerhards, 2005-10-20
+ */
+static void domark(void)
+{
+ register selector_t *f;
+
+ if (MarkInterval > 0) {
+ now = time(NULL);
+ MarkSeq += TIMERINTVL;
+ if (MarkSeq >= MarkInterval) {
+ logmsgInternal(LOG_INFO, "-- MARK --", ADDDATE|MARK);
+ MarkSeq = 0;
+ }
+
+ /* see if we need to flush any "message repeated n times"... */
+ for (f = Files; f != NULL ; f = f->f_next) {
+ llExecFunc(&f->llActList, domarkActions, NULL);
+ }
+ }
+}
+
+
+/* This is the alarm handler setting the global variable for
+ * domark request. See domark() comments for further details.
+ * rgerhards, 2005-10-20
+ */
+static void domarkAlarmHdlr()
+{
+ bRequestDoMark = 1; /* request alarm */
+ (void) signal(SIGALRM, domarkAlarmHdlr);
+ (void) alarm(TIMERINTVL);
+}
+
+
+static void debug_switch()
+{
+ dbgprintf("Switching debugging_on to %s\n", (debugging_on == 0) ? "true" : "false");
+ debugging_on = (debugging_on == 0) ? 1 : 0;
+ signal(SIGUSR1, debug_switch);
+}
+
+
+/*
+ * Add a string to error message and send it to logerror()
+ * The error message is passed to snprintf() and must be
+ * correctly formatted for it (containing a single %s param).
+ * rgerhards 2005-09-19
+ */
+void logerrorSz(char *type, char *errMsg)
+{
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf), type, errMsg);
+ buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
+ logerror(buf);
+ return;
+}
+
+/*
+ * Add an integer to error message and send it to logerror()
+ * The error message is passed to snprintf() and must be
+ * correctly formatted for it (containing a single %d param).
+ * rgerhards 2005-09-19
+ */
+void logerrorInt(char *type, int errCode)
+{
+ char buf[1024];
+
+ snprintf(buf, sizeof(buf), type, errCode);
+ buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
+ logerror(buf);
+ return;
+}
+
+/* Print syslogd errors some place.
+ */
+void logerror(char *type)
+{
+ char buf[1024];
+
+ dbgprintf("Called logerr, msg: %s\n", type);
+
+ if (errno == 0)
+ snprintf(buf, sizeof(buf), "%s", type);
+ else
+ snprintf(buf, sizeof(buf), "%s: %s", type, strerror(errno));
+ buf[sizeof(buf)/sizeof(char) - 1] = '\0'; /* just to be on the safe side... */
+ errno = 0;
+ logmsgInternal(LOG_SYSLOG|LOG_ERR, buf, ADDDATE);
+ return;
+}
+
+/* doDie() is a signal handler. If called, it sets the bFinished variable
+ * to indicate the program should terminate. However, it does not terminate
+ * it itself, because that causes issues with multi-threading. The actual
+ * termination is then done on the main thread. This solution might introduce
+ * a minimal delay, but it is much cleaner than the approach of doing everything
+ * inside the signal handler.
+ * rgerhards, 2005-10-26
+ */
+static void doDie(int sig)
+{
+ dbgprintf("DoDie called.\n");
+ bFinished = sig;
+}
+
+
+/* die() is called when the program shall end. This typically only occurs
+ * during sigterm or during the initialization. If you search for places where
+ * it is called, search for "die", not "die(", because the later will not find
+ * setting of signal handlers! As die() is intended to shutdown rsyslogd, it is
+ * safe to call exit() here. Just make sure that die() itself is not called
+ * at inapropriate places. As a general rule of thumb, it is a bad idea to add
+ * any calls to die() in new code!
+ * rgerhards, 2005-10-24
+ */
+static void die(int sig)
+{
+ char buf[256];
+ int i;
+
+ if (sig) {
+ dbgprintf(" exiting on signal %d\n", sig);
+ (void) snprintf(buf, sizeof(buf) / sizeof(char),
+ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
+ "\" x-pid=\"%d\"]" " exiting on signal %d.",
+ (int) myPid, sig);
+ errno = 0;
+ logmsgInternal(LOG_SYSLOG|LOG_INFO, buf, ADDDATE);
+ }
+
+ /* Free ressources and close connections */
+ freeSelectors();
+
+#ifdef USE_PTHREADS
+ /* Worker threads are stopped by freeSelectors() */
+ queueDelete(pMsgQueue); /* delete fifo here! */
+ pMsgQueue = NULL;
+#endif
+
+ /* now clean up the listener part */
+#ifdef SYSLOG_INET
+ /* Close the UNIX sockets. */
+ for (i = 0; i < nfunix; i++)
+ if (funix[i] != -1)
+ close(funix[i]);
+ /* Close the UDP inet socket. */
+ closeUDPListenSockets();
+ /* Close the TCP inet socket. */
+ if(sockTCPLstn != NULL && *sockTCPLstn) {
+ deinit_tcp_listener();
+ }
+#endif
+
+ /* Clean-up files. */
+ for (i = 0; i < nfunix; i++)
+ if (funixn[i] && funix[i] != -1)
+ (void)unlink(funixn[i]);
+
+ /* rger 2005-02-22
+ * now clean up the in-memory structures. OK, the OS
+ * would also take care of that, but if we do it
+ * ourselfs, this makes finding memory leaks a lot
+ * easier.
+ */
+ tplDeleteAll();
+
+ remove_pid(PidFile);
+ if(glblHadMemShortage)
+ dbgprintf("Had memory shortage at least once during the run.\n");
+
+ /* de-init some modules */
+ modExitIminternal();
+
+ /*TODO: the module config command handlers must also be freed! */
+
+ /* TODO: this would also be the right place to de-init the builtin output modules. We
+ * do not currently do that, because the module interface does not allow for
+ * it. This will come some time later (it's essential with loadable modules).
+ * For the time being, this is a memory leak on exit, but as the process is
+ * terminated, we do not really bother about it.
+ * rgerhards, 2007-08-03
+ * I have added some code now, but all that mod init/de-init should be moved to
+ * init, so that modules are unloaded and reloaded on HUP to. Eventually it should go
+ * into freeSelectors() - but that needs to be seen. -- rgerhards, 2007-08-09
+ */
+ modUnloadAndDestructAll();
+
+ dbgprintf("Clean shutdown completed, bye.\n");
+ exit(0); /* "good" exit, this is the terminator function for rsyslog [die()] */
+}
+
+/*
+ * Signal handler to terminate the parent process.
+ * rgerhards, 2005-10-24: this is only called during forking of the
+ * detached syslogd. I consider this method to be safe.
+ */
+static void doexit()
+{
+ exit(0); /* "good" exit, only during child-creation */
+}
+
+
+/* parse an allowed sender config line and add the allowed senders
+ * (if the line is correct).
+ * rgerhards, 2005-09-27
+ */
+static rsRetVal addAllowedSenderLine(char* pName, uchar** ppRestOfConfLine)
+{
+#ifdef SYSLOG_INET
+ struct AllowedSenders **ppRoot;
+ struct AllowedSenders **ppLast;
+ rsParsObj *pPars;
+ rsRetVal iRet;
+ struct NetAddr *uIP = NULL;
+ int iBits;
+#endif
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+ assert(*ppRestOfConfLine != NULL);
+
+#ifndef SYSLOG_INET
+ errno = 0;
+ logerror("config file contains allowed sender list, but rsyslogd "
+ "compiled without Internet support - line ignored");
+ return RS_RET_ERR;
+#else
+ if(!strcasecmp(pName, "udp")) {
+ ppRoot = &pAllowedSenders_UDP;
+ ppLast = &pLastAllowedSenders_UDP;
+ } else if(!strcasecmp(pName, "tcp")) {
+ ppRoot = &pAllowedSenders_TCP;
+ ppLast = &pLastAllowedSenders_TCP;
+ } else {
+ logerrorSz("Invalid protocol '%s' in allowed sender "
+ "list, line ignored", pName);
+ return RS_RET_ERR;
+ }
+
+ /* OK, we now know the protocol and have valid list pointers.
+ * So let's process the entries. We are using the parse class
+ * for this.
+ */
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, (uchar*) *ppRestOfConfLine) != RS_RET_OK)) {
+ logerrorInt("Error %d constructing parser object - ignoring allowed sender list", iRet);
+ return(iRet);
+ }
+
+ while(!parsIsAtEndOfParseString(pPars)) {
+ if(parsPeekAtCharAtParsPtr(pPars) == '#')
+ break; /* a comment-sign stops processing of line */
+ /* now parse a single IP address */
+ if((iRet = parsAddrWithBits(pPars, &uIP, &iBits)) != RS_RET_OK) {
+ logerrorInt("Error %d parsing address in allowed sender"
+ "list - ignoring.", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+ if((iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits))
+ != RS_RET_OK) {
+ logerrorInt("Error %d adding allowed sender entry "
+ "- ignoring.", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+ free (uIP); /* copy stored in AllowedSenders list */
+ }
+
+ /* cleanup */
+ *ppRestOfConfLine += parsGetCurrentPosition(pPars);
+ return rsParsDestruct(pPars);
+#endif /*#ifndef SYSLOG_INET */
+}
+
+
+/* process a directory and include all of its files into
+ * the current config file. There is no specific order of inclusion,
+ * files are included in the order they are read from the directory.
+ * The caller must have make sure that the provided parameter is
+ * indeed a directory.
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal doIncludeDirectory(uchar *pDirName)
+{
+ DEFiRet;
+ int iEntriesDone = 0;
+ DIR *pDir;
+ union {
+ struct dirent d;
+ char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
+ } u;
+ struct dirent *res;
+ size_t iDirNameLen;
+ size_t iFileNameLen;
+ uchar szFullFileName[MAXFNAME];
+
+ assert(pDirName != NULL);
+
+ if((pDir = opendir((char*) pDirName)) == NULL) {
+ logerror("error opening include directory");
+ ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
+ }
+
+ /* prepare file name buffer */
+ iDirNameLen = strlen((char*) pDirName);
+ memcpy(szFullFileName, pDirName, iDirNameLen);
+
+ /* now read the directory */
+ iEntriesDone = 0;
+ while(readdir_r(pDir, &u.d, &res) == 0) {
+ if(res == NULL)
+ break; /* this also indicates end of directory */
+ if(res->d_type != DT_REG)
+ continue; /* we are not interested in special files */
+ if(res->d_name[0] == '.')
+ continue; /* these files we are also not interested in */
+ ++iEntriesDone;
+ /* construct filename */
+ iFileNameLen = strnlen(res->d_name, NAME_MAX);
+ memcpy(szFullFileName + iDirNameLen, res->d_name, iFileNameLen);
+ *(szFullFileName + iDirNameLen + iFileNameLen) = '\0';
+ dbgprintf("including file '%s'\n", szFullFileName);
+ processConfFile(szFullFileName);
+ /* we deliberately ignore the iRet of processConfFile() - this is because
+ * failure to process one file does not mean all files will fail. By ignoring,
+ * we retry with the next file, which is the best thing we can do. -- rgerhards, 2007-08-01
+ */
+ }
+
+ if(iEntriesDone == 0) {
+ /* I just make it a debug output, because I can think of a lot of cases where it
+ * makes sense not to have any files. E.g. a system maintainer may place a $Include
+ * into the config file just in case, when additional modules be installed. When none
+ * are installed, the directory will be empty, which is fine. -- rgerhards 2007-08-01
+ */
+ dbgprintf("warning: the include directory contained no files - this may be ok.\n");
+ }
+
+finalize_it:
+ if(pDir != NULL)
+ closedir(pDir);
+
+ return iRet;
+}
+
+
+/* process a $include config line. That type of line requires
+ * inclusion of another file.
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal doIncludeLine(uchar **pp, __attribute__((unused)) void* pVal)
+{
+ DEFiRet;
+ uchar cfgFile[MAXFNAME];
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) cfgFile, sizeof(cfgFile) / sizeof(uchar), ' ') != 0) {
+ logerror("could not extract group name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ if(*(cfgFile+strlen((char*) cfgFile) - 1) == '/') {
+ dbgprintf("requested to include directory '%s'\n", cfgFile);
+ iRet = doIncludeDirectory(cfgFile);
+ } else {
+ dbgprintf("Requested to include config file '%s'\n", cfgFile);
+ iRet = processConfFile(cfgFile);
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* process a $ModLoad config line.
+ * As of now, it is a dummy, that will later evolve into the
+ * loader for plug-ins.
+ * rgerhards, 2007-07-21
+ */
+static rsRetVal doModLoad(uchar **pp, __attribute__((unused)) void* pVal)
+{
+ DEFiRet;
+ uchar szName[512];
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+
+ if(getSubString(pp, (char*) szName, sizeof(szName) / sizeof(uchar), ' ') != 0) {
+ logerror("could not extract group name");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ dbgprintf("Requested to load module '%s'\n", szName);
+
+ if(!strcmp((char*)szName, "MySQL")) {
+ bModMySQLLoaded = 1;
+ } else {
+ logerrorSz("$ModLoad with invalid module name '%s' - currently 'MySQL' only supported",
+ (char*) szName);
+ }
+
+ skipWhiteSpace(pp); /* skip over any whitespace */
+
+finalize_it:
+ return iRet;
+}
+
+/* parse and interpret a $-config line that starts with
+ * a name (this is common code). It is parsed to the name
+ * and then the proper sub-function is called to handle
+ * the actual directive.
+ * rgerhards 2004-11-17
+ * rgerhards 2005-06-21: previously only for templates, now
+ * generalized.
+ */
+static rsRetVal doNameLine(uchar **pp, void* pVal)
+{
+ DEFiRet;
+ uchar *p;
+ enum eDirective eDir;
+ char szName[128];
+
+ assert(pp != NULL);
+ p = *pp;
+ assert(p != NULL);
+
+ eDir = (enum eDirective) pVal; /* this time, it actually is NOT a pointer! */
+
+ if(getSubString(&p, szName, sizeof(szName) / sizeof(char), ',') != 0) {
+ logerror("Invalid config line: could not extract name - line ignored");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ if(*p == ',')
+ ++p; /* comma was eaten */
+
+ /* we got the name - now we pass name & the rest of the string
+ * to the subfunction. It makes no sense to do further
+ * parsing here, as this is in close interaction with the
+ * respective subsystem. rgerhards 2004-11-17
+ */
+
+ switch(eDir) {
+ case DIR_TEMPLATE:
+ tplAddLine(szName, &p);
+ break;
+ case DIR_OUTCHANNEL:
+ ochAddLine(szName, &p);
+ break;
+ case DIR_ALLOWEDSENDER:
+ addAllowedSenderLine(szName, &p);
+ break;
+ default:/* we do this to avoid compiler warning - not all
+ * enum values call this function, so an incomplete list
+ * is quite ok (but then we should not run into this code,
+ * so at least we log a debug warning).
+ */
+ dbgprintf("INTERNAL ERROR: doNameLine() called with invalid eDir %d.\n",
+ eDir);
+ break;
+ }
+
+ *pp = p;
+
+finalize_it:
+ return iRet;
+}
+
+
+/* set the action resume interval
+ */
+static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
+{
+ return actionSetGlobalResumeInterval(iNewVal);
+}
+
+
+/* set the processes umask (upon configuration request)
+ */
+static rsRetVal setUmask(void __attribute__((unused)) *pVal, int iUmask)
+{
+ umask(iUmask);
+ dbgprintf("umask set to 0%3.3o.\n", iUmask);
+
+ return RS_RET_OK;
+}
+
+
+/* Parse and interpret a system-directive in the config line
+ * A system directive is one that starts with a "$" sign. It offers
+ * extended configuration parameters.
+ * 2004-11-17 rgerhards
+ */
+rsRetVal cfsysline(uchar *p)
+{
+ DEFiRet;
+ uchar szCmd[64];
+ uchar errMsg[128]; /* for dynamic error messages */
+
+ assert(p != NULL);
+ errno = 0;
+ if(getSubString(&p, (char*) szCmd, sizeof(szCmd) / sizeof(uchar), ' ') != 0) {
+ logerror("Invalid $-configline - could not extract command - line ignored\n");
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+
+ /* we now try and see if we can find the command in the registered
+ * list of cfsysline handlers. -- rgerhards, 2007-07-31
+ */
+ CHKiRet(processCfSysLineCommand(szCmd, &p));
+
+ /* now check if we have some extra characters left on the line - that
+ * should not be the case. Whitespace is OK, but everything else should
+ * trigger a warning (that may be an indication of undesired behaviour).
+ * An exception, of course, are comments (starting with '#').
+ * rgerhards, 2007-07-04
+ */
+ skipWhiteSpace(&p);
+
+ if(*p && *p != '#') { /* we have a non-whitespace, so let's complain */
+ snprintf((char*) errMsg, sizeof(errMsg)/sizeof(uchar),
+ "error: extra characters in config line ignored: '%s'", p);
+ errno = 0;
+ logerror((char*) errMsg);
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* helper to freeSelectors(), used with llExecFunc() to flush
+ * pending output. -- rgerhards, 2007-08-02
+ */
+DEFFUNC_llExecFunc(freeSelectorsActions)
+{
+ action_t *pAction = (action_t*) pData;
+
+ assert(pAction != NULL);
+
+ /* flush any pending output */
+ if(pAction->f_prevcount) {
+ fprintlog(pAction);
+ }
+
+ return RS_RET_OK; /* never fails ;) */
+}
+
+
+/* Close all open log files and free selector descriptor array.
+ */
+static void freeSelectors(void)
+{
+ selector_t *f;
+ selector_t *fPrev;
+
+ if(Files != NULL) {
+ dbgprintf("Freeing log structures.\n");
+
+ /* just in case, we flush the emergency log. If error messages occur after
+ * this stage, we loose them, but that's ok. With multi-threading, this can
+ * never happen. -- rgerhards, 2007-08-03
+ */
+ processImInternal();
+
+ /* we need first to flush, then wait for all messages to be processed
+ * (stopWoker() does that), then we can free the structures.
+ */
+ for(f = Files ; f != NULL ; f = f->f_next) {
+ llExecFunc(&f->llActList, freeSelectorsActions, NULL);
+ }
+
+# ifdef USE_PTHREADS
+ stopWorker();
+# endif
+
+ f = Files;
+ while (f != NULL) {
+ fPrev = f;
+ f = f->f_next;
+ selectorDestruct(fPrev);
+ }
+
+ /* Reflect the deletion of the selectors linked list. */
+ Files = NULL;
+ Initialized = 0;
+ }
+}
+
+
+/* helper to dbPrintInitInfo, to print out all actions via
+ * the llExecFunc() facility.
+ * rgerhards, 2007-08-02
+ */
+DEFFUNC_llExecFunc(dbgPrintInitInfoAction)
+{
+ DEFiRet;
+ iRet = actionDbgPrint((action_t*) pData);
+ printf("\n");
+
+ return iRet;
+}
+
+/* print debug information as part of init(). This pretty much
+ * outputs the whole config of rsyslogd. I've moved this code
+ * out of init() to clean it somewhat up.
+ * rgerhards, 2007-07-31
+ */
+static void dbgPrintInitInfo(void)
+{
+ register selector_t *f;
+ int iSelNbr = 1;
+ int i;
+
+ printf("\nActive selectors:\n");
+ for (f = Files; f != NULL ; f = f->f_next) {
+ printf("Selector %d:\n", iSelNbr++);
+ if(f->pCSProgNameComp != NULL)
+ printf("tag: '%s'\n", rsCStrGetSzStr(f->pCSProgNameComp));
+ if(f->eHostnameCmpMode != HN_NO_COMP)
+ printf("hostname: %s '%s'\n",
+ f->eHostnameCmpMode == HN_COMP_MATCH ?
+ "only" : "allbut",
+ rsCStrGetSzStr(f->pCSHostnameComp));
+ if(f->f_filter_type == FILTER_PRI) {
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ if (f->f_filterData.f_pmask[i] == TABLE_NOPRI)
+ printf(" X ");
+ else
+ printf("%2X ", f->f_filterData.f_pmask[i]);
+ } else {
+ printf("PROPERTY-BASED Filter:\n");
+ printf("\tProperty.: '%s'\n",
+ rsCStrGetSzStr(f->f_filterData.prop.pCSPropName));
+ printf("\tOperation: ");
+ if(f->f_filterData.prop.isNegated)
+ printf("NOT ");
+ printf("'%s'\n", getFIOPName(f->f_filterData.prop.operation));
+ printf("\tValue....: '%s'\n",
+ rsCStrGetSzStr(f->f_filterData.prop.pCSCompValue));
+ printf("\tAction...: ");
+ }
+
+ printf("\nActions:\n");
+ llExecFunc(&f->llActList, dbgPrintInitInfoAction, NULL); /* actions */
+
+ printf("\n");
+ }
+ printf("\n");
+ if(bDebugPrintTemplateList)
+ tplPrintList();
+ if(bDebugPrintModuleList)
+ modPrintList();
+ ochPrintList();
+
+ if(bDebugPrintCfSysLineHandlerList)
+ dbgPrintCfSysLineHandlers();
+
+#ifdef SYSLOG_INET
+ /* now the allowedSender lists: */
+ PrintAllowedSenders(1); /* UDP */
+ PrintAllowedSenders(2); /* TCP */
+ printf("\n");
+#endif /* #ifdef SYSLOG_INET */
+
+ printf("Messages with malicious PTR DNS Records are %sdropped.\n",
+ bDropMalPTRMsgs ? "" : "not ");
+
+ printf("Control characters are %sreplaced upon reception.\n",
+ bEscapeCCOnRcv? "" : "not ");
+
+ if(bEscapeCCOnRcv)
+ printf("Control character escape sequence prefix is '%c'.\n",
+ cCCEscapeChar);
+
+#ifdef USE_PTHREADS
+ printf("Main queue size %d messages.\n", iMainMsgQueueSize);
+#endif
+}
+
+
+/* process a configuration file
+ * started with code from init() by rgerhards on 2007-07-31
+ */
+static rsRetVal processConfFile(uchar *pConfFile)
+{
+ DEFiRet;
+ int iLnNbr = 0;
+ FILE *cf;
+ selector_t *fCurr = NULL;
+ uchar *p;
+#ifdef CONT_LINE
+ uchar cbuf[BUFSIZ];
+ uchar *cline;
+#else
+ uchar cline[BUFSIZ];
+#endif
+ assert(pConfFile != NULL);
+
+ if((cf = fopen((char*)pConfFile, "r")) == NULL) {
+ ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
+ }
+
+ /* Now process the file.
+ */
+#if CONT_LINE
+ cline = cbuf;
+ while (fgets((char*)cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
+#else
+ while (fgets(cline, sizeof(cline), cf) != NULL) {
+#endif
+ ++iLnNbr;
+ /* drop LF - TODO: make it better, replace fgets(), but its clean as it is */
+ if(cline[strlen((char*)cline)-1] == '\n') {
+ cline[strlen((char*)cline) -1] = '\0';
+ }
+ /* check for end-of-section, comments, strip off trailing
+ * spaces and newline character.
+ */
+ p = cline;
+ skipWhiteSpace(&p);
+ if (*p == '\0' || *p == '#')
+ continue;
+
+#if CONT_LINE
+ strcpy((char*)cline, (char*)p);
+#endif
+ for (p = (uchar*) strchr((char*)cline, '\0'); isspace((int) *--p););
+#if CONT_LINE
+ if (*p == '\\') {
+ if ((p - cbuf) > BUFSIZ - 30) {
+ /* Oops the buffer is full - what now? */
+ cline = cbuf;
+ } else {
+ *p = 0;
+ cline = p;
+ continue;
+ }
+ } else
+ cline = cbuf;
+#endif
+ *++p = '\0'; // TODO: check this
+
+ /* we now have the complete line, and are positioned at the first non-whitespace
+ * character. So let's process it
+ */
+#if CONT_LINE
+ if(cfline(cbuf, &fCurr) != RS_RET_OK) {
+#else
+ if(cfline((uchar*)cline, &fCurr) != RS_RET_OK) {
+#endif
+ /* we log a message, but otherwise ignore the error. After all, the next
+ * line can be correct. -- rgerhards, 2007-08-02
+ */
+ uchar szErrLoc[MAXFNAME + 64];
+ dbgprintf("config line NOT successfully processed\n");
+ snprintf((char*)szErrLoc, sizeof(szErrLoc) / sizeof(uchar),
+ "%s, line %d", pConfFile, iLnNbr);
+ logerrorSz("the last error occured in %s", (char*)szErrLoc);
+ }
+ }
+
+ /* we probably have one selector left to be added - so let's do that now */
+ CHKiRet(selectorAddList(fCurr));
+
+ /* close the configuration file */
+ (void) fclose(cf);
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(fCurr != NULL)
+ selectorDestruct(fCurr);
+ dbgprintf("error %d processing config file '%s'; os error (if any): %s\n",
+ iRet, pConfFile, strerror(errno));
+ }
+ return iRet;
+}
+
+
+/* INIT -- Initialize syslogd from configuration table
+ * init() is called at initial startup AND each time syslogd is HUPed
+ */
+static void init(void)
+{
+ DEFiRet;
+ register int i;
+#ifdef CONT_LINE
+ char cbuf[BUFSIZ];
+#else
+ char cline[BUFSIZ];
+#endif
+ char bufStartUpMsg[512];
+ struct servent *sp;
+
+ /* initialize some static variables */
+ pDfltHostnameCmp = NULL;
+ pDfltProgNameCmp = NULL;
+ eDfltHostnameCmpMode = HN_NO_COMP;
+ Forwarding = 0;
+
+#ifdef SYSLOG_INET
+ if (restart) {
+ if (pAllowedSenders_UDP != NULL) {
+ clearAllowedSenders (pAllowedSenders_UDP);
+ pAllowedSenders_UDP = NULL;
+ }
+
+ if (pAllowedSenders_TCP != NULL) {
+ clearAllowedSenders (pAllowedSenders_TCP);
+ pAllowedSenders_TCP = NULL;
+ }
+ }
+
+ assert (pAllowedSenders_UDP == NULL &&
+ pAllowedSenders_TCP == NULL );
+#endif
+ /* I was told by an IPv6 expert that calling getservbyname() seems to be
+ * still valid, at least for the use case we have. So I re-enabled that
+ * code. rgerhards, 2007-07-02
+ */
+ if(!strcmp(LogPort, "0")) {
+ /* we shall use the default syslog/udp port, so let's
+ * look it up.
+ */
+ sp = getservbyname("syslog", "udp");
+ if (sp == NULL) {
+ errno = 0;
+ logerror("Could not find syslog/udp port in /etc/services. "
+ "Now using IANA-assigned default of 514.");
+ LogPort = "514";
+ } else {
+ /* we can dynamically allocate memory here and do NOT need
+ * to care about freeing it because even though init() is
+ * called on each restart, the LogPort can never again be
+ * "0". So we will only once run into this part of the code
+ * here. rgerhards, 2007-07-02
+ * We save ourselfs the hassle of dynamic memory management
+ * for the very same reason.
+ */
+ static char defPort[8];
+ snprintf(defPort, sizeof(defPort) * sizeof(char), "%d", ntohs(sp->s_port));
+ LogPort = defPort;
+ }
+ }
+
+ dbgprintf("Called init.\n");
+
+ /* Close all open log files and free log descriptor array. */
+ freeSelectors();
+
+ dbgprintf("Clearing templates.\n");
+ tplDeleteNew();
+
+#ifdef USE_PTHREADS
+ if(pMsgQueue != NULL) {
+ dbgprintf("deleting message queue\n");
+ queueDelete(pMsgQueue); /* delete fifo here! */
+ pMsgQueue = NULL;
+ }
+#endif
+
+
+ /* re-setting values to defaults (where applicable) */
+ /* TODO: once we have loadable modules, we must re-visit this code. The reason is
+ * that config variables are not re-set, because the module is not yet loaded. On
+ * the other hand, that doesn't matter, because the module got unloaded and is then
+ * re-loaded, so the variables should be re-set via that way. In any case, we should
+ * think about the whole situation when we implement loadable plugins.
+ * rgerhards, 2007-07-31
+ */
+ cfsysline((uchar*)"ResetConfigVariables");
+
+ /* open the configuration file */
+ if((iRet = processConfFile(ConfFile)) != RS_RET_OK) {
+ /* rgerhards: this code is executed to set defaults when the
+ * config file could not be opened. We might think about
+ * abandoning the run in this case - but this, too, is not
+ * very clever... So we stick with what we have.
+ * We ignore any errors while doing this - we would be lost anyhow...
+ */
+ selector_t *f = NULL;
+ char *pTTY = ttyname(0);
+ dbgprintf("primary config file could not be opened - using emergency definitions.\n");
+ cfline((uchar*)"*.ERR\t" _PATH_CONSOLE, &f);
+ cfline((uchar*)"*.PANIC\t*", &f);
+ if(pTTY != NULL) {
+ snprintf(cbuf,sizeof(cbuf), "*.*\t%s", pTTY);
+ cfline((uchar*)cbuf, &f);
+ }
+ selectorAddList(f);
+ }
+
+ /* we are now done with reading the configuration. This is the right time to
+ * free some objects that were just needed for loading it. rgerhards 2005-10-19
+ */
+ if(pDfltHostnameCmp != NULL) {
+ rsCStrDestruct(pDfltHostnameCmp);
+ pDfltHostnameCmp = NULL;
+ }
+
+ if(pDfltProgNameCmp != NULL) {
+ rsCStrDestruct(pDfltProgNameCmp);
+ pDfltProgNameCmp = NULL;
+ }
+
+#ifdef SYSLOG_UNIXAF
+ for (i = startIndexUxLocalSockets ; i < nfunix ; i++) {
+ if (funix[i] != -1)
+ /* Don't close the socket, preserve it instead
+ close(funix[i]);
+ */
+ continue;
+ if ((funix[i] = create_unix_socket(funixn[i])) != -1)
+ dbgprintf("Opened UNIX socket `%s' (fd %d).\n", funixn[i], funix[i]);
+ }
+#endif
+
+#ifdef SYSLOG_INET
+ /* I have moved initializing UDP sockets before the TCP sockets. This ensures
+ * they are as soon ready for reception as possible. Of course, it is only a
+ * very small window of exposure, but it doesn't hurt to limit the message
+ * loss risk to as low as possible - especially if it costs nothing...
+ * rgerhards, 2007-06-28
+ */
+ if(Forwarding || AcceptRemote) {
+ if (finet == NULL) {
+ if((finet = create_udp_socket()) != NULL)
+ dbgprintf("Opened %d syslog UDP port(s).\n", *finet);
+ }
+ }
+ else {
+ /* this case can happen during HUP processing. */
+ closeUDPListenSockets();
+ }
+
+ if (bEnableTCP) {
+ if(sockTCPLstn == NULL) {
+ /* even when doing a re-init, we do not shut down and
+ * re-open the TCP socket. That would break existing TCP
+ * session, which we do not desire. Should at some time arise
+ * need to do that, I recommend controlling that via a
+ * user-selectable option. rgerhards, 2007-06-21
+ */
+ if((sockTCPLstn = create_tcp_socket()) != NULL) {
+ dbgprintf("Opened %d syslog TCP port(s).\n", *sockTCPLstn);
+ }
+ }
+ }
+#endif
+
+# ifdef USE_PTHREADS
+ /* create message queue */
+ pMsgQueue = queueInit();
+ if(pMsgQueue == NULL) {
+ errno = 0;
+ logerror("error: could not create message queue - running single-threaded!\n");
+ }
+
+ startWorker();
+# endif
+
+ Initialized = 1;
+
+ if(Debug) {
+ dbgPrintInitInfo();
+ }
+
+ /* 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-configInfo udpReception=\"%s\" " \
+ "udpPort=\"%s\" tcpReception=\"%s\" tcpPort=\"%s\"]" \
+ " restart",
+ (int) myPid,
+#ifdef SYSLOG_INET
+ AcceptRemote ? "Yes" : "No", LogPort,
+ bEnableTCP ? "Yes" : "No", TCPLstnPort
+#else
+ "No", "0", "No", "0"
+#endif /* #ifdef SYSLOG_INET */
+ );
+ logmsgInternal(LOG_SYSLOG|LOG_INFO, bufStartUpMsg, ADDDATE);
+
+ (void) signal(SIGHUP, sighup_handler);
+ dbgprintf(" restarted.\n");
+}
+
+
+/* Helper to cfline() and its helpers. Parses a template name
+ * from an "action" line. Must be called with the Line pointer
+ * pointing to the first character after the semicolon.
+ * rgerhards 2004-11-19
+ * changed function to work with OMSR. -- rgerhards, 2007-07-27
+ * the default template is to be used when no template is specified.
+ */
+rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName)
+{
+ uchar *p;
+ uchar *tplName;
+ DEFiRet;
+ rsCStrObj *pStrB;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pOMSR != NULL);
+
+ p =*pp;
+ /* a template must follow - search it and complain, if not found
+ */
+ skipWhiteSpace(&p);
+ if(*p == ';')
+ ++p; /* eat it */
+ else if(*p != '\0' && *p != '#') {
+ logerror("invalid character in selector line - ';template' expected");
+ iRet = RS_RET_ERR;
+ goto finalize_it;
+ }
+
+ skipWhiteSpace(&p); /* go to begin of template name */
+
+ if(*p == '\0') {
+ /* no template specified, use the default */
+ /* TODO: check NULL ptr */
+ tplName = (uchar*) strdup((char*)dfltTplName);
+ } else {
+ /* template specified, pick it up */
+ if((pStrB = rsCStrConstruct()) == NULL) {
+ glblHadMemShortage = 1;
+ iRet = RS_RET_OUT_OF_MEMORY;
+ goto finalize_it;
+ }
+
+ /* now copy the string */
+ while(*p && *p != '#' && !isspace((int) *p)) {
+ if((iRet = rsCStrAppendChar(pStrB, *p)) != RS_RET_OK) goto finalize_it;
+ ++p;
+ }
+ if((iRet = rsCStrFinish(pStrB)) != RS_RET_OK) goto finalize_it;
+ tplName = rsCStrConvSzStrAndDestruct(pStrB);
+ }
+
+ iRet = OMSRsetEntry(pOMSR, iEntry, tplName, iTplOpts);
+ if(iRet != RS_RET_OK) goto finalize_it;
+
+finalize_it:
+ *pp = p;
+
+ return iRet;
+}
+
+/* Helper to cfline(). Parses a file name up until the first
+ * comma and then looks for the template specifier. Tries
+ * to find that template.
+ * rgerhards 2004-11-18
+ * parameter pFileName must point to a buffer large enough
+ * to hold the largest possible filename.
+ * rgerhards, 2007-07-25
+ * updated to include OMSR pointer -- rgerhards, 2007-07-27
+ */
+rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts)
+{
+ register uchar *pName;
+ int i;
+ DEFiRet;
+
+ assert(pOMSR != NULL);
+
+ pName = pFileName;
+ i = 1; /* we start at 1 so that we reseve space for the '\0'! */
+ while(*p && *p != ';' && i < MAXFNAME) {
+ *pName++ = *p++;
+ ++i;
+ }
+ *pName = '\0';
+
+ iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, (uchar*) " TradFmt");
+
+ return iRet;
+}
+
+
+/*
+ * Helper to cfline(). This function takes the filter part of a traditional, PRI
+ * based line and decodes the PRIs given in the selector line. It processed the
+ * line up to the beginning of the action part. A pointer to that beginnig is
+ * passed back to the caller.
+ * rgerhards 2005-09-15
+ */
+static rsRetVal cflineProcessTradPRIFilter(uchar **pline, register selector_t *f)
+{
+ uchar *p;
+ register uchar *q;
+ register int i, i2;
+ uchar *bp;
+ int pri;
+ int singlpri = 0;
+ int ignorepri = 0;
+ uchar buf[MAXLINE];
+ uchar xbuf[200];
+
+ assert(pline != NULL);
+ assert(*pline != NULL);
+ assert(f != NULL);
+
+ dbgprintf(" - traditional PRI filter\n");
+ errno = 0; /* keep strerror() stuff out of logerror messages */
+
+ f->f_filter_type = FILTER_PRI;
+ /* Note: file structure is pre-initialized to zero because it was
+ * created with calloc()!
+ */
+ for (i = 0; i <= LOG_NFACILITIES; i++) {
+ f->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ }
+
+ /* scan through the list of selectors */
+ for (p = *pline; *p && *p != '\t' && *p != ' ';) {
+
+ /* find the end of this facility name list */
+ for (q = p; *q && *q != '\t' && *q++ != '.'; )
+ continue;
+
+ /* collect priority name */
+ for (bp = buf; *q && !strchr("\t ,;", *q); )
+ *bp++ = *q++;
+ *bp = '\0';
+
+ /* skip cruft */
+ while (strchr(",;", *q))
+ q++;
+
+ /* decode priority name */
+ if ( *buf == '!' ) {
+ ignorepri = 1;
+ for (bp=buf; *(bp+1); bp++)
+ *bp=*(bp+1);
+ *bp='\0';
+ }
+ else {
+ ignorepri = 0;
+ }
+ if ( *buf == '=' )
+ {
+ singlpri = 1;
+ pri = decode(&buf[1], PriNames);
+ }
+ else {
+ singlpri = 0;
+ pri = decode(buf, PriNames);
+ }
+
+ if (pri < 0) {
+ snprintf((char*) xbuf, sizeof(xbuf), "unknown priority name \"%s\"", buf);
+ logerror((char*) xbuf);
+ return RS_RET_ERR;
+ }
+
+ /* scan facilities */
+ while (*p && !strchr("\t .;", *p)) {
+ for (bp = buf; *p && !strchr("\t ,;.", *p); )
+ *bp++ = *p++;
+ *bp = '\0';
+ if (*buf == '*') {
+ for (i = 0; i <= LOG_NFACILITIES; i++) {
+ if ( pri == INTERNAL_NOPRI ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i] = TABLE_ALLPRI;
+ else
+ f->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ }
+ else if ( singlpri ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i] &= ~(1<<pri);
+ else
+ f->f_filterData.f_pmask[i] |= (1<<pri);
+ }
+ else
+ {
+ if ( pri == TABLE_ALLPRI ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i] = TABLE_NOPRI;
+ else
+ f->f_filterData.f_pmask[i] = TABLE_ALLPRI;
+ }
+ else
+ {
+ if ( ignorepri )
+ for (i2= 0; i2 <= pri; ++i2)
+ f->f_filterData.f_pmask[i] &= ~(1<<i2);
+ else
+ for (i2= 0; i2 <= pri; ++i2)
+ f->f_filterData.f_pmask[i] |= (1<<i2);
+ }
+ }
+ }
+ } else {
+ i = decode(buf, FacNames);
+ if (i < 0) {
+
+ snprintf((char*) xbuf, sizeof(xbuf), "unknown facility name \"%s\"", buf);
+ logerror((char*) xbuf);
+ return RS_RET_ERR;
+ }
+
+ if ( pri == INTERNAL_NOPRI ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
+ else
+ f->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
+ } else if ( singlpri ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i >> 3] &= ~(1<<pri);
+ else
+ f->f_filterData.f_pmask[i >> 3] |= (1<<pri);
+ } else {
+ if ( pri == TABLE_ALLPRI ) {
+ if ( ignorepri )
+ f->f_filterData.f_pmask[i >> 3] = TABLE_NOPRI;
+ else
+ f->f_filterData.f_pmask[i >> 3] = TABLE_ALLPRI;
+ } else {
+ if ( ignorepri )
+ for (i2= 0; i2 <= pri; ++i2)
+ f->f_filterData.f_pmask[i >> 3] &= ~(1<<i2);
+ else
+ for (i2= 0; i2 <= pri; ++i2)
+ f->f_filterData.f_pmask[i >> 3] |= (1<<i2);
+ }
+ }
+ }
+ while (*p == ',' || *p == ' ')
+ p++;
+ }
+
+ p = q;
+ }
+
+ /* skip to action part */
+ while (*p == '\t' || *p == ' ')
+ p++;
+
+ *pline = p;
+ return RS_RET_OK;
+}
+
+
+/*
+ * Helper to cfline(). This function takes the filter part of a property
+ * based filter and decodes it. It processes the line up to the beginning
+ * of the action part. A pointer to that beginnig is passed back to the caller.
+ * rgerhards 2005-09-15
+ */
+static rsRetVal cflineProcessPropFilter(uchar **pline, register selector_t *f)
+{
+ rsParsObj *pPars;
+ rsCStrObj *pCSCompOp;
+ rsRetVal iRet;
+ int iOffset; /* for compare operations */
+
+ assert(pline != NULL);
+ assert(*pline != NULL);
+ assert(f != NULL);
+
+ dbgprintf(" - property-based filter\n");
+ errno = 0; /* keep strerror() stuff out of logerror messages */
+
+ f->f_filter_type = FILTER_PROP;
+
+ /* create parser object starting with line string without leading colon */
+ if((iRet = rsParsConstructFromSz(&pPars, (*pline)+1)) != RS_RET_OK) {
+ logerrorInt("Error %d constructing parser object - ignoring selector", iRet);
+ return(iRet);
+ }
+
+ /* read property */
+ iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1);
+ if(iRet != RS_RET_OK) {
+ logerrorInt("error %d parsing filter property - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+
+ /* read operation */
+ iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1);
+ if(iRet != RS_RET_OK) {
+ logerrorInt("error %d compare operation property - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+
+ /* we now first check if the condition is to be negated. To do so, we first
+ * must make sure we have at least one char in the param and then check the
+ * first one.
+ * rgerhards, 2005-09-26
+ */
+ if(rsCStrLen(pCSCompOp) > 0) {
+ if(*rsCStrGetBufBeg(pCSCompOp) == '!') {
+ f->f_filterData.prop.isNegated = 1;
+ iOffset = 1; /* ignore '!' */
+ } else {
+ f->f_filterData.prop.isNegated = 0;
+ iOffset = 0;
+ }
+ } else {
+ f->f_filterData.prop.isNegated = 0;
+ iOffset = 0;
+ }
+
+ if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "contains", 8)) {
+ f->f_filterData.prop.operation = FIOP_CONTAINS;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "isequal", 7)) {
+ f->f_filterData.prop.operation = FIOP_ISEQUAL;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (uchar*) "startswith", 10)) {
+ f->f_filterData.prop.operation = FIOP_STARTSWITH;
+ } else if(!rsCStrOffsetSzStrCmp(pCSCompOp, iOffset, (unsigned char*) "regex", 5)) {
+ f->f_filterData.prop.operation = FIOP_REGEX;
+ } else {
+ logerrorSz("error: invalid compare operation '%s' - ignoring selector",
+ (char*) rsCStrGetSzStr(pCSCompOp));
+ }
+ rsCStrDestruct (pCSCompOp); /* no longer needed */
+
+ /* read compare value */
+ iRet = parsQuotedCStr(pPars, &f->f_filterData.prop.pCSCompValue);
+ if(iRet != RS_RET_OK) {
+ logerrorInt("error %d compare value property - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+
+ /* skip to action part */
+ if((iRet = parsSkipWhitespace(pPars)) != RS_RET_OK) {
+ logerrorInt("error %d skipping to action part - ignoring selector", iRet);
+ rsParsDestruct(pPars);
+ return(iRet);
+ }
+
+ /* cleanup */
+ *pline = *pline + rsParsGetParsePointer(pPars) + 1;
+ /* we are adding one for the skipped initial ":" */
+
+ return rsParsDestruct(pPars);
+}
+
+
+/*
+ * Helper to cfline(). This function interprets a BSD host selector line
+ * from the config file ("+/-hostname"). It stores it for further reference.
+ * rgerhards 2005-10-19
+ */
+static rsRetVal cflineProcessHostSelector(uchar **pline)
+{
+ rsRetVal iRet;
+
+ assert(pline != NULL);
+ assert(*pline != NULL);
+ assert(**pline == '-' || **pline == '+');
+
+ dbgprintf(" - host selector line\n");
+
+ /* check include/exclude setting */
+ if(**pline == '+') {
+ eDfltHostnameCmpMode = HN_COMP_MATCH;
+ } else { /* we do not check for '-', it must be, else we wouldn't be here */
+ eDfltHostnameCmpMode = HN_COMP_NOMATCH;
+ }
+ (*pline)++; /* eat + or - */
+
+ /* the below is somewhat of a quick hack, but it is efficient (this is
+ * why it is in here. "+*" resets the tag selector with BSD syslog. We mimic
+ * this, too. As it is easy to check that condition, we do not fire up a
+ * parser process, just make sure we do not address beyond our space.
+ * Order of conditions in the if-statement is vital! rgerhards 2005-10-18
+ */
+ if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
+ dbgprintf("resetting BSD-like hostname filter\n");
+ eDfltHostnameCmpMode = HN_NO_COMP;
+ if(pDfltHostnameCmp != NULL) {
+ if((iRet = rsCStrSetSzStr(pDfltHostnameCmp, NULL)) != RS_RET_OK)
+ return(iRet);
+ pDfltHostnameCmp = NULL;
+ }
+ } else {
+ dbgprintf("setting BSD-like hostname filter to '%s'\n", *pline);
+ if(pDfltHostnameCmp == NULL) {
+ /* create string for parser */
+ if((iRet = rsCStrConstructFromszStr(&pDfltHostnameCmp, *pline)) != RS_RET_OK)
+ return(iRet);
+ } else { /* string objects exists, just update... */
+ if((iRet = rsCStrSetSzStr(pDfltHostnameCmp, *pline)) != RS_RET_OK)
+ return(iRet);
+ }
+ }
+ return RS_RET_OK;
+}
+
+
+/*
+ * Helper to cfline(). This function interprets a BSD tag selector line
+ * from the config file ("!tagname"). It stores it for further reference.
+ * rgerhards 2005-10-18
+ */
+static rsRetVal cflineProcessTagSelector(uchar **pline)
+{
+ rsRetVal iRet;
+
+ assert(pline != NULL);
+ assert(*pline != NULL);
+ assert(**pline == '!');
+
+ dbgprintf(" - programname selector line\n");
+
+ (*pline)++; /* eat '!' */
+
+ /* the below is somewhat of a quick hack, but it is efficient (this is
+ * why it is in here. "!*" resets the tag selector with BSD syslog. We mimic
+ * this, too. As it is easy to check that condition, we do not fire up a
+ * parser process, just make sure we do not address beyond our space.
+ * Order of conditions in the if-statement is vital! rgerhards 2005-10-18
+ */
+ if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
+ dbgprintf("resetting programname filter\n");
+ if(pDfltProgNameCmp != NULL) {
+ if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, NULL)) != RS_RET_OK)
+ return(iRet);
+ pDfltProgNameCmp = NULL;
+ }
+ } else {
+ dbgprintf("setting programname filter to '%s'\n", *pline);
+ if(pDfltProgNameCmp == NULL) {
+ /* create string for parser */
+ if((iRet = rsCStrConstructFromszStr(&pDfltProgNameCmp, *pline)) != RS_RET_OK)
+ return(iRet);
+ } else { /* string objects exists, just update... */
+ if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, *pline)) != RS_RET_OK)
+ return(iRet);
+ }
+ }
+ return RS_RET_OK;
+}
+
+
+/* add an Action to the current selector
+ * The pOMSR is freed, as it is not needed after this function.
+ * Note: this function pulls global data that specifies action config state.
+ * rgerhards, 2007-07-27
+ */
+rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, int bSuspended)
+{
+ DEFiRet;
+ int i;
+ int iTplOpts;
+ uchar *pTplName;
+ action_t *pAction;
+ char errMsg[512];
+
+ assert(ppAction != NULL);
+ assert(pMod != NULL);
+ assert(pOMSR != NULL);
+ dbgprintf("Module %s processed this config line.\n", modGetName(pMod));
+
+ CHKiRet(actionConstruct(&pAction)); /* create action object first */
+ pAction->pMod = pMod;
+ pAction->pModData = pModData;
+ pAction->bExecWhenPrevSusp = bActExecWhenPrevSusp;
+
+ /* check if we can obtain the template pointers - TODO: move to separat function? */
+ pAction->iNumTpls = OMSRgetEntryCount(pOMSR);
+ assert(pAction->iNumTpls >= 0); /* only debug check because this "can not happen" */
+ /* please note: iNumTpls may validly be zero. This is the case if the module
+ * does not request any templates. This sounds unlikely, but an actual example is
+ * the discard action, which does not require a string. -- rgerhards, 2007-07-30
+ */
+ if(pAction->iNumTpls > 0) {
+ /* we first need to create the template pointer array */
+ if((pAction->ppTpl = calloc(pAction->iNumTpls, sizeof(struct template *))) == NULL) {
+ glblHadMemShortage = 1;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ /* and now the array for doAction() message pointers */
+ if((pAction->ppMsgs = calloc(pAction->iNumTpls, sizeof(uchar *))) == NULL) {
+ glblHadMemShortage = 1;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ }
+
+ for(i = 0 ; i < pAction->iNumTpls ; ++i) {
+ CHKiRet(OMSRgetEntry(pOMSR, i, &pTplName, &iTplOpts));
+ /* Ok, we got everything, so it now is time to look up the
+ * template (Hint: templates MUST be defined before they are
+ * used!)
+ */
+ if((pAction->ppTpl[i] = tplFind((char*)pTplName, strlen((char*)pTplName))) == NULL) {
+ snprintf(errMsg, sizeof(errMsg) / sizeof(char),
+ " Could not find template '%s' - action disabled\n",
+ pTplName);
+ errno = 0;
+ logerror(errMsg);
+ ABORT_FINALIZE(RS_RET_NOT_FOUND);
+ }
+ /* check required template options */
+ if( (iTplOpts & OMSR_RQD_TPL_OPT_SQL)
+ && (pAction->ppTpl[i]->optFormatForSQL == 0)) {
+ errno = 0;
+ logerror("Action disabled. To use this action, you have to specify "
+ "the SQL or stdSQL option in your template!\n");
+ ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING);
+ }
+
+ dbgprintf("template: '%s' assigned\n", pTplName);
+ }
+
+ pAction->pMod = pMod;
+ pAction->pModData = pModData;
+ /* now check if the module is compatible with select features */
+ if(pMod->isCompatibleWithFeature(sFEATURERepeatedMsgReduction) == RS_RET_OK)
+ pAction->f_ReduceRepeated = bReduceRepeatMsgs;
+ else {
+ dbgprintf("module is incompatible with RepeatedMsgReduction - turned off\n");
+ pAction->f_ReduceRepeated = 0;
+ }
+ pAction->bEnabled = 1; /* action is enabled */
+
+ if(bSuspended)
+ actionSuspend(pAction);
+
+ *ppAction = pAction; /* finally store the action pointer */
+
+finalize_it:
+ if(iRet == RS_RET_OK)
+ iRet = OMSRdestruct(pOMSR);
+ else {
+ /* do not overwrite error state! */
+ OMSRdestruct(pOMSR);
+ if(pAction != NULL)
+ actionDestruct(pAction);
+ }
+
+ return iRet;
+}
+
+
+/* read the filter part of a configuration line and store the filter
+ * in the supplied selector_t
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal cflineDoFilter(uchar **pp, selector_t *f)
+{
+ DEFiRet;
+
+ assert(pp != NULL);
+ assert(f != NULL);
+
+ /* check which filter we need to pull... */
+ switch(**pp) {
+ case ':':
+ iRet = cflineProcessPropFilter(pp, f);
+ break;
+ default:
+ iRet = cflineProcessTradPRIFilter(pp, f);
+ break;
+ }
+
+ /* we now check if there are some global (BSD-style) filter conditions
+ * and, if so, we copy them over. rgerhards, 2005-10-18
+ */
+ if(pDfltProgNameCmp != NULL)
+ if((iRet = rsCStrConstructFromCStr(&(f->pCSProgNameComp), pDfltProgNameCmp)) != RS_RET_OK)
+ return(iRet);
+
+ if(eDfltHostnameCmpMode != HN_NO_COMP) {
+ f->eHostnameCmpMode = eDfltHostnameCmpMode;
+ if((iRet = rsCStrConstructFromCStr(&(f->pCSHostnameComp), pDfltHostnameCmp)) != RS_RET_OK)
+ return(iRet);
+ }
+
+ return iRet;
+}
+
+
+/* process the action part of a selector line
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal cflineDoAction(uchar **p, action_t **ppAction)
+{
+ DEFiRet;
+ modInfo_t *pMod;
+ omodStringRequest_t *pOMSR;
+ action_t *pAction;
+ void *pModData;
+
+ assert(p != NULL);
+ assert(ppAction != NULL);
+
+ /* loop through all modules and see if one picks up the line */
+ pMod = omodGetNxt(NULL);
+ while(pMod != NULL) {
+ iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR);
+ dbgprintf("tried selector action for %s: %d\n", modGetName(pMod), iRet);
+ if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {
+ if((iRet = addAction(&pAction, pMod, pModData, pOMSR, (iRet == RS_RET_SUSPENDED)? 1 : 0)) == RS_RET_OK) {
+ /* now check if the module is compatible with select features */
+ if(pMod->isCompatibleWithFeature(sFEATURERepeatedMsgReduction) == RS_RET_OK)
+ pAction->f_ReduceRepeated = bReduceRepeatMsgs;
+ else {
+ dbgprintf("module is incompatible with RepeatedMsgReduction - turned off\n");
+ pAction->f_ReduceRepeated = 0;
+ }
+ pAction->bEnabled = 1; /* action is enabled */
+ }
+ break;
+ }
+ else if(iRet != RS_RET_CONFLINE_UNPROCESSED) {
+ /* In this case, the module would have handled the config
+ * line, but some error occured while doing so. This error should
+ * already by reported by the module. We do not try any other
+ * modules on this line, because we found the right one.
+ * rgerhards, 2007-07-24
+ */
+ dbgprintf("error %d parsing config line\n", (int) iRet);
+ break;
+ }
+ pMod = omodGetNxt(pMod);
+ }
+
+ *ppAction = pAction;
+ return iRet;
+}
+
+
+/* helper to selectorAddListCheckActions()
+ * This is the fucntion to be executed by llExecFunc
+ */
+DEFFUNC_llExecFunc(selectorAddListCheckActionsChecker)
+{
+ DEFiRet;
+ action_t *pAction = (action_t *) pData;
+
+ assert(pAction != NULL);
+
+ if(pAction->pMod->needUDPSocket(pAction->pModData) == RS_RET_TRUE) {
+ Forwarding++;
+ }
+
+ return iRet;
+}
+
+/* loop through a list of actions and perform necessary checks and
+ * housekeeping. This function must only be called when the owning
+ * selector_t looks valid and is not likely to be discarded. However,
+ * if we do not return RS_RET_OK, the caller MUST discard the
+ * owning selector_t. -- rgerhards, 2007-08-02
+*/
+static rsRetVal selectorAddListCheckActions(selector_t *f)
+{
+ DEFiRet;
+
+ assert(f != NULL);
+
+ CHKiRet(llExecFunc(&f->llActList, selectorAddListCheckActionsChecker, NULL));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* add a completely-processed selector (after config line parsing) to
+ * the linked list of selectors. We now need to check
+ * if it has any actions associated and, if so, link it to the linked
+ * list. If it has nothing associated with it, we can simply discard
+ * it.
+ * We have one special case during initialization: then, the current
+ * selector is NULL, which means we do not need to care about it at
+ * all. -- rgerhards, 2007-08-01
+ */
+static rsRetVal selectorAddList(selector_t *f)
+{
+ DEFiRet;
+ int iActionCnt;
+
+ static selector_t *nextp = NULL; /* TODO: make this go away (see comment below) */
+
+ if(f != NULL) {
+ CHKiRet(llGetNumElts(&f->llActList, &iActionCnt));
+ if(iActionCnt == 0) {
+ logerror("warning: selector line without actions will be discarded");
+ selectorDestruct(f);
+ } else {
+ if((iRet = selectorAddListCheckActions(f)) != RS_RET_OK) {
+ logerror("selector line will be discarded due to error in action(s)");
+ selectorDestruct(f);
+ goto finalize_it;
+ }
+ /* successfully created an entry */
+ dbgprintf("selector line successfully processed\n");
+ /* TODO: we should use the linked list class for the selector list, else we need to add globals
+ * ... well nextp could be added temporarily...
+ * Thanks to varmojfekoj for having the idea to just use "Files" to make this
+ * code work. I had actually forgotten to fix the code here before moving to 1.18.0.
+ * And, of course, I also did not migrate the selector_t structure to the linked list class.
+ * However, that should still be one of the very next things to happen.
+ * rgerhards, 2007-08-06
+ */
+ if(Files == NULL) {
+ Files = f;
+ } else {
+ nextp->f_next = f;
+ }
+ nextp = f;
+ }
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* Process a configuration file line in traditional "filter selector" format
+ */
+static rsRetVal cflineClassic(uchar *p, selector_t **pfCurr)
+{
+ DEFiRet;
+ action_t *pAction;
+ selector_t *fCurr;
+
+ assert(pfCurr != NULL);
+
+ fCurr = *pfCurr;
+
+ /* lines starting with '&' have no new filters and just add
+ * new actions to the currently processed selector.
+ */
+ if(*p == '&') {
+ ++p; /* eat '&' */
+ skipWhiteSpace(&p); /* on to command */
+ } else {
+ /* we are finished with the current selector. So we now need to check
+ * if it has any actions associated and, if so, link it to the linked
+ * list. If it has nothing associated with it, we can simply discard
+ * it. In any case, we create a fresh selector for our new filter.
+ * We have one special case during initialization: then, the current
+ * selector is NULL, which means we do not need to care about it at
+ * all. -- rgerhards, 2007-08-01
+ */
+ CHKiRet(selectorAddList(fCurr));
+ CHKiRet(selectorConstruct(&fCurr)); /* create "fresh" selector */
+ CHKiRet(cflineDoFilter(&p, fCurr)); /* pull filters */
+ }
+
+ CHKiRet(cflineDoAction(&p, &pAction));
+ CHKiRet(llAppend(&fCurr->llActList, NULL, (void*) pAction));
+
+finalize_it:
+ *pfCurr = fCurr;
+ return iRet;
+}
+
+
+/* process a configuration line
+ * I re-did this functon because it was desperately time to do so
+ * rgerhards, 2007-08-01
+ */
+static rsRetVal cfline(uchar *line, selector_t **pfCurr)
+{
+ DEFiRet;
+
+ assert(line != NULL);
+
+ dbgprintf("cfline: '%s'\n", line);
+
+ /* check type of line and call respective processing */
+ switch(*line) {
+ case '!':
+ iRet = cflineProcessTagSelector(&line);
+ break;
+ case '+':
+ case '-':
+ iRet = cflineProcessHostSelector(&line);
+ break;
+ case '$':
+ ++line; /* eat '$' */
+ iRet = cfsysline(line);
+ break;
+ default:
+ iRet = cflineClassic(line, pfCurr);
+ break;
+ }
+
+ return iRet;
+}
+
+
+/* Decode a symbolic name to a numeric value
+ */
+int decode(uchar *name, struct code *codetab)
+{
+ register struct code *c;
+ register uchar *p;
+ uchar buf[80];
+
+ assert(name != NULL);
+ assert(codetab != NULL);
+
+ dbgprintf("symbolic name: %s", name);
+ if (isdigit((int) *name))
+ {
+ dbgprintf("\n");
+ return (atoi((char*) name));
+ }
+ strncpy((char*) buf, (char*) name, 79);
+ for (p = buf; *p; p++)
+ if (isupper((int) *p))
+ *p = tolower((int) *p);
+ for (c = codetab; c->c_name; c++)
+ if (!strcmp((char*) buf, (char*) c->c_name))
+ {
+ dbgprintf(" ==> %d\n", c->c_val);
+ return (c->c_val);
+ }
+ return (-1);
+}
+
+extern void dbgprintf(char *fmt, ...) __attribute__((format(printf,1, 2)));
+void dbgprintf(char *fmt, ...)
+{
+# ifdef USE_PTHREADS
+ static int bWasNL = FALSE;
+# endif
+ va_list ap;
+
+ if ( !(Debug && debugging_on) )
+ return;
+
+# ifdef USE_PTHREADS
+ /* The bWasNL handler does not really work. It works if no thread
+ * switching occurs during non-NL messages. Else, things are messed
+ * up. Anyhow, it works well enough to provide useful help during
+ * getting this up and running. It is questionable if the extra effort
+ * is worth fixing it, giving the limited appliability.
+ * rgerhards, 2005-10-25
+ * I have decided that it is not worth fixing it - especially as it works
+ * pretty well.
+ * rgerhards, 2007-06-15
+ */
+ if(bWasNL) {
+ fprintf(stdout, "%8.8d: ", (unsigned int) pthread_self());
+ }
+ bWasNL = (*(fmt + strlen(fmt) - 1) == '\n') ? TRUE : FALSE;
+# endif
+ va_start(ap, fmt);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ fflush(stdout);
+ return;
+}
+
+
+/*
+ * The following function is resposible for handling a SIGHUP signal. Since
+ * we are now doing mallocs/free as part of init we had better not being
+ * doing this during a signal handler. Instead this function simply sets
+ * a flag variable which will tell the main loop to go through a restart.
+ */
+void sighup_handler()
+{
+ restart = 1;
+ signal(SIGHUP, sighup_handler);
+ return;
+}
+
+
+/**
+ * getSubString
+ *
+ * Copy a string byte by byte until the occurrence
+ * of a given separator.
+ *
+ * \param ppSrc Pointer to a pointer of the source array of characters. If a
+ separator detected the Pointer points to the next char after the
+ separator. Except if the end of the string is dedected ('\n').
+ Then it points to the terminator char.
+ * \param pDst Pointer to the destination array of characters. Here the substing
+ will be stored.
+ * \param DstSize Maximum numbers of characters to store.
+ * \param cSep Separator char.
+ * \ret int Returns 0 if no error occured.
+ */
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
+{
+ uchar *pSrc = *ppSrc;
+ int iErr = 0; /* 0 = no error, >0 = error */
+ while(*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
+ *pDst++ = *(pSrc)++;
+ DstSize--;
+ }
+ /* check if the Dst buffer was to small */
+ if (*pSrc != cSep && *pSrc != '\n' && *pSrc != '\0')
+ {
+ dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
+ iErr = 1;
+ }
+ if (*pSrc == '\0' || *pSrc == '\n')
+ /* this line was missing, causing ppSrc to be invalid when it
+ * was returned in case of end-of-string. rgerhards 2005-07-29
+ */
+ *ppSrc = pSrc;
+ else
+ *ppSrc = pSrc+1;
+ *pDst = '\0';
+ return iErr;
+}
+
+
+/* print out which socket we are listening on. This is only
+ * a debug aid. rgerhards, 2007-07-02
+ */
+static void debugListenInfo(int fd, char *type)
+{
+ char *szFamily;
+ int port;
+ struct sockaddr sa;
+ struct sockaddr_in *ipv4;
+ struct sockaddr_in6 *ipv6;
+ socklen_t saLen = sizeof(sa);
+
+ if(getsockname(fd, &sa, &saLen) == 0) {
+ switch(sa.sa_family) {
+ case PF_INET:
+ szFamily = "IPv4";
+ ipv4 = (struct sockaddr_in*) &sa;
+ port = ntohs(ipv4->sin_port);
+ break;
+ case PF_INET6:
+ szFamily = "IPv6";
+ ipv6 = (struct sockaddr_in6*) &sa;
+ port = ntohs(ipv6->sin6_port);
+ break;
+ default:
+ szFamily = "other";
+ port = -1;
+ break;
+ }
+ dbgprintf("Listening on %s syslogd socket %d (%s/port %d).\n",
+ type, fd, szFamily, port);
+ return;
+ }
+
+ /* we can not obtain peer info. We are just providing
+ * debug info, so this is no reason to break the program
+ * or do any serious error reporting.
+ */
+ dbgprintf("Listening on syslogd socket %d - could not obtain peer info.\n", fd);
+}
+
+
+/* this function pulls all internal messages from the buffer
+ * and puts them into the processing engine.
+ * We can only do limited error handling, as this would not
+ * really help us. TODO: add error messages?
+ * rgerhards, 2007-08-03
+ */
+static void processImInternal(void)
+{
+ int iPri;
+ int iFlags;
+ msg_t *pMsg;
+
+ while(iminternalRemoveMsg(&iPri, &pMsg, &iFlags) == RS_RET_OK) {
+ logmsg(iPri, pMsg, iFlags);
+ MsgDestruct(pMsg);
+ }
+}
+
+
+/* helper function for mainloop(). This is used to add all module
+ * writeFDsfor Select via llExecFunc().
+ * rgerhards, 2007-08-02
+ */
+typedef struct selectHelperWriteFDSInfo_s { /* struct for pParam */
+ fd_set *pWritefds;
+ int *pMaxfds;
+} selectHelperWriteFDSInfo_t;
+DEFFUNC_llExecFunc(mainloopAddModWriteFDSforSelect)
+{
+ DEFiRet;
+ action_t *pAction = (action_t*) pData;
+ selectHelperWriteFDSInfo_t *pState = (selectHelperWriteFDSInfo_t*) pParam;
+ short fdMod;
+
+ assert(pAction != NULL);
+ assert(pState != NULL);
+
+ if(pAction->pMod->getWriteFDForSelect(pAction->pModData, &fdMod) == RS_RET_OK) {
+ FD_SET(fdMod, pState->pWritefds);
+ if(fdMod > *pState->pMaxfds)
+ *pState->pMaxfds = fdMod;
+ }
+
+ return iRet;
+}
+
+
+/* helper function for mainloop(). This is used to call module action
+ * handlers after select if a fd is writable.
+ * HINT: when we change to the new threading model, this function
+ * is probably no longer needed.
+ * rgerhards, 2007-08-02
+ */
+DEFFUNC_llExecFunc(mainloopCallWithWritableFDsActions)
+{
+ DEFiRet;
+ action_t *pAction = (action_t*) pData;
+ selectHelperWriteFDSInfo_t *pState = (selectHelperWriteFDSInfo_t*) pParam;
+ short fdMod;
+
+ assert(pAction != NULL);
+ assert(pState != NULL);
+
+ if(pAction->pMod->getWriteFDForSelect(pAction->pModData, &fdMod) == RS_RET_OK) {
+ if(FD_ISSET(fdMod, pState->pWritefds)) {
+ if((iRet = pAction->pMod->onSelectReadyWrite(pAction->pModData))
+ != RS_RET_OK) {
+ dbgprintf("error %d from onSelectReadyWrite() - continuing\n", iRet);
+ }
+ if(--(pState->pMaxfds) == 0) {
+ ABORT_FINALIZE(RS_RET_FINISHED); /* all processed, nothing left to do */
+ }
+ }
+ }
+
+finalize_it:
+ return iRet;
+}
+
+
+/* process the select() selector array after the successful select.
+ * processing is completed as soon as all selectors needing attention
+ * are processed.
+ * rgerhards, 2007-08-08
+ */
+static rsRetVal processSelectAfter(int maxfds, int nfds, fd_set *pReadfds, fd_set *pWritefds)
+{
+ DEFiRet;
+ rsRetVal iRetLL;
+ int i;
+ int fd;
+ char line[MAXLINE +1];
+ selectHelperWriteFDSInfo_t writeFDSInfo;
+#ifdef SYSLOG_INET
+ selector_t *f;
+ struct sockaddr_storage frominet;
+ socklen_t socklen;
+ uchar fromHost[NI_MAXHOST];
+ uchar fromHostFQDN[NI_MAXHOST];
+ int iTCPSess;
+ ssize_t l;
+#endif /* #ifdef SYSLOG_INET */
+
+ /* the following macro is used to decrement the number of to-be-probed
+ * fds and abort this function when we are done with all.
+ */
+# define FDPROCESSED() if(--nfds == 0) { dbgprintf("nfds == 0, aborting\n");ABORT_FINALIZE(RS_RET_OK); }
+
+ if (nfds < 0) {
+ if (errno != EINTR)
+ logerror("select");
+ dbgprintf("Select interrupted.\n");
+ ABORT_FINALIZE(RS_RET_OK); /* we are done in any case */
+ }
+
+ if(debugging_on) {
+ dbgprintf("\nSuccessful select, descriptor count = %d, Activity on: ", nfds);
+ for (i = 0; i <= maxfds; ++i)
+ if ( FD_ISSET(i, pReadfds) )
+ dbgprintf("%d ", i);
+ dbgprintf(("\n"));
+ }
+
+#ifdef SYSLOG_INET
+ /* Now check the TCP send sockets. So far, we only see if they become
+ * writable and then change their internal status. No real async
+ * writing is currently done. This code will be replaced once liblogging
+ * is used, thus we try not to focus too much on it.
+ *
+ * IMPORTANT: With the current code, the writefds must be checked first,
+ * because the readfds might have messages to be forwarded, which
+ * rely on the status setting that is done here!
+ * rgerhards 2005-07-20
+ *
+ * liblogging implementation will not happen as anticipated above. So
+ * this code here will stay for quite a while.
+ * rgerhards, 2006-12-07
+ */
+ writeFDSInfo.pWritefds = pWritefds;
+ writeFDSInfo.pMaxfds = &nfds;
+ for(f = Files; f != NULL ; f = f->f_next) {
+ iRetLL = llExecFunc(&f->llActList, mainloopCallWithWritableFDsActions, &writeFDSInfo);
+ if(iRetLL == RS_RET_FINISHED) {
+ ABORT_FINALIZE(RS_RET_OK); /* we are done in this case */
+ }
+ }
+#endif /* #ifdef SYSLOG_INET */
+#ifdef SYSLOG_UNIXAF
+ for (i = 0; i < nfunix; i++) {
+ if ((fd = funix[i]) != -1 && FD_ISSET(fd, pReadfds)) {
+ int iRcvd;
+ iRcvd = recv(fd, line, MAXLINE - 1, 0);
+ dbgprintf("Message from UNIX socket: #%d\n", fd);
+ if (iRcvd > 0) {
+ printchopped(LocalHostName, line, iRcvd, fd, funixParseHost[i]);
+ } else if (iRcvd < 0 && errno != EINTR) {
+ dbgprintf("UNIX socket error: %d = %s.\n", \
+ errno, strerror(errno));
+ logerror("recvfrom UNIX");
+ }
+ FDPROCESSED();
+ }
+ }
+#endif
+
+#ifdef SYSLOG_INET
+ if (finet != NULL && AcceptRemote) {
+ for (i = 0; i < *finet; i++) {
+ if (FD_ISSET(finet[i+1], pReadfds)) {
+ socklen = sizeof(frominet);
+ memset(line, '\0', sizeof(line));
+ l = recvfrom(finet[i+1], line, MAXLINE - 1, 0,
+ (struct sockaddr *)&frominet, &socklen);
+ if (l > 0) {
+ line[l] = '\0';
+ if(cvthname(&frominet, fromHost, fromHostFQDN) == 1) {
+ dbgprintf("Message from inetd socket: #%d, host: %s\n",
+ finet[i+1], fromHost);
+ /* Here we check if a host is permitted to send us
+ * syslog messages. If it isn't, we do not further
+ * process the message but log a warning (if we are
+ * configured to do this).
+ * rgerhards, 2005-09-26
+ */
+ if(isAllowedSender(pAllowedSenders_UDP,
+ (struct sockaddr *)&frominet, (char*)fromHostFQDN)) {
+ printchopped((char*)fromHost, line, l, finet[i+1], 1);
+ } else {
+ if(option_DisallowWarning) {
+ logerrorSz("UDP message from disallowed sender %s discarded",
+ (char*)fromHost);
+ }
+ }
+ }
+ }
+ else if (l < 0 && errno != EINTR && errno != EAGAIN) {
+ dbgprintf("INET socket error: %d = %s.\n",
+ errno, strerror(errno));
+ logerror("recvfrom inet");
+ /* should be harmless */
+ sleep(1);
+ }
+ FDPROCESSED();
+ }
+ }
+ }
+
+ if(sockTCPLstn != NULL && *sockTCPLstn) {
+ for (i = 0; i < *sockTCPLstn; i++) {
+ if (FD_ISSET(sockTCPLstn[i+1], pReadfds)) {
+ dbgprintf("New connect on TCP inetd socket: #%d\n", sockTCPLstn[i+1]);
+ TCPSessAccept(sockTCPLstn[i+1]);
+ FDPROCESSED();
+ }
+ }
+
+ /* now check the sessions */
+ iTCPSess = TCPSessGetNxtSess(-1);
+ while(iTCPSess != -1) {
+ int fdSess;
+ int state;
+ fdSess = pTCPSessions[iTCPSess].sock;
+ if(FD_ISSET(fdSess, pReadfds)) {
+ char buf[MAXLINE];
+ dbgprintf("tcp session socket with new data: #%d\n", fdSess);
+
+ /* Receive message */
+ state = recv(fdSess, buf, sizeof(buf), 0);
+ if(state == 0) {
+ /* process any incomplete frames left over */
+ TCPSessPrepareClose(iTCPSess);
+ /* Session closed */
+ TCPSessClose(iTCPSess);
+ } else if(state == -1) {
+ logerrorInt("TCP session %d will be closed, error ignored\n",
+ fdSess);
+ TCPSessClose(iTCPSess);
+ } else {
+ /* valid data received, process it! */
+ if(TCPSessDataRcvd(iTCPSess, buf, state) == 0) {
+ /* in this case, something went awfully wrong.
+ * We are instructed to terminate the session.
+ */
+ logerrorInt("Tearing down TCP Session %d - see "
+ "previous messages for reason(s)\n",
+ iTCPSess);
+ TCPSessClose(iTCPSess);
+ }
+ }
+ FDPROCESSED();
+ }
+ iTCPSess = TCPSessGetNxtSess(iTCPSess);
+ }
+ }
+
+#endif
+finalize_it:
+ return iRet;
+}
+
+
+static void mainloop(void)
+{
+ fd_set readfds;
+ int i;
+ int maxfds;
+ int nfds;
+#ifdef SYSLOG_INET
+ selectHelperWriteFDSInfo_t writeFDSInfo;
+ fd_set writefds;
+ selector_t *f;
+ int iTCPSess;
+#endif /* #ifdef SYSLOG_INET */
+#ifdef BSD
+#ifdef USE_PTHREADS
+ struct timeval tvSelectTimeout;
+#endif
+#endif
+
+ errno = 0;
+ FD_ZERO(&readfds);
+ maxfds = 0;
+
+ while(!bFinished){
+ /* first check if we have any internal messages queued and spit them out */
+ processImInternal();
+
+#ifdef SYSLOG_UNIXAF
+ /* 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..
+ */
+ /* 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];
+ }
+ }
+#endif
+#ifdef SYSLOG_INET
+ /* Add the UDP listen sockets to the list of read descriptors.
+ */
+ if(finet != NULL && AcceptRemote) {
+ for (i = 0; i < *finet; i++) {
+ if (finet[i+1] != -1) {
+ if(Debug)
+ debugListenInfo(finet[i+1], "UDP");
+ FD_SET(finet[i+1], &readfds);
+ if(finet[i+1]>maxfds) maxfds=finet[i+1];
+ }
+ }
+ }
+
+ /* Add the TCP listen sockets to the list of read descriptors.
+ */
+ if(sockTCPLstn != NULL && *sockTCPLstn) {
+ for (i = 0; i < *sockTCPLstn; i++) {
+ /* The if() below is theoretically not needed, but I leave it in
+ * so that a socket may become unsuable during execution. That
+ * feature is not yet supported by the current code base.
+ */
+ if (sockTCPLstn[i+1] != -1) {
+ if(Debug)
+ debugListenInfo(sockTCPLstn[i+1], "TCP");
+ FD_SET(sockTCPLstn[i+1], &readfds);
+ if(sockTCPLstn[i+1]>maxfds) maxfds=sockTCPLstn[i+1];
+ }
+ }
+ /* do the sessions */
+ iTCPSess = TCPSessGetNxtSess(-1);
+ while(iTCPSess != -1) {
+ int fdSess;
+ fdSess = pTCPSessions[iTCPSess].sock;
+ dbgprintf("Adding TCP Session %d\n", fdSess);
+ FD_SET(fdSess, &readfds);
+ if (fdSess>maxfds) maxfds=fdSess;
+ /* now get next... */
+ iTCPSess = TCPSessGetNxtSess(iTCPSess);
+ }
+ }
+
+ /* TODO: activate the code below only if we actually need to check
+ * for outstanding writefds.
+ */
+ if(1) {
+ /* Now add the TCP output sockets to the writefds set. This implementation
+ * is not optimal (performance-wise) and it should be replaced with something
+ * better in the longer term. I've not yet done this, as this code is
+ * scheduled to be replaced after the liblogging integration.
+ * rgerhards 2005-07-20
+ */
+ FD_ZERO(&writefds);
+ writeFDSInfo.pWritefds = &writefds;
+ writeFDSInfo.pMaxfds = &maxfds;
+ for (f = Files; f != NULL ; f = f->f_next) {
+ llExecFunc(&f->llActList, mainloopAddModWriteFDSforSelect, &writeFDSInfo);
+ }
+ }
+#endif
+
+ if ( debugging_on ) {
+ dbgprintf("----------------------------------------\n");
+ dbgprintf("Calling select, active file descriptors (max %d): ", maxfds);
+ for (nfds= 0; nfds <= maxfds; ++nfds)
+ if ( FD_ISSET(nfds, &readfds) )
+ dbgprintf("%d ", nfds);
+ dbgprintf("\n");
+ }
+
+#define MAIN_SELECT_TIMEVAL NULL
+#ifdef BSD
+#ifdef USE_PTHREADS
+ /* There seems to be a problem with BSD and threads. When running on
+ * multiple threads, a signal will not cause the select call to be
+ * interrrupted. I am not sure if this is by design or an bug (some
+ * information on the web let's me think it is a bug), but that really
+ * does not matter. The issue with our code is that we will not gain
+ * control when rsyslogd is terminated or huped. What I am doing now is
+ * make the select call timeout after 10 seconds, so that we can check
+ * the condition then. Obviously, this causes some sluggish behaviour and
+ * also the loss of some (very few) cpu cycles. Both, I think, are
+ * absolutely acceptable.
+ * rgerhards, 2005-10-26
+ * TODO: I got some information: this seems to be expected signal() behaviour
+ * we should investigate the use of sigaction() (see klogd.c for an sample).
+ * rgerhards, 2007-06-22
+ */
+ tvSelectTimeout.tv_sec = 10;
+ tvSelectTimeout.tv_usec = 0;
+# undef MAIN_SELECT_TIMEVAL
+# define MAIN_SELECT_TIMEVAL &tvSelectTimeout
+#endif
+#endif
+#ifdef SYSLOG_INET
+#define MAIN_SELECT_WRITEFDS (fd_set *) &writefds
+#else
+#define MAIN_SELECT_WRITEFDS NULL
+#endif
+ nfds = select(maxfds+1, (fd_set *) &readfds, MAIN_SELECT_WRITEFDS,
+ (fd_set *) NULL, MAIN_SELECT_TIMEVAL);
+
+ if(bRequestDoMark) {
+ domark();
+ bRequestDoMark = 0;
+ /* We do not use continue, because domark() is carried out
+ * only when something else happened.
+ */
+ }
+ if(restart) {
+ dbgprintf("\nReceived SIGHUP, reloading rsyslogd.\n");
+ /* worker thread is stopped as part of init() */
+ init();
+ restart = 0;
+ continue;
+ }
+ if (nfds == 0) {
+ dbgprintf("No select activity.\n");
+ continue;
+ }
+
+ processSelectAfter(maxfds, nfds, &readfds, MAIN_SELECT_WRITEFDS);
+
+#undef MAIN_SELECT_TIMEVAL
+#undef MAIN_SELECT_WRITEFDS
+ }
+}
+
+/* If user is not root, prints warnings or even exits
+ * TODO: check all dynafiles for write permission
+ * ... but it is probably better to wait here until we have
+ * a module interface - rgerhards, 2007-07-23
+ */
+static void checkPermissions()
+{
+ /* we are not root */
+ if (geteuid() != 0)
+ {
+ fputs("WARNING: Local messages will not be logged! If you want to log them, run rsyslog as root.\n",stderr);
+#ifdef SYSLOG_INET
+ /* udp enabled and port number less than or equal to 1024 */
+ if ( AcceptRemote && (atoi(LogPort) <= 1024) )
+ fprintf(stderr, "WARNING: Will not listen on UDP port %s. Use port number higher than 1024 or run rsyslog as root!\n", LogPort);
+
+ /* tcp enabled and port number less or equal to 1024 */
+ if( bEnableTCP && (atoi(TCPLstnPort) <= 1024) )
+ fprintf(stderr, "WARNING: Will not listen on TCP port %s. Use port number higher than 1024 or run rsyslog as root!\n", TCPLstnPort);
+
+ /* Neither explicit high UDP port nor explicit high TCP port.
+ * It is useless to run anymore */
+ if( !(AcceptRemote && (atoi(LogPort) > 1024)) && !( bEnableTCP && (atoi(TCPLstnPort) > 1024)) )
+ {
+#endif
+ fprintf(stderr, "ERROR: Nothing to log, no reason to run. Please run rsyslog as root.\n");
+ exit(EXIT_FAILURE);
+#ifdef SYSLOG_INET
+ }
+#endif
+ }
+}
+
+
+/* load build-in modules
+ * very first version begun on 2007-07-23 by rgerhards
+ */
+static rsRetVal loadBuildInModules(void)
+{
+ DEFiRet;
+
+ if((iRet = doModInit(modInitFile, (uchar*) "builtin-file")) != RS_RET_OK)
+ return iRet;
+#ifdef SYSLOG_INET
+ if((iRet = doModInit(modInitFwd, (uchar*) "builtin-fwd")) != RS_RET_OK)
+ return iRet;
+#endif
+ if((iRet = doModInit(modInitShell, (uchar*) "builtin-shell")) != RS_RET_OK)
+ return iRet;
+# ifdef WITH_DB
+ if((iRet = doModInit(modInitMySQL, (uchar*) "builtin-mysql")) != RS_RET_OK)
+ return iRet;
+# endif
+ if((iRet = doModInit(modInitDiscard, (uchar*) "builtin-discard")) != RS_RET_OK)
+ return iRet;
+
+ /* dirty, but this must be for the time being: the usrmsg module must always be
+ * loaded as last module. This is because it processes any time of action selector.
+ * If we load it before other modules, these others will never have a chance of
+ * working with the config file. We may change that implementation so that a user name
+ * must start with an alnum, that would definitely help (but would it break backwards
+ * compatibility?). * rgerhards, 2007-07-23
+ */
+ if((iRet = doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg")) != RS_RET_OK)
+ return iRet;
+
+ /* ok, initialization of the command handler probably does not 100% belong right in
+ * this space here. However, with the current design, this is actually quite a good
+ * place to put it. We might decide to shuffle it around later, but for the time
+ * being, the code has found its home here. A not-just-sideeffect of this decision
+ * 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
+ */
+#ifdef USE_PTHREADS
+ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize));
+#endif
+ CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp));
+ CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar));
+ CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv));
+ CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs));
+ CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF));
+ CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_TEMPLATE));
+ CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_OUTCHANNEL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, doNameLine, (void*)DIR_ALLOWEDSENDER));
+ CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, doModLoad, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler, doIncludeLine, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, setUmask, NULL));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintTemplateList));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintModuleList));
+ CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
+ NULL, &bDebugPrintCfSysLineHandlerList));
+ CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL));
+
+finalize_it:
+ return iRet;
+}
+
+
+/* print version and compile-time setting information.
+ */
+static void printVersion(void)
+{
+ printf("rsyslogd %s, ", VERSION);
+ printf("compiled with:\n");
+#ifdef USE_PTHREADS
+ printf("\tFEATURE_PTHREADS (dual-threading):\tYes\n");
+#else
+ printf("\tFEATURE_PTHREADS (dual-threading):\tNo\n");
+#endif
+#ifdef FEATURE_REGEXP
+ printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
+#else
+ printf("\tFEATURE_REGEXP:\t\t\t\tNo\n");
+#endif
+#ifdef WITH_DB
+ printf("\tFEATURE_DB (MySQL):\t\t\tYes\n");
+#else
+ printf("\tFEATURE_DB (MySQL):\t\t\tNo\n");
+#endif
+#ifndef NOLARGEFILE
+ printf("\tFEATURE_LARGEFILE:\t\t\tYes\n");
+#else
+ printf("\tFEATURE_LARGEFILE:\t\t\tNo\n");
+#endif
+#ifdef USE_NETZIP
+ printf("\tFEATURE_NETZIP (message compression):\tYes\n");
+#else
+ printf("\tFEATURE_NETZIP (message compression):\tNo\n");
+#endif
+#ifdef SYSLOG_INET
+ printf("\tSYSLOG_INET (Internet/remote support):\tYes\n");
+#else
+ printf("\tSYSLOG_INET (Internet/remote support):\tNo\n");
+#endif
+#ifndef NDEBUG
+ printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
+#else
+ printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
+#endif
+ printf("\nSee http://www.rsyslog.com for more information.\n");
+}
+
+
+int main(int argc, char **argv)
+{ register int i;
+ register char *p;
+ int num_fds;
+ rsRetVal iRet;
+
+#ifdef MTRACE
+ mtrace(); /* this is a debug aid for leak detection - either remove
+ * or put in conditional compilation. 2005-01-18 RGerhards */
+#endif
+
+ pid_t ppid = getpid();
+ int ch;
+ struct hostent *hent;
+
+ extern int optind;
+ extern char *optarg;
+ uchar *pTmp;
+
+ if(chdir ("/") != 0)
+ fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
+ for (i = 1; i < MAXFUNIX; i++) {
+ funixn[i] = "";
+ funix[i] = -1;
+ }
+
+ /* doing some core initializations */
+ if((iRet = modInitIminternal()) != RS_RET_OK) {
+ fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
+ iRet);
+ exit(1); /* "good" exit, leaving at init for fatal error */
+ }
+
+ if((iRet = loadBuildInModules()) != RS_RET_OK) {
+ fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
+ iRet);
+ exit(1); /* "good" exit, leaving at init for fatal error */
+ }
+
+ /* END core initializations */
+
+ while ((ch = getopt(argc, argv, "46Aa:dehi:f:l:m:nop:r::s:t:u:vwx")) != EOF) {
+ switch((char)ch) {
+ case '4':
+ family = PF_INET;
+ break;
+ case '6':
+ family = PF_INET6;
+ break;
+ case 'A':
+ send_to_all++;
+ break;
+ case 'a':
+ if (nfunix < MAXFUNIX)
+ if(*optarg == ':') {
+ funixParseHost[nfunix] = 1;
+ funixn[nfunix++] = optarg+1;
+ }
+ else {
+ funixParseHost[nfunix] = 0;
+ funixn[nfunix++] = optarg;
+ }
+ else
+ fprintf(stderr, "rsyslogd: Out of descriptors, ignoring %s\n", optarg);
+ break;
+ case 'd': /* debug */
+ Debug = 1;
+ break;
+ case 'e': /* log every message (no repeat message supression) */
+ logEveryMsg = 1;
+ break;
+ case 'f': /* configuration file */
+ ConfFile = (uchar*) optarg;
+ break;
+ case 'h':
+ NoHops = 0;
+ break;
+ case 'i': /* pid file name */
+ PidFile = optarg;
+ break;
+ case 'l':
+ if (LocalHosts) {
+ fprintf (stderr, "rsyslogd: Only one -l argument allowed," \
+ "the first one is taken.\n");
+ break;
+ }
+ LocalHosts = crunch_list(optarg);
+ break;
+ case 'm': /* mark interval */
+ MarkInterval = atoi(optarg) * 60;
+ break;
+ case 'n': /* don't fork */
+ NoFork = 1;
+ break;
+ case 'o': /* omit local logging (/dev/log) */
+ startIndexUxLocalSockets = 1;
+ break;
+ case 'p': /* path to regular log socket */
+ funixn[0] = optarg;
+ break;
+ case 'r': /* accept remote messages */
+ AcceptRemote = 1;
+ if(optarg == NULL)
+ LogPort = "0";
+ else
+ LogPort = optarg;
+ break;
+ case 's':
+ if (StripDomains) {
+ fprintf (stderr, "rsyslogd: Only one -s argument allowed," \
+ "the first one is taken.\n");
+ break;
+ }
+ StripDomains = crunch_list(optarg);
+ break;
+ case 't': /* enable tcp logging */
+#ifdef SYSLOG_INET
+ configureTCPListen(optarg);
+#else
+ fprintf(stderr, "rsyslogd: -t not valid - not compiled for network support");
+#endif
+ break;
+ case 'u': /* misc user settings */
+ if(atoi(optarg) == 1)
+ bParseHOSTNAMEandTAG = 0;
+ break;
+ case 'v':
+ printVersion();
+ exit(0); /* exit for -v option - so this is a "good one" */
+ case 'w': /* disable disallowed host warnigs */
+ option_DisallowWarning = 0;
+ break;
+ case 'x': /* disable dns for remote messages */
+ DisableDNS = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+
+ if ((argc -= optind))
+ usage();
+
+ checkPermissions();
+
+ if ( !(Debug || NoFork) )
+ {
+ dbgprintf("Checking pidfile.\n");
+ if (!check_pid(PidFile))
+ {
+ signal (SIGTERM, doexit);
+ if (fork()) {
+ /*
+ * Parent process
+ */
+ sleep(300);
+ /*
+ * Not reached unless something major went wrong. 5
+ * minutes should be a fair amount of time to wait.
+ * Please note that this procedure is important since
+ * the father must not exit before syslogd isn't
+ * initialized or the klogd won't be able to flush its
+ * logs. -Joey
+ */
+ exit(1); /* "good" exit - after forking, not diasabling anything */
+ }
+ num_fds = getdtablesize();
+ for (i= 0; i < num_fds; i++)
+ (void) close(i);
+ untty();
+ }
+ else
+ {
+ fputs(" Already running.\n", stderr);
+ exit(1); /* "good" exit, done if syslogd is already running */
+ }
+ }
+ else
+ debugging_on = 1;
+
+ /* tuck my process id away */
+ if ( !Debug )
+ {
+ dbgprintf("Writing pidfile.\n");
+ if (!check_pid(PidFile))
+ {
+ if (!write_pid(PidFile))
+ {
+ dbgprintf("Can't write pid.\n");
+ exit(1); /* exit during startup - questionable */
+ }
+ }
+ else
+ {
+ dbgprintf("Pidfile (and pid) already exist.\n");
+ exit(1); /* exit during startup - questionable */
+ }
+ } /* if ( !Debug ) */
+ myPid = getpid(); /* save our pid for further testing (also used for messages) */
+
+ /* initialize the default templates
+ * we use template names with a SP in front - these
+ * can NOT be generated via the configuration file
+ */
+ pTmp = template_TraditionalFormat;
+ tplAddLine(" TradFmt", &pTmp);
+ pTmp = template_WallFmt;
+ tplAddLine(" WallFmt", &pTmp);
+ pTmp = template_StdFwdFmt;
+ tplAddLine(" StdFwdFmt", &pTmp);
+ pTmp = template_StdUsrMsgFmt;
+ tplAddLine(" StdUsrMsgFmt", &pTmp);
+ pTmp = template_StdDBFmt;
+ tplLastStaticInit(tplAddLine(" StdDBFmt", &pTmp));
+
+ gethostname(LocalHostName, sizeof(LocalHostName));
+ if ( (p = strchr(LocalHostName, '.')) ) {
+ *p++ = '\0';
+ LocalDomain = p;
+ }
+ else
+ {
+ LocalDomain = "";
+
+ /*
+ * It's not clearly defined whether gethostname()
+ * should return the simple hostname or the fqdn. A
+ * good piece of software should be aware of both and
+ * we want to distribute good software. Joey
+ *
+ * Good software also always checks its return values...
+ * If syslogd starts up before DNS is up & /etc/hosts
+ * doesn't have LocalHostName listed, gethostbyname will
+ * return NULL.
+ */
+ hent = gethostbyname(LocalHostName);
+ if ( hent )
+ snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
+
+ if ( (p = strchr(LocalHostName, '.')) )
+ {
+ *p++ = '\0';
+ LocalDomain = p;
+ }
+ }
+
+ /* Convert to lower case to recognize the correct domain laterly
+ */
+ for (p = (char *)LocalDomain; *p ; p++)
+ if (isupper((int) *p))
+ *p = tolower(*p);
+
+ (void) signal(SIGTERM, doDie);
+ (void) signal(SIGINT, Debug ? doDie : SIG_IGN);
+ (void) signal(SIGQUIT, Debug ? doDie : SIG_IGN);
+ (void) signal(SIGCHLD, reapchild);
+ (void) signal(SIGALRM, domarkAlarmHdlr);
+ (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN);
+ (void) signal(SIGPIPE, SIG_IGN);
+ (void) signal(SIGXFSZ, SIG_IGN); /* do not abort if 2gig file limit is hit */
+ (void) alarm(TIMERINTVL);
+
+ dbgprintf("Starting.\n");
+ init();
+ if(Debug) {
+ dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n");
+ debugging_on = 1;
+ }
+ /*
+ * Send a signal to the parent to it can terminate.
+ */
+ if (myPid != ppid)
+ kill (ppid, SIGTERM);
+ /* END OF INTIALIZATION
+ * ... but keep in mind that we might do a restart and thus init() might
+ * be called again. If that happens, we must shut down all active threads,
+ * do the init() and then restart things.
+ * rgerhards, 2005-10-24
+ */
+
+ mainloop();
+ /* end de-init's */
+
+ die(bFinished);
+ return 0;
+}
+
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ * vi:set ai:
+ */
diff --git a/syslogd.h b/syslogd.h
new file mode 100644
index 0000000..080f15e
--- /dev/null
+++ b/syslogd.h
@@ -0,0 +1,88 @@
+/* common header for syslogd
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef SYSLOGD_H_INCLUDED
+#define SYSLOGD_H_INCLUDED 1
+
+#include "syslogd-types.h"
+#include "objomsr.h"
+
+#ifdef USE_NETZIP
+#include <unistd.h>
+#include <zlib.h>
+/* config param: minimum message size to try compression. The smaller
+ * the message, the less likely is any compression gain. We check for
+ * gain before we submit the message. But to do so we still need to
+ * do the (costly) compress() call. The following setting sets a size
+ * for which no call to compress() is done at all. This may result in
+ * a few more bytes being transmited but better overall performance.
+ * Note: I have not yet checked the minimum UDP packet size. It might be
+ * that we do not save anything by compressing very small messages, because
+ * UDP might need to pad ;)
+ * rgerhards, 2006-11-30
+ */
+#define MIN_SIZE_FOR_COMPRESS 60
+#endif
+
+#define MAXLINE 2048 /* maximum line length */
+
+/* Flags to logmsg().
+ */
+#define INTERNAL_MSG 0x001 /* msg generated by logmsgInternal() --> special handling */
+#define SYNC_FILE 0x002 /* do fsync on file after printing */
+#define ADDDATE 0x004 /* add a date to the message */
+#define MARK 0x008 /* this message is a mark */
+
+void dbgprintf(char *, ...);
+void logerror(char *type);
+void logerrorSz(char *type, char *errMsg);
+void logerrorInt(char *type, int iErr);
+
+void printchopped(char *hname, char *msg, int len, int fd, int iSourceType);
+void freeAllSockets(int **socks);
+int isAllowedSender(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost);
+void getCurrTime(struct syslogTime *t);
+int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst);
+int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
+int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf);
+void untty(void);
+rsRetVal cflineParseTemplateName(uchar** pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName);
+rsRetVal cflineParseFileName(uchar* p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts);
+int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
+
+extern int glblHadMemShortage; /* indicates if we had memory shortage some time during the run */
+extern syslogCODE rs_prioritynames[];
+extern syslogCODE rs_facilitynames[];
+extern char LocalHostName[];
+extern int family;
+extern int NoHops;
+extern int *finet;
+extern int send_to_all;
+extern int option_DisallowWarning;
+extern int Debug;
+extern char**LocalHosts;
+extern int DisableDNS;
+extern char **StripDomains;
+extern char *LocalDomain;
+extern int bDropMalPTRMsgs;
+extern struct AllowedSenders *pAllowedSenders_TCP;
+extern char ctty[];
+extern int bModMySQLLoaded;
+
+#endif /* #ifndef SYSLOGD_H_INCLUDED */
diff --git a/tcpsyslog.c b/tcpsyslog.c
new file mode 100644
index 0000000..27ef8e4
--- /dev/null
+++ b/tcpsyslog.c
@@ -0,0 +1,692 @@
+/* tcpsyslog.c
+ * This is the implementation of TCP-based syslog.
+ *
+ * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c)
+ * This file is under development and has not yet arrived at being fully
+ * self-contained and a real object. So far, it is mostly an excerpt
+ * of the "old" message code without any modifications. However, it
+ * helps to have things at the right place one we go to the meat of it.
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "syslogd.h"
+#include "syslogd-types.h"
+#include "net.h"
+#include "tcpsyslog.h"
+/********************************************************************
+ * ### SYSLOG/TCP CODE ###
+ * This is code for syslog/tcp. This code would belong to a separate
+ * file - but I have put it here to avoid hassle with CVS. Over
+ * time, I expect rsyslog to utilize liblogging for actual network
+ * I/O. So the tcp code will be (re)moved some time. I don't like
+ * to add a new file to cvs that I will push to the attic in just
+ * a few weeks (month at most...). So I simply add the code here.
+ *
+ * Place no unrelated code between this comment and the
+ * END tcp comment!
+ *
+ * 2005-07-04 RGerhards (Happy independence day to our US friends!)
+ ********************************************************************/
+#ifdef SYSLOG_INET
+
+#define TCPSESS_MAX_DEFAULT 200 /* default for nbr of tcp sessions if no number is given */
+
+static int iTCPSessMax = TCPSESS_MAX_DEFAULT; /* actual number of sessions */
+char *TCPLstnPort = "0"; /* read-only after startup */
+int bEnableTCP = 0; /* read-only after startup */
+int *sockTCPLstn = NULL; /* read-only after startup, modified by restart */
+struct TCPSession *pTCPSessions;
+/* The thread-safeness of the sesion table is doubtful */
+
+
+/* configure TCP listener settings. This is called during command
+ * line parsing. The argument following -t is supplied as an argument.
+ * The format of this argument is
+ * "<port-to-use>, <nbr-of-sessions>"
+ * Typically, there is no whitespace between port and session number.
+ * (but it may be...).
+ * NOTE: you can not use dbgprintf() in here - the dbgprintf() system is
+ * not yet initilized when this function is called.
+ * rgerhards, 2007-06-21
+ * We can also not use logerror(), as that system is also not yet
+ * initialized... rgerhards, 2007-06-28
+ */
+void configureTCPListen(char *cOptarg)
+{
+ register int i;
+ register char *pArg = cOptarg;
+
+ assert(cOptarg != NULL);
+ bEnableTCP = -1; /* enable TCP listening */
+
+ /* extract port */
+ i = 0;
+ while(isdigit((int) *pArg)) {
+ i = i * 10 + *pArg++ - '0';
+ }
+
+ if( i >= 0 && i <= 65535) {
+ TCPLstnPort = cOptarg;
+ } else {
+ fprintf(stderr, "rsyslogd: Invalid TCP listen port %d - changed to 514.\n", i);
+ TCPLstnPort = "514";
+ }
+
+ /* number of sessions */
+ if(*pArg == ','){
+ *pArg = '\0'; /* hack: terminates port (see a few lines above, same buffer!) */
+ ++pArg;
+ while(isspace((int) *pArg))
+ ++pArg;
+ /* ok, here should be the number... */
+ i = 0;
+ while(isdigit((int) *pArg)) {
+ i = i * 10 + *pArg++ - '0';
+ }
+ if(i > 1)
+ iTCPSessMax = i;
+ else {
+ /* too small, need to adjust */
+ fprintf(stderr,
+ "rsyslogd: TCP session max configured to %d [-t %s] - changing to 1.\n",
+ i, cOptarg);
+ iTCPSessMax = 1;
+ }
+ } else if(*pArg == '\0') {
+ /* use default for session number - that's already set...*/
+ /*EMPTY BY INTENSION*/
+ } else {
+ fprintf(stderr, "rsyslogd: Invalid -t %s command line option.\n", cOptarg);
+ }
+}
+
+
+/* Initialize the session table
+ * returns 0 if OK, somewhat else otherwise
+ */
+static int TCPSessInit(void)
+{
+ register int i;
+
+ assert(pTCPSessions == NULL);
+ dbgprintf("Allocating buffer for %d TCP sessions.\n", iTCPSessMax);
+ if((pTCPSessions = (struct TCPSession *) malloc(sizeof(struct TCPSession) * iTCPSessMax))
+ == NULL) {
+ dbgprintf("Error: TCPSessInit() could not alloc memory for TCP session table.\n");
+ return(1);
+ }
+
+ for(i = 0 ; i < iTCPSessMax ; ++i) {
+ pTCPSessions[i].sock = -1; /* no sock */
+ pTCPSessions[i].iMsg = 0; /* just make sure... */
+ pTCPSessions[i].bAtStrtOfFram = 1; /* indicate frame header expected */
+ pTCPSessions[i].eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */
+ }
+ return(0);
+}
+
+
+/* find a free spot in the session table. If the table
+ * is full, -1 is returned, else the index of the free
+ * entry (0 or higher).
+ */
+static int TCPSessFindFreeSpot(void)
+{
+ register int i;
+
+ for(i = 0 ; i < iTCPSessMax ; ++i) {
+ if(pTCPSessions[i].sock == -1)
+ break;
+ }
+
+ return((i < iTCPSessMax) ? i : -1);
+}
+
+
+/* Get the next session index. Free session tables entries are
+ * skipped. This function is provided the index of the last
+ * session entry, or -1 if no previous entry was obtained. It
+ * returns the index of the next session or -1, if there is no
+ * further entry in the table. Please note that the initial call
+ * might as well return -1, if there is no session at all in the
+ * session table.
+ */
+int TCPSessGetNxtSess(int iCurr)
+{
+ register int i;
+
+ for(i = iCurr + 1 ; i < iTCPSessMax ; ++i)
+ if(pTCPSessions[i].sock != -1)
+ break;
+
+ return((i < iTCPSessMax) ? i : -1);
+}
+
+
+/* De-Initialize TCP listner sockets.
+ * This function deinitializes everything, including freeing the
+ * session table. No TCP listen receive operations are permitted
+ * unless the subsystem is reinitialized.
+ * rgerhards, 2007-06-21
+ */
+void deinit_tcp_listener(void)
+{
+ int iTCPSess;
+
+ assert(pTCPSessions != NULL);
+ /* close all TCP connections! */
+ iTCPSess = TCPSessGetNxtSess(-1);
+ while(iTCPSess != -1) {
+ int fd;
+ fd = pTCPSessions[iTCPSess].sock;
+ dbgprintf("Closing TCP Session %d\n", fd);
+ close(fd);
+ /* now get next... */
+ iTCPSess = TCPSessGetNxtSess(iTCPSess);
+ }
+
+ /* we are done with the session table - so get rid of it...
+ */
+ free(pTCPSessions);
+ pTCPSessions = NULL; /* just to make sure... */
+
+ /* finally close the listen sockets themselfs */
+ freeAllSockets(&sockTCPLstn);
+}
+
+
+/* Initialize TCP sockets (for listener)
+ * This function returns either NULL (which means it failed) or
+ * a pointer to an array of file descriptiors. If the pointer is
+ * returned, the zeroest element [0] contains the count of valid
+ * descriptors. The descriptors themself follow in range
+ * [1] ... [num-descriptors]. It is guaranteed that each of these
+ * descriptors is valid, at least when this function returns.
+ * Please note that technically the array may be larger than the number
+ * of valid pointers stored in it. The memory overhead is minimal, so
+ * we do not bother to re-allocate an array of the exact size. Logically,
+ * the array still contains the exactly correct number of descriptors.
+ */
+int *create_tcp_socket(void)
+{
+ struct addrinfo hints, *res, *r;
+ int error, maxs, *s, *socks, on = 1;
+
+ if(!strcmp(TCPLstnPort, "0"))
+ TCPLstnPort = "514";
+ /* use default - we can not do service db update, because there is
+ * no IANA-assignment for syslog/tcp. In the long term, we might
+ * re-use RFC 3195 port of 601, but that would probably break to
+ * many existing configurations.
+ * rgerhards, 2007-06-28
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+
+ error = getaddrinfo(NULL, TCPLstnPort, &hints, &res);
+ if(error) {
+ logerror((char*) gai_strerror(error));
+ return NULL;
+ }
+
+ /* Count max number of sockets we may open */
+ for (maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++)
+ /* EMPTY */;
+ socks = malloc((maxs+1) * sizeof(int));
+ if (socks == NULL) {
+ logerror("couldn't allocate memory for TCP listen sockets, suspending TCP message reception.");
+ freeaddrinfo(res);
+ return NULL;
+ }
+
+ *socks = 0; /* num of sockets counter at start of array */
+ s = socks + 1;
+ for (r = res; r != NULL ; r = r->ai_next) {
+ *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
+ if (*s < 0) {
+ if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT))
+ logerror("create_udp_socket(), socket");
+ /* it is debatable if PF_INET with EAFNOSUPPORT should
+ * also be ignored...
+ */
+ continue;
+ }
+
+#ifdef IPV6_V6ONLY
+ if (r->ai_family == AF_INET6) {
+ int iOn = 1;
+ if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&iOn, sizeof (iOn)) < 0) {
+ logerror("TCP setsockopt");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+ }
+#endif
+ if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &on, sizeof(on)) < 0 ) {
+ logerror("TCP setsockopt(REUSEADDR)");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+
+ /* We need to enable BSD compatibility. Otherwise an attacker
+ * could flood our log files by sending us tons of ICMP errors.
+ */
+#ifndef BSD
+ if (should_use_so_bsdcompat()) {
+ if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT,
+ (char *) &on, sizeof(on)) < 0) {
+ logerror("TCP setsockopt(BSDCOMPAT)");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+ }
+#endif
+
+ if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0)
+#ifndef IPV6_V6ONLY
+ && (errno != EADDRINUSE)
+#endif
+ ) {
+ logerror("TCP bind");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+
+ if( listen(*s,iTCPSessMax / 10 + 5) < 0) {
+ /* If the listen fails, it most probably fails because we ask
+ * for a too-large backlog. So in this case we first set back
+ * to a fixed, reasonable, limit that should work. Only if
+ * that fails, too, we give up.
+ */
+ logerrorInt("listen with a backlog of %d failed - retrying with default of 32.",
+ iTCPSessMax / 10 + 5);
+ if(listen(*s, 32) < 0) {
+ logerror("TCP listen, suspending tcp inet");
+ close(*s);
+ *s = -1;
+ continue;
+ }
+ }
+
+ (*socks)++;
+ s++;
+ }
+
+ if(res != NULL)
+ freeaddrinfo(res);
+
+ if(Debug && *socks != maxs)
+ dbgprintf("We could initialize %d TCP listen sockets out of %d we received "
+ "- this may or may not be an error indication.\n", *socks, maxs);
+
+ if(*socks == 0) {
+ logerror("No TCP listen socket could successfully be initialized, "
+ "message reception via TCP disabled.\n");
+ free(socks);
+ return(NULL);
+ }
+
+ /* OK, we had success. Now it is also time to
+ * initialize our connections
+ */
+ if(TCPSessInit() != 0) {
+ /* OK, we are in some trouble - we could not initialize the
+ * session table, so we can not continue. We need to free all
+ * we have assigned so far, because we can not really use it...
+ */
+ logerror("Could not initialize TCP session table, suspending TCP message reception.");
+ freeAllSockets(&socks); /* prevent a socket leak */
+ return(NULL);
+ }
+
+ return(socks);
+}
+
+
+/* Accept new TCP connection; make entry in session table. If there
+ * is no more space left in the connection table, the new TCP
+ * connection is immediately dropped.
+ */
+void TCPSessAccept(int fd)
+{
+ int newConn;
+ int iSess;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(struct sockaddr_storage);
+ size_t lenHostName;
+ uchar fromHost[NI_MAXHOST];
+ uchar fromHostFQDN[NI_MAXHOST];
+ char *pBuf;
+
+ newConn = accept(fd, (struct sockaddr*) &addr, &addrlen);
+ if (newConn < 0) {
+ logerror("tcp accept, ignoring error and connection request");
+ return;
+ }
+
+ /* Add to session list */
+ iSess = TCPSessFindFreeSpot();
+ if(iSess == -1) {
+ errno = 0;
+ logerror("too many tcp sessions - dropping incoming request");
+ close(newConn);
+ return;
+ }
+
+ /* OK, we have a "good" index... */
+ /* get the host name */
+ if(cvthname(&addr, fromHost, fromHostFQDN) == 0) {
+ /* we seem to have something malicous - at least we
+ * are now told to discard the connection request.
+ * Error message has been generated by cvthname.
+ */
+ close (newConn);
+ return;
+ }
+
+ /* Here we check if a host is permitted to send us
+ * syslog messages. If it isn't, we do not further
+ * process the message but log a warning (if we are
+ * configured to do this).
+ * rgerhards, 2005-09-26
+ */
+ if(!isAllowedSender(pAllowedSenders_TCP, (struct sockaddr *)&addr, (char*)fromHostFQDN)) {
+ if(option_DisallowWarning) {
+ errno = 0;
+ logerrorSz("TCP message from disallowed sender %s discarded",
+ (char*)fromHost);
+ }
+ close(newConn);
+ return;
+ }
+
+ /* OK, we have an allowed sender, so let's continue */
+ lenHostName = strlen((char*)fromHost) + 1; /* for \0 byte */
+ if((pBuf = (char*) malloc(sizeof(char) * lenHostName)) == NULL) {
+ glblHadMemShortage = 1;
+ pTCPSessions[iSess].fromHost = "NO-MEMORY-FOR-HOSTNAME";
+ } else {
+ memcpy(pBuf, fromHost, lenHostName);
+ pTCPSessions[iSess].fromHost = pBuf;
+ }
+
+ pTCPSessions[iSess].sock = newConn;
+ pTCPSessions[iSess].iMsg = 0; /* init msg buffer! */
+}
+
+
+/* This should be called before a normal (non forced) close
+ * of a TCP session. This function checks if there is any unprocessed
+ * message left in the TCP stream. Such a message is probably a
+ * fragement. If evrything goes well, we must be right at the
+ * beginnig of a new frame without any data received from it. If
+ * not, there is some kind of a framing error. I think I remember that
+ * some legacy syslog/TCP implementations have non-LF terminated
+ * messages at the end of the stream. For now, we allow this behaviour.
+ * Later, it should probably become a configuration option.
+ * rgerhards, 2006-12-07
+ */
+void TCPSessPrepareClose(int iTCPSess)
+{
+ if(iTCPSess < 0 || iTCPSess > iTCPSessMax) {
+ errno = 0;
+ logerror("internal error, trying to close an invalid TCP session!");
+ return;
+ }
+
+ if(pTCPSessions[iTCPSess].bAtStrtOfFram == 1) {
+ /* this is how it should be. There is no unprocessed
+ * data left and such we have nothing to do. For simplicity
+ * reasons, we immediately return in that case.
+ */
+ return;
+ }
+
+ /* we have some data left! */
+ if(pTCPSessions[iTCPSess].eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ /* In this case, we have an invalid frame count and thus
+ * generate an error message and discard the frame.
+ */
+ logerrorInt("Incomplete frame at end of stream in session %d - "
+ "ignoring extra data (a message may be lost).\n",
+ pTCPSessions[iTCPSess].sock);
+ /* nothing more to do */
+ } else { /* here, we have traditional framing. Missing LF at the end
+ * of message may occur. As such, we process the message in
+ * this case.
+ */
+ dbgprintf("Extra data at end of stream in legacy syslog/tcp message - processing\n");
+ printchopped(pTCPSessions[iTCPSess].fromHost, pTCPSessions[iTCPSess].msg,
+ pTCPSessions[iTCPSess].iMsg, pTCPSessions[iTCPSess].sock, 1);
+ pTCPSessions[iTCPSess].bAtStrtOfFram = 1;
+ }
+}
+
+
+/* Closes a TCP session and marks its slot in the session
+ * table as unused. No attention is paid to the return code
+ * of close, so potential-double closes are not detected.
+ */
+void TCPSessClose(int iSess)
+{
+ if(iSess < 0 || iSess > iTCPSessMax) {
+ errno = 0;
+ logerror("internal error, trying to close an invalid TCP session!");
+ return;
+ }
+
+ close(pTCPSessions[iSess].sock);
+ pTCPSessions[iSess].sock = -1;
+ free(pTCPSessions[iSess].fromHost);
+ pTCPSessions[iSess].fromHost = NULL; /* not really needed, but... */
+}
+
+
+/* Processes the data received via a TCP session. If there
+ * is no other way to handle it, data is discarded.
+ * Input parameter data is the data received, iLen is its
+ * len as returned from recv(). iLen must be 1 or more (that
+ * is errors must be handled by caller!). iTCPSess must be
+ * the index of the TCP session that received the data.
+ * rgerhards 2005-07-04
+ * Changed this functions interface. We now return a status of
+ * what shall happen with the session. This is information for
+ * the caller. If 1 is returned, the session should remain open
+ * and additional data be accepted. If we return 0, the TCP
+ * session is to be closed by the caller. This functionality is
+ * needed in order to support framing errors, from which there
+ * is no recovery possible other than session termination and
+ * re-establishment. The need for this functionality thus is
+ * primarily rooted in support for -transport-tls I-D framing.
+ * rgerhards, 2006-12-07
+ */
+int TCPSessDataRcvd(int iTCPSess, char *pData, int iLen)
+{
+ register int iMsg;
+ char *pMsg;
+ char *pEnd;
+ assert(pData != NULL);
+ assert(iLen > 0);
+ assert(iTCPSess >= 0);
+ assert(iTCPSess < iTCPSessMax);
+ assert(pTCPSessions[iTCPSess].sock != -1);
+
+ /* We now copy the message to the session buffer. As
+ * it looks, we need to do this in any case because
+ * we might run into multiple messages inside a single
+ * buffer. Of course, we could think about optimizations,
+ * but as this code is to be replaced by liblogging, it
+ * probably doesn't make so much sense...
+ * rgerhards 2005-07-04
+ *
+ * Algo:
+ * - copy message to buffer until the first LF is found
+ * - printline() the buffer
+ * - continue with copying
+ */
+ iMsg = pTCPSessions[iTCPSess].iMsg; /* copy for speed */
+ pMsg = pTCPSessions[iTCPSess].msg; /* just a shortcut */
+ pEnd = pData + iLen; /* this is one off, which is intensional */
+
+ while(pData < pEnd) {
+ /* Check if we are at a new frame */
+ if(pTCPSessions[iTCPSess].bAtStrtOfFram) {
+ /* we need to look at the message and detect
+ * the framing mode used
+ *//*
+ * Contrary to -transport-tls, we accept leading zeros in the message
+ * length. We do this in the spirit of "Be liberal in what you accept,
+ * and conservative in what you send". We expect that including leading
+ * zeros could be a common coding error.
+ * rgerhards, 2006-12-07
+ * The chairs of the IETF syslog-sec WG have announced that it is
+ * consensus to do the octet count on the SYSLOG-MSG part only. I am
+ * now changing the code to reflect this. Hopefully, it will not change
+ * once again (there can no compatibility layer programmed for this).
+ * To be on the save side, I just comment the code out. I mark these
+ * comments with "IETF20061218".
+ * rgerhards, 2006-12-19
+ */
+ if(isdigit((int) *pData)) {
+ int iCnt; /* the frame count specified */
+ pTCPSessions[iTCPSess].eFraming = TCP_FRAMING_OCTET_COUNTING;
+ /* in this mode, we have OCTET-COUNT SP MSG - so we now need
+ * to extract the OCTET-COUNT and the SP and then extract
+ * the msg.
+ */
+ iCnt = 0;
+ /* IETF20061218 int iNbrOctets = 0; / * number of octets already consumed */
+ while(isdigit((int) *pData)) {
+ iCnt = iCnt * 10 + *pData - '0';
+ /* IETF20061218 ++iNbrOctets; */
+ ++pData;
+ }
+ dbgprintf("TCP Message with octet-counter, size %d.\n", iCnt);
+ if(*pData == ' ') {
+ ++pData; /* skip over SP */
+ /* IETF20061218 ++iNbrOctets; */
+ } else {
+ /* TODO: handle "invalid frame" case */
+ logerrorInt("Framing Error in received TCP message: "
+ "delimiter is not SP but has ASCII value %d.\n",
+ *pData);
+ return(0); /* unconditional error exit */
+ }
+ /* IETF20061218 pTCPSessions[iTCPSess].iOctetsRemain = iCnt - iNbrOctets; */
+ pTCPSessions[iTCPSess].iOctetsRemain = iCnt;
+ if(pTCPSessions[iTCPSess].iOctetsRemain < 1) {
+ /* TODO: handle the case where the octet count is 0 or negative! */
+ dbgprintf("Framing Error: invalid octet count\n");
+ logerrorInt("Framing Error in received TCP message: "
+ "invalid octet count %d.\n",
+ pTCPSessions[iTCPSess].iOctetsRemain);
+ return(0); /* unconditional error exit */
+ }
+ } else {
+ pTCPSessions[iTCPSess].eFraming = TCP_FRAMING_OCTET_STUFFING;
+ /* No need to do anything else here in this case */
+ }
+ pTCPSessions[iTCPSess].bAtStrtOfFram = 0; /* done frame header */
+ }
+
+ /* now copy message until end of record */
+
+ if(iMsg >= MAXLINE) {
+ /* emergency, we now need to flush, no matter if
+ * we are at end of message or not...
+ */
+ printchopped(pTCPSessions[iTCPSess].fromHost, pMsg, iMsg,
+ pTCPSessions[iTCPSess].sock, 1);
+ iMsg = 0;
+ /* we might think if it is better to ignore the rest of the
+ * message than to treat it as a new one. Maybe this is a good
+ * candidate for a configuration parameter...
+ * rgerhards, 2006-12-04
+ */
+ }
+
+ if(*pData == '\n' &&
+ pTCPSessions[iTCPSess].eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delemiter? */
+ printchopped(pTCPSessions[iTCPSess].fromHost, pMsg, iMsg,
+ pTCPSessions[iTCPSess].sock, 1);
+ iMsg = 0;
+ pTCPSessions[iTCPSess].bAtStrtOfFram = 1;
+ ++pData;
+ } else {
+ /* IMPORTANT: here we copy the actual frame content to the message! */
+ *(pMsg + iMsg++) = *pData++;
+ }
+
+ if(pTCPSessions[iTCPSess].eFraming == TCP_FRAMING_OCTET_COUNTING) {
+ /* do we need to find end-of-frame via octet counting? */
+ pTCPSessions[iTCPSess].iOctetsRemain--;
+ if(pTCPSessions[iTCPSess].iOctetsRemain < 1) {
+ /* we have end of frame! */
+ printchopped(pTCPSessions[iTCPSess].fromHost, pMsg, iMsg,
+ pTCPSessions[iTCPSess].sock, 1);
+ iMsg = 0;
+ pTCPSessions[iTCPSess].bAtStrtOfFram = 1;
+ }
+ }
+ }
+
+ pTCPSessions[iTCPSess].iMsg = iMsg; /* persist value */
+
+ return(1); /* successful return */
+}
+
+
+#endif
+/********************************************************************
+ * ### END OF SYSLOG/TCP CODE ###
+ ********************************************************************/
+
+
+/*
+ * vi:set ai:
+ */
diff --git a/tcpsyslog.h b/tcpsyslog.h
new file mode 100644
index 0000000..1cead1a
--- /dev/null
+++ b/tcpsyslog.h
@@ -0,0 +1,56 @@
+/* tcpsyslog.h
+ * These are the definitions for TCP-based syslog.
+ *
+ * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c)
+ *
+ * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#ifndef TCPSYSLOG_H_INCLUDED
+#define TCPSYSLOG_H_INCLUDED 1
+
+struct TCPSession {
+ int sock;
+ int iMsg; /* index of next char to store in msg */
+ int bAtStrtOfFram; /* are we at the very beginning of a new frame? */
+ int iOctetsRemain; /* Number of Octets remaining in message */
+ TCPFRAMINGMODE eFraming;
+ char msg[MAXLINE+1];
+ char *fromHost;
+};
+
+/* static data */
+extern int *sockTCPLstn;
+extern char *TCPLstnPort;
+extern int bEnableTCP;
+extern struct TCPSession *pTCPSessions;
+
+/* prototypes */
+void deinit_tcp_listener(void);
+int *create_tcp_socket(void);
+int TCPSessGetNxtSess(int iCurr);
+void TCPSessAccept(int fd);
+void TCPSessPrepareClose(int iTCPSess);
+void TCPSessClose(int iSess);
+int TCPSessDataRcvd(int iTCPSess, char *pData, int iLen);
+void configureTCPListen(char *cOptarg);
+
+#endif /* #ifndef TCPSYSLOG_H_INCLUDED */
+/*
+ * vi:set ai:
+ */
diff --git a/template.c b/template.c
new file mode 100644
index 0000000..6f2c102
--- /dev/null
+++ b/template.c
@@ -0,0 +1,987 @@
+/* This is the template processing code of rsyslog.
+ * Please see syslogd.c for license information.
+ * This code is placed under the GPL.
+ * begun 2004-11-17 rgerhards
+ */
+#include "config.h"
+
+#ifdef __FreeBSD__
+#define BSD
+#endif
+
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "stringbuf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "msg.h"
+#include "syslogd.h"
+
+static struct template *tplRoot = NULL; /* the root of the template list */
+static struct template *tplLast = NULL; /* points to the last element of the template list */
+static struct template *tplLastStatic = NULL; /* last static element of the template list */
+
+/* This functions converts a template into a string. It should
+ * actually be in template.c, but this requires larger re-structuring
+ * of the code (because all the property-access functions are static
+ * to this module). I have placed it next to the iov*() functions, as
+ * it is somewhat similiar in what it does.
+ *
+ * The function takes a pointer to a template and a pointer to a msg object.
+ * It the creates a string based on the template definition. A pointer
+ * to that string is returned to the caller. The caller MUST FREE that
+ * pointer when it is no longer needed. If the function fails, NULL
+ * is returned.
+ * If memory allocation fails in this function, we silently return
+ * NULL. The reason is that we can not do anything against it. And
+ * if we raise an alert, the memory situation might become even
+ * worse. So we prefer to let the caller deal with it.
+ * rgerhards, 2007-07-03
+ */
+uchar *tplToString(struct template *pTpl, msg_t *pMsg)
+{
+ struct templateEntry *pTpe;
+ rsCStrObj *pCStr;
+ unsigned short bMustBeFreed;
+ char *pVal;
+ size_t iLenVal;
+ rsRetVal iRet;
+
+ assert(pTpl != NULL);
+ assert(pMsg != NULL);
+
+ /* loop through the template. We obtain one value
+ * and copy it over to our dynamic string buffer. Then, we
+ * free the obtained value (if requested). We continue this
+ * loop until we got hold of all values.
+ */
+ if((pCStr = rsCStrConstruct()) == NULL) {
+ dbgprintf("memory shortage, tplToString failed\n");
+ return NULL;
+ }
+
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ if(pTpe->eEntryType == CONSTANT) {
+ if((iRet = rsCStrAppendStrWithLen(pCStr,
+ (uchar *) pTpe->data.constant.pConstant,
+ pTpe->data.constant.iLenConstant)
+ ) != RS_RET_OK) {
+ dbgprintf("error %d during tplToString()\n", iRet);
+ /* it does not make sense to continue now */
+ rsCStrDestruct(pCStr);
+ return NULL;
+ }
+ } else if(pTpe->eEntryType == FIELD) {
+ pVal = (char*) MsgGetProp(pMsg, pTpe, NULL, &bMustBeFreed);
+ iLenVal = strlen(pVal);
+ /* we now need to check if we should use SQL option. In this case,
+ * we must go over the generated string and escape '\'' characters.
+ * rgerhards, 2005-09-22: the option values below look somewhat misplaced,
+ * but they are handled in this way because of legacy (don't break any
+ * existing thing).
+ */
+ if(pTpl->optFormatForSQL == 1)
+ doSQLEscape(&pVal, &iLenVal, &bMustBeFreed, 1);
+ else if(pTpl->optFormatForSQL == 2)
+ doSQLEscape(&pVal, &iLenVal, &bMustBeFreed, 0);
+ /* value extracted, so lets copy */
+ if((iRet = rsCStrAppendStrWithLen(pCStr, (uchar*) pVal, iLenVal)) != RS_RET_OK) {
+ dbgprintf("error %d during tplToString()\n", iRet);
+ /* it does not make sense to continue now */
+ rsCStrDestruct(pCStr);
+ if(bMustBeFreed)
+ free(pVal);
+ return NULL;
+ }
+ if(bMustBeFreed)
+ free(pVal);
+ }
+ pTpe = pTpe->pNext;
+ }
+
+ /* we are done with the template, now let's convert the result into a
+ * "real" (usable) string and discard the helper structures.
+ */
+ rsCStrFinish(pCStr);
+ return rsCStrConvSzStrAndDestruct(pCStr);
+}
+
+/* Helper to doSQLEscape. This is called if doSQLEscape
+ * runs out of memory allocating the escaped string.
+ * Then we are in trouble. We can
+ * NOT simply return the unmodified string because this
+ * may cause SQL injection. But we also can not simply
+ * abort the run, this would be a DoS. I think an appropriate
+ * measure is to remove the dangerous \' characters. We
+ * replace them by \", which will break the message and
+ * signatures eventually present - but this is the
+ * best thing we can do now (or does anybody
+ * have a better idea?). rgerhards 2004-11-23
+ * added support for "escapeMode" (so doSQLEscape for details).
+ * if mode = 1, then backslashes are changed to slashes.
+ * rgerhards 2005-09-22
+ */
+static void doSQLEmergencyEscape(register char *p, int escapeMode)
+{
+ while(*p) {
+ if(*p == '\'')
+ *p = '"';
+ else if((escapeMode == 1) && (*p == '\\'))
+ *p = '/';
+ ++p;
+ }
+}
+
+
+/* SQL-Escape a string. Single quotes are found and
+ * replaced by two of them. A new buffer is allocated
+ * for the provided string and the provided buffer is
+ * freed. The length is updated. Parameter pbMustBeFreed
+ * is set to 1 if a new buffer is allocated. Otherwise,
+ * it is left untouched.
+ * --
+ * We just discovered a security issue. MySQL is so
+ * "smart" to not only support the standard SQL mechanism
+ * for escaping quotes, but to also provide its own (using
+ * c-type syntax with backslashes). As such, it is actually
+ * possible to do sql injection via rsyslogd. The cure is now
+ * to escape backslashes, too. As we have found on the web, some
+ * other databases seem to be similar "smart" (why do we have standards
+ * at all if they are violated without any need???). Even better, MySQL's
+ * smartness depends on config settings. So we add a new option to this
+ * function that allows the caller to select if they want to standard or
+ * "smart" encoding ;)
+ * new parameter escapeMode is 0 - standard sql, 1 - "smart" engines
+ * 2005-09-22 rgerhards
+ */
+void doSQLEscape(char **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode)
+{
+ char *p;
+ int iLen;
+ rsCStrObj *pStrB;
+ uchar *pszGenerated;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pLen != NULL);
+ assert(pbMustBeFreed != NULL);
+
+ /* first check if we need to do anything at all... */
+ if(escapeMode == 0)
+ for(p = *pp ; *p && *p != '\'' ; ++p)
+ ;
+ else
+ for(p = *pp ; *p && *p != '\'' && *p != '\\' ; ++p)
+ ;
+ /* when we get out of the loop, we are either at the
+ * string terminator or the first \'. */
+ if(*p == '\0')
+ return; /* nothing to do in this case! */
+
+ p = *pp;
+ iLen = *pLen;
+ if((pStrB = rsCStrConstruct()) == NULL) {
+ /* oops - no mem ... Do emergency... */
+ doSQLEmergencyEscape(p, escapeMode);
+ return;
+ }
+
+ while(*p) {
+ if(*p == '\'') {
+ if(rsCStrAppendChar(pStrB, (escapeMode == 0) ? '\'' : '\\') != RS_RET_OK) {
+ doSQLEmergencyEscape(*pp, escapeMode);
+ rsCStrFinish(pStrB);
+ if((pszGenerated = rsCStrConvSzStrAndDestruct(pStrB)) != NULL)
+ free(pszGenerated);
+ return;
+ }
+ iLen++; /* reflect the extra character */
+ } else if((escapeMode == 1) && (*p == '\\')) {
+ if(rsCStrAppendChar(pStrB, '\\') != RS_RET_OK) {
+ doSQLEmergencyEscape(*pp, escapeMode);
+ rsCStrFinish(pStrB);
+ if((pszGenerated = rsCStrConvSzStrAndDestruct(pStrB)) != NULL)
+ free(pszGenerated);
+ return;
+ }
+ iLen++; /* reflect the extra character */
+ }
+ if(rsCStrAppendChar(pStrB, *p) != RS_RET_OK) {
+ doSQLEmergencyEscape(*pp, escapeMode);
+ rsCStrFinish(pStrB);
+ if((pszGenerated = rsCStrConvSzStrAndDestruct(pStrB)) != NULL)
+ free(pszGenerated);
+ return;
+ }
+ ++p;
+ }
+ rsCStrFinish(pStrB);
+ if((pszGenerated = rsCStrConvSzStrAndDestruct(pStrB)) == NULL) {
+ doSQLEmergencyEscape(*pp, escapeMode);
+ return;
+ }
+
+ if(*pbMustBeFreed)
+ free(*pp); /* discard previous value */
+
+ *pp = (char*) pszGenerated;
+ *pLen = iLen;
+ *pbMustBeFreed = 1;
+}
+
+/* Constructs a template entry object. Returns pointer to it
+ * or NULL (if it fails). Pointer to associated template list entry
+ * must be provided.
+ */
+struct templateEntry* tpeConstruct(struct template *pTpl)
+{
+ struct templateEntry *pTpe;
+
+ assert(pTpl != NULL);
+
+ if((pTpe = calloc(1, sizeof(struct templateEntry))) == NULL)
+ return NULL;
+
+ /* basic initialization is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(pTpl->pEntryLast == NULL){
+ /* we are the first element! */
+ pTpl->pEntryRoot = pTpl->pEntryLast = pTpe;
+ } else {
+ pTpl->pEntryLast->pNext = pTpe;
+ pTpl->pEntryLast = pTpe;
+ }
+ pTpl->tpenElements++;
+
+ return(pTpe);
+}
+
+
+/* Constructs a template list object. Returns pointer to it
+ * or NULL (if it fails).
+ */
+struct template* tplConstruct(void)
+{
+ struct template *pTpl;
+ if((pTpl = calloc(1, sizeof(struct template))) == NULL)
+ return NULL;
+
+ /* basic initialisation is done via calloc() - need to
+ * initialize only values != 0. */
+
+ if(tplLast == NULL) {
+ /* we are the first element! */
+ tplRoot = tplLast = pTpl;
+ } else {
+ tplLast->pNext = pTpl;
+ tplLast = pTpl;
+ }
+
+ return(pTpl);
+}
+
+
+/* helper to tplAddLine. Parses a constant and generates
+ * the necessary structure.
+ * returns: 0 - ok, 1 - failure
+ */
+static int do_Constant(unsigned char **pp, struct template *pTpl)
+{
+ register unsigned char *p;
+ rsCStrObj *pStrB;
+ struct templateEntry *pTpe;
+ int i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpl != NULL);
+
+ p = *pp;
+
+ if((pStrB = rsCStrConstruct()) == NULL)
+ return 1;
+ rsCStrSetAllocIncrement(pStrB, 32);
+ /* process the message and expand escapes
+ * (additional escapes can be added here if needed)
+ */
+ while(*p && *p != '%' && *p != '\"') {
+ if(*p == '\\') {
+ switch(*++p) {
+ case '\0':
+ /* the best we can do - it's invalid anyhow... */
+ rsCStrAppendChar(pStrB, *p);
+ break;
+ case 'n':
+ rsCStrAppendChar(pStrB, '\n');
+ ++p;
+ break;
+ case 'r':
+ rsCStrAppendChar(pStrB, '\r');
+ ++p;
+ break;
+ case '\\':
+ rsCStrAppendChar(pStrB, '\\');
+ ++p;
+ break;
+ case '%':
+ rsCStrAppendChar(pStrB, '%');
+ ++p;
+ break;
+ case '0': /* numerical escape sequence */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i = 0;
+ while(*p && isdigit((int)*p)) {
+ i = i * 10 + *p++ - '0';
+ }
+ rsCStrAppendChar(pStrB, i);
+ break;
+ default:
+ rsCStrAppendChar(pStrB, *p++);
+ break;
+ }
+ }
+ else
+ rsCStrAppendChar(pStrB, *p++);
+ }
+
+ if((pTpe = tpeConstruct(pTpl)) == NULL) {
+ /* OK, we are out of luck. Let's invalidate the
+ * entry and that's it.
+ * TODO: add panic message once we have a mechanism for this
+ */
+ pTpe->eEntryType = UNDEFINED;
+ return 1;
+ }
+ pTpe->eEntryType = CONSTANT;
+ rsCStrFinish(pStrB);
+ /* We obtain the length from the counted string object
+ * (before we delete it). Later we might take additional
+ * benefit from the counted string object.
+ * 2005-09-09 rgerhards
+ */
+ pTpe->data.constant.iLenConstant = rsCStrLen(pStrB);
+ pTpe->data.constant.pConstant = (char*) rsCStrConvSzStrAndDestruct(pStrB);
+
+ *pp = p;
+
+ return 0;
+}
+
+
+/* Helper to do_Parameter(). This parses the formatting options
+ * specified in a template variable. It returns the passed-in pointer
+ * updated to the next processed character.
+ */
+static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
+{
+ register unsigned char *p;
+ unsigned char Buf[64];
+ size_t i;
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpe != NULL);
+
+ p = *pp;
+
+ while(*p && *p != '%') {
+ /* outer loop - until end of options */
+ i = 0;
+ while((i < sizeof(Buf) / sizeof(char)) &&
+ *p && *p != '%' && *p != ',') {
+ /* inner loop - until end of ONE option */
+ Buf[i++] = tolower((int)*p);
+ ++p;
+ }
+ Buf[i] = '\0'; /* terminate */
+ /* check if we need to skip oversize option */
+ while(*p && *p != '%' && *p != ',')
+ ++p; /* just skip */
+ /* OK, we got the option, so now lets look what
+ * it tells us...
+ */
+ if(!strcmp((char*)Buf, "date-mysql")) {
+ pTpe->data.field.eDateFormat = tplFmtMySQLDate;
+ } else if(!strcmp((char*)Buf, "date-rfc3164")) {
+ pTpe->data.field.eDateFormat = tplFmtRFC3164Date;
+ } else if(!strcmp((char*)Buf, "date-rfc3339")) {
+ pTpe->data.field.eDateFormat = tplFmtRFC3339Date;
+ } else if(!strcmp((char*)Buf, "lowercase")) {
+ pTpe->data.field.eCaseConv = tplCaseConvLower;
+ } else if(!strcmp((char*)Buf, "uppercase")) {
+ pTpe->data.field.eCaseConv = tplCaseConvUpper;
+ } else if(!strcmp((char*)Buf, "escape-cc")) {
+ pTpe->data.field.options.bEscapeCC = 1;
+ } else if(!strcmp((char*)Buf, "drop-cc")) {
+ pTpe->data.field.options.bDropCC = 1;
+ } else if(!strcmp((char*)Buf, "space-cc")) {
+ pTpe->data.field.options.bSpaceCC = 1;
+ } else if(!strcmp((char*)Buf, "drop-last-lf")) {
+ pTpe->data.field.options.bDropLastLF = 1;
+ } else {
+ dbgprintf("Invalid field option '%s' specified - ignored.\n", Buf);
+ }
+ }
+
+ *pp = p;
+}
+
+
+/* helper to tplAddLine. Parses a parameter and generates
+ * the necessary structure.
+ * returns: 0 - ok, 1 - failure
+ */
+static int do_Parameter(unsigned char **pp, struct template *pTpl)
+{
+ unsigned char *p;
+ rsCStrObj *pStrB;
+ struct templateEntry *pTpe;
+ int iNum; /* to compute numbers */
+
+#ifdef FEATURE_REGEXP
+ /* APR: variables for regex */
+ int longitud;
+ unsigned char *regex_char;
+ unsigned char *regex_end;
+#endif
+
+ assert(pp != NULL);
+ assert(*pp != NULL);
+ assert(pTpl != NULL);
+
+ p = (unsigned char*) *pp;
+
+ if((pStrB = rsCStrConstruct()) == NULL)
+ return 1;
+
+ if((pTpe = tpeConstruct(pTpl)) == NULL) {
+ /* TODO: add handler */
+ dbgprintf("Could not allocate memory for template parameter!\n");
+ return 1;
+ }
+ pTpe->eEntryType = FIELD;
+
+ while(*p && *p != '%' && *p != ':') {
+ rsCStrAppendChar(pStrB, *p++);
+ }
+
+ /* got the name*/
+ rsCStrFinish(pStrB);
+ pTpe->data.field.pPropRepl = (char*) rsCStrConvSzStrAndDestruct(pStrB);
+
+ /* Check frompos, if it has an R, then topos should be a regex */
+ if(*p == ':') {
+ ++p; /* eat ':' */
+#ifdef FEATURE_REGEXP
+ if (*p == 'R') {
+ /* APR: R found! regex alarm ! :) */
+ ++p; /* eat ':' */
+
+ if (*p != ':') {
+ /* There is something more than an R , this is invalid ! */
+ /* Complain on extra characters */
+ logerrorSz
+ ("error: invalid character in frompos after \"R\", property: '%%%s'",
+ (char*) *pp);
+ } else {
+ pTpe->data.field.has_regex = 1;
+ }
+ } else {
+ /* now we fall through the "regular" FromPos code */
+#endif /* #ifdef FEATURE_REGEXP */
+ if(*p == 'F') {
+ /* we have a field counter, so indicate it in the template */
+ ++p; /* eat 'F' */
+ if (*p == ':') {
+ /* no delimiter specified, so use the default (HT) */
+ pTpe->data.field.has_fields = 1;
+ pTpe->data.field.field_delim = 9;
+ } else if (*p == ',') {
+ ++p; /* eat ',' */
+ /* configured delimiter follows, so we need to obtain
+ * it. Important: the following number must be the
+ * **DECIMAL** ASCII value of the delimiter character.
+ */
+ pTpe->data.field.has_fields = 1;
+ if(!isdigit((int)*p)) {
+ /* complain and use default */
+ logerrorSz
+ ("error: invalid character in frompos after \"F,\", property: '%%%s' - using 9 (HT) as field delimiter",
+ (char*) *pp);
+ pTpe->data.field.field_delim = 9;
+ } else {
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ if(iNum < 0 || iNum > 255) {
+ logerrorInt
+ ("error: non-USASCII delimiter character value in template - using 9 (HT) as substitute", iNum);
+ pTpe->data.field.field_delim = 9;
+ } else {
+ pTpe->data.field.field_delim = iNum;
+ }
+ }
+ } else {
+ /* invalid character after F, so we need to reject
+ * this.
+ */
+ logerrorSz
+ ("error: invalid character in frompos after \"F\", property: '%%%s'",
+ (char*) *pp);
+ }
+ } else {
+ /* we now have a simple offset in frompos (the previously "normal" case) */
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iFromPos = iNum;
+ /* skip to next known good */
+ while(*p && *p != '%' && *p != ':') {
+ /* TODO: complain on extra characters */
+ dbgprintf("error: extra character in frompos: '%s'\n", p);
+ ++p;
+ }
+ }
+#ifdef FEATURE_REGEXP
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+ /* check topos (holds an regex if FromPos is "R"*/
+ if(*p == ':') {
+ ++p; /* eat ':' */
+
+#ifdef FEATURE_REGEXP
+ if (pTpe->data.field.has_regex) {
+
+ dbgprintf("debug: has regex \n");
+
+ /* APR 2005-09 I need the string that represent the regex */
+ /* The regex end is: "--end" */
+ /* TODO : this is hardcoded and cant be escaped, please change */
+ regex_end = (unsigned char*) strstr((char*)p, "--end");
+ if (regex_end == NULL) {
+ dbgprintf("error: can not find regex end in: '%s'\n", p);
+ pTpe->data.field.has_regex = 0;
+ } else {
+ /* We get here ONLY if the regex end was found */
+ longitud = regex_end - p;
+ /* Malloc for the regex string */
+ regex_char = (unsigned char *) malloc(longitud + 1);
+ if (regex_char == NULL) {
+ dbgprintf
+ ("Could not allocate memory for template parameter!\n");
+ pTpe->data.field.has_regex = 0;
+ return 1;
+ /* TODO: RGer: check if we can recover better... (probably not) */
+ }
+
+ /* Get the regex string for compiling later */
+ memcpy(regex_char, p, longitud);
+ regex_char[longitud] = '\0';
+
+ dbgprintf("debug: regex detected: '%s'\n", regex_char);
+
+ /* Now i compile the regex */
+ /* Remember that the re is an attribute of the Template entry */
+ if(regcomp(&(pTpe->data.field.re), (char*) regex_char, 0) != 0) {
+ dbgprintf("error: can not compile regex: '%s'\n", regex_char);
+ pTpe->data.field.has_regex = 2;
+ }
+
+ /* Finally we move the pointer to the end of the regex
+ * so it aint parsed twice or something weird */
+ p = regex_end + 5/*strlen("--end")*/;
+ free(regex_char);
+ }
+ } else if(*p == '$') {
+ /* shortcut for "end of message */
+ p++; /* eat '$' */
+ /* in this case, we do a quick, somewhat dirty but totally
+ * legitimate trick: we simply use a topos that is higher than
+ * potentially ever can happen. The code below checks that no copy
+ * will occur after the end of string, so this is perfectly legal.
+ * rgerhards, 2006-10-17
+ */
+ pTpe->data.field.iToPos = 9999999;
+ } else {
+ /* fallthrough to "regular" ToPos code */
+#endif /* #ifdef FEATURE_REGEXP */
+
+ iNum = 0;
+ while(isdigit((int)*p))
+ iNum = iNum * 10 + *p++ - '0';
+ pTpe->data.field.iToPos = iNum;
+ /* skip to next known good */
+ while(*p && *p != '%' && *p != ':') {
+ /* TODO: complain on extra characters */
+ dbgprintf("error: extra character in frompos: '%s'\n", p);
+ ++p;
+ }
+#ifdef FEATURE_REGEXP
+ }
+#endif /* #ifdef FEATURE_REGEXP */
+ }
+
+ /* TODO: add more sanity checks. For now, we do the bare minimum */
+ if((pTpe->data.field.has_fields == 0) && (pTpe->data.field.iToPos < pTpe->data.field.iFromPos)) {
+ iNum = pTpe->data.field.iToPos;
+ pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
+ pTpe->data.field.iFromPos = iNum;
+ }
+
+ /* check options */
+ if(*p == ':') {
+ ++p; /* eat ':' */
+ doOptions(&p, pTpe);
+ }
+
+ if(*p) ++p; /* eat '%' */
+
+ *pp = p;
+ return 0;
+}
+
+
+/* Add a new template line
+ * returns pointer to new object if it succeeds, NULL otherwise.
+ */
+struct template *tplAddLine(char* pName, unsigned char** ppRestOfConfLine)
+{
+ struct template *pTpl;
+ unsigned char *p;
+ int bDone;
+ char optBuf[128]; /* buffer for options - should be more than enough... */
+ size_t i;
+
+ assert(pName != NULL);
+ assert(ppRestOfConfLine != NULL);
+
+ if((pTpl = tplConstruct()) == NULL)
+ return NULL;
+
+ pTpl->iLenName = strlen(pName);
+ pTpl->pszName = (char*) malloc(sizeof(char) * (pTpl->iLenName + 1));
+ if(pTpl->pszName == NULL) {
+ dbgprintf("tplAddLine could not alloc memory for template name!");
+ pTpl->iLenName = 0;
+ return NULL;
+ /* I know - we create a memory leak here - but I deem
+ * it acceptable as it is a) a very small leak b) very
+ * unlikely to happen. rgerhards 2004-11-17
+ */
+ }
+ memcpy(pTpl->pszName, pName, pTpl->iLenName + 1);
+
+ /* now actually parse the line */
+ p = *ppRestOfConfLine;
+ assert(p != NULL);
+
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ if(*p != '"') {
+ dbgprintf("Template '%s' invalid, does not start with '\"'!\n", pTpl->pszName);
+ /* we simply make the template defunct in this case by setting
+ * its name to a zero-string. We do not free it, as this would
+ * require additional code and causes only a very small memory
+ * consumption. Memory is freed, however, in normal operation
+ * and most importantly by HUPing syslogd.
+ */
+ *pTpl->pszName = '\0';
+ return NULL;
+ }
+ ++p;
+
+ /* we finally go to the actual template string - so let's have some fun... */
+ bDone = *p ? 0 : 1;
+ while(!bDone) {
+ switch(*p) {
+ case '\0':
+ bDone = 1;
+ break;
+ case '%': /* parameter */
+ ++p; /* eat '%' */
+ do_Parameter(&p, pTpl);
+ break;
+ default: /* constant */
+ do_Constant(&p, pTpl);
+ break;
+ }
+ if(*p == '"') {/* end of template string? */
+ ++p; /* eat it! */
+ bDone = 1;
+ }
+ }
+
+ /* we now have the template - let's look at the options (if any)
+ * we process options until we reach the end of the string or
+ * an error occurs - whichever is first.
+ */
+ while(*p) {
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ if(*p != ',')
+ break;
+ ++p; /* eat ',' */
+
+ while(isspace((int)*p))/* skip whitespace */
+ ++p;
+
+ /* read option word */
+ i = 0;
+ while(i < sizeof(optBuf) / sizeof(char) - 1
+ && *p && *p != '=' && *p !=',' && *p != '\n') {
+ optBuf[i++] = tolower((int)*p);
+ ++p;
+ }
+ optBuf[i] = '\0';
+
+ if(*p == '\n')
+ ++p;
+
+ /* as of now, the no form is nonsense... but I do include
+ * it anyhow... ;) rgerhards 2004-11-22
+ */
+ if(!strcmp(optBuf, "stdsql")) {
+ pTpl->optFormatForSQL = 2;
+ } else if(!strcmp(optBuf, "sql")) {
+ pTpl->optFormatForSQL = 1;
+ } else if(!strcmp(optBuf, "nosql")) {
+ pTpl->optFormatForSQL = 0;
+ } else {
+ dbgprintf("Invalid option '%s' ignored.\n", optBuf);
+ }
+ }
+
+ *ppRestOfConfLine = p;
+ return(pTpl);
+}
+
+
+/* Find a template object based on name. Search
+ * currently is case-senstive (should we change?).
+ * returns pointer to template object if found and
+ * NULL otherwise.
+ * rgerhards 2004-11-17
+ */
+struct template *tplFind(char *pName, int iLenName)
+{
+ struct template *pTpl;
+
+ assert(pName != NULL);
+
+ pTpl = tplRoot;
+ while(pTpl != NULL &&
+ !(pTpl->iLenName == iLenName &&
+ !strcmp(pTpl->pszName, pName)
+ ))
+ {
+ pTpl = pTpl->pNext;
+ }
+ return(pTpl);
+}
+
+/* Destroy the template structure. This is for de-initialization
+ * at program end. Everything is deleted.
+ * rgerhards 2005-02-22
+ * I have commented out dbgprintfs, because they are not needed for
+ * "normal" debugging. Uncomment them, if they are needed.
+ * rgerhards, 2007-07-05
+ */
+void tplDeleteAll(void)
+{
+ struct template *pTpl, *pTplDel;
+ struct templateEntry *pTpe, *pTpeDel;
+
+ pTpl = tplRoot;
+ while(pTpl != NULL) {
+ /* dbgprintf("Delete Template: Name='%s'\n ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);*/
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ pTpeDel = pTpe;
+ pTpe = pTpe->pNext;
+ /*dbgprintf("\tDelete Entry(%x): type %d, ", (unsigned) pTpeDel, pTpeDel->eEntryType);*/
+ switch(pTpeDel->eEntryType) {
+ case UNDEFINED:
+ /*dbgprintf("(UNDEFINED)");*/
+ break;
+ case CONSTANT:
+ /*dbgprintf("(CONSTANT), value: '%s'",
+ pTpeDel->data.constant.pConstant);*/
+ free(pTpeDel->data.constant.pConstant);
+ break;
+ case FIELD:
+ /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/
+ free(pTpeDel->data.field.pPropRepl);
+ break;
+ }
+ /*dbgprintf("\n");*/
+ free(pTpeDel);
+ }
+ pTplDel = pTpl;
+ pTpl = pTpl->pNext;
+ if(pTplDel->pszName != NULL)
+ free(pTplDel->pszName);
+ free(pTplDel);
+ }
+}
+
+/* Destroy all templates obtained from conf file
+ * preserving hadcoded ones. This is called from init().
+ */
+void tplDeleteNew(void)
+{
+ struct template *pTpl, *pTplDel;
+ struct templateEntry *pTpe, *pTpeDel;
+
+ if(tplRoot == NULL || tplLastStatic == NULL)
+ return;
+
+ pTpl = tplLastStatic->pNext;
+ tplLastStatic->pNext = NULL;
+ tplLast = tplLastStatic;
+ while(pTpl != NULL) {
+ /* dbgprintf("Delete Template: Name='%s'\n ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);*/
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ pTpeDel = pTpe;
+ pTpe = pTpe->pNext;
+ /*dbgprintf("\tDelete Entry(%x): type %d, ", (unsigned) pTpeDel, pTpeDel->eEntryType);*/
+ switch(pTpeDel->eEntryType) {
+ case UNDEFINED:
+ /*dbgprintf("(UNDEFINED)");*/
+ break;
+ case CONSTANT:
+ /*dbgprintf("(CONSTANT), value: '%s'",
+ pTpeDel->data.constant.pConstant);*/
+ free(pTpeDel->data.constant.pConstant);
+ break;
+ case FIELD:
+ /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/
+ free(pTpeDel->data.field.pPropRepl);
+ break;
+ }
+ /*dbgprintf("\n");*/
+ free(pTpeDel);
+ }
+ pTplDel = pTpl;
+ pTpl = pTpl->pNext;
+ if(pTplDel->pszName != NULL)
+ free(pTplDel->pszName);
+ free(pTplDel);
+ }
+}
+
+/* Store the pointer to the last hardcoded teplate */
+void tplLastStaticInit(struct template *tpl)
+{
+ tplLastStatic = tpl;
+}
+
+/* Print the template structure. This is more or less a
+ * debug or test aid, but anyhow I think it's worth it...
+ */
+void tplPrintList(void)
+{
+ struct template *pTpl;
+ struct templateEntry *pTpe;
+
+ pTpl = tplRoot;
+ while(pTpl != NULL) {
+ dbgprintf("Template: Name='%s' ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);
+ if(pTpl->optFormatForSQL == 1)
+ dbgprintf("[SQL-Format (MySQL)] ");
+ else if(pTpl->optFormatForSQL == 2)
+ dbgprintf("[SQL-Format (standard SQL)] ");
+ dbgprintf("\n");
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ dbgprintf("\tEntry(%x): type %d, ", (unsigned) pTpe, pTpe->eEntryType);
+ switch(pTpe->eEntryType) {
+ case UNDEFINED:
+ dbgprintf("(UNDEFINED)");
+ break;
+ case CONSTANT:
+ dbgprintf("(CONSTANT), value: '%s'",
+ pTpe->data.constant.pConstant);
+ break;
+ case FIELD:
+ dbgprintf("(FIELD), value: '%s' ", pTpe->data.field.pPropRepl);
+ switch(pTpe->data.field.eDateFormat) {
+ case tplFmtDefault:
+ break;
+ case tplFmtMySQLDate:
+ dbgprintf("[Format as MySQL-Date] ");
+ break;
+ case tplFmtRFC3164Date:
+ dbgprintf("[Format as RFC3164-Date] ");
+ break;
+ case tplFmtRFC3339Date:
+ dbgprintf("[Format as RFC3339-Date] ");
+ break;
+ default:
+ dbgprintf("[INVALID eDateFormat %d] ", pTpe->data.field.eDateFormat);
+ }
+ switch(pTpe->data.field.eCaseConv) {
+ case tplCaseConvNo:
+ break;
+ case tplCaseConvLower:
+ dbgprintf("[Converted to Lower Case] ");
+ break;
+ case tplCaseConvUpper:
+ dbgprintf("[Converted to Upper Case] ");
+ break;
+ }
+ if(pTpe->data.field.options.bEscapeCC) {
+ dbgprintf("[escape control-characters] ");
+ }
+ if(pTpe->data.field.options.bDropCC) {
+ dbgprintf("[drop control-characters] ");
+ }
+ if(pTpe->data.field.options.bSpaceCC) {
+ dbgprintf("[replace control-characters with space] ");
+ }
+ if(pTpe->data.field.options.bDropLastLF) {
+ dbgprintf("[drop last LF in msg] ");
+ }
+ if(pTpe->data.field.has_fields == 1) {
+ dbgprintf("[substring, field #%d only (delemiter %d)] ",
+ pTpe->data.field.iToPos, pTpe->data.field.field_delim);
+ } else if(pTpe->data.field.iFromPos != 0 ||
+ pTpe->data.field.iToPos != 0) {
+ dbgprintf("[substring, from character %d to %d] ",
+ pTpe->data.field.iFromPos,
+ pTpe->data.field.iToPos);
+ }
+ break;
+ }
+ dbgprintf("\n");
+ pTpe = pTpe->pNext;
+ }
+ pTpl = pTpl->pNext; /* done, go next */
+ }
+}
+
+int tplGetEntryCount(struct template *pTpl)
+{
+ assert(pTpl != NULL);
+ return(pTpl->tpenElements);
+}
+/*
+ * vi:set ai:
+ */
diff --git a/template.h b/template.h
new file mode 100644
index 0000000..bbd7709
--- /dev/null
+++ b/template.h
@@ -0,0 +1,92 @@
+/* This is the header for template processing code of rsyslog.
+ * Please see syslogd.c for license information.
+ * This code is placed under the GPL.
+ * begun 2004-11-17 rgerhards
+ */
+
+#ifndef TEMPLATE_H_INCLUDED
+#define TEMPLATE_H_INCLUDED 1
+
+
+#include "stringbuf.h"
+
+#ifdef FEATURE_REGEXP
+/* Include regular expressions */
+#include <regex.h>
+#endif
+
+struct template {
+ struct template *pNext;
+ char *pszName;
+ int iLenName;
+ int tpenElements; /* number of elements in templateEntry list */
+ struct templateEntry *pEntryRoot;
+ struct templateEntry *pEntryLast;
+ char optFormatForSQL; /* in text fields, 0 - do not escape,
+ * 1 - escape quotes by double quotes,
+ * 2 - escape "the MySQL way"
+ */
+ /* following are options. All are 0/1 defined (either on or off).
+ * we use chars because they are faster than bit fields and smaller
+ * than short...
+ */
+};
+
+enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 };
+enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1,
+ tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3 };
+enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 };
+
+#include "msg.h"
+
+/* a specific parse entry */
+struct templateEntry {
+ struct templateEntry *pNext;
+ enum EntryTypes eEntryType;
+ union {
+ struct {
+ char *pConstant; /* pointer to constant value */
+ int iLenConstant; /* its length */
+ } constant;
+ struct {
+ char *pPropRepl; /* pointer to property replacer string */
+ unsigned iFromPos; /* for partial strings only chars from this position ... */
+ unsigned iToPos; /* up to that one... */
+#ifdef FEATURE_REGEXP
+ regex_t re; /* APR: this is the regular expression */
+ unsigned has_regex;
+#endif
+ unsigned has_fields; /* support for field-counting: field to extract */
+ unsigned char field_delim; /* support for field-counting: field delemiter char */
+ enum tplFormatTypes eDateFormat;
+ enum tplFormatCaseConvTypes eCaseConv;
+ struct { /* bit fields! */
+ unsigned bDropCC: 1; /* drop control characters? */
+ unsigned bSpaceCC: 1; /* change control characters to spaceescape? */
+ unsigned bEscapeCC: 1; /* escape control characters? */
+ unsigned bDropLastLF: 1; /* drop last LF char in msg (PIX!) */
+ } options; /* options as bit fields */
+ } field;
+ } data;
+};
+
+struct template* tplConstruct(void);
+struct template *tplAddLine(char* pName, unsigned char** pRestOfConfLine);
+struct template *tplFind(char *pName, int iLenName);
+int tplGetEntryCount(struct template *pTpl);
+void tplDeleteAll(void);
+void tplDeleteNew(void);
+void tplPrintList(void);
+void tplLastStaticInit(struct template *tpl);
+/* note: if a compiler warning for undefined type tells you to look at this
+ * code line below, the actual cause is that you currently MUST include template.h
+ * BEFORE msg.h, even if your code file does not actually need it.
+ * rgerhards, 2007-08-06
+ */
+uchar *tplToString(struct template *pTpl, msg_t *pMsg);
+void doSQLEscape(char **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);
+
+#endif /* #ifndef TEMPLATE_H_INCLUDED */
+/*
+ * vi:set ai:
+ */