From 7834544c60a0a3f5a50c2c6e73d7d8741cbfd28d Mon Sep 17 00:00:00 2001 From: Joey Schulze Date: Mon, 2 Jun 1997 17:21:41 +0000 Subject: [PATCH] Import of bare source for 1.3 --- ANNOUNCE | 59 ++ COPYING | 339 +++++++ INSTALL | 37 + MANIFEST | 48 + Makefile | 91 ++ NEWS | 101 ++ README.1st | 65 ++ README.linux | 64 ++ Sysklogd-1.3.lsm | 23 + kernel.patch | 70 ++ klogd.8 | 271 ++++++ klogd.c | 735 +++++++++++++++ klogd.h | 17 + ksym.c | 713 ++++++++++++++ pidfile.c | 130 +++ pidfile.h | 50 + sysklogd.8 | 585 ++++++++++++ syslog-tst.conf | 0 syslog.c | 243 +++++ syslog.conf | 46 + syslog.conf.5 | 389 ++++++++ syslog_tst.c | 74 ++ syslogd.8 | 1 + syslogd.c | 2339 ++++++++++++++++++++++++++++++++++++++++++++++ version.h | 2 + 25 files changed, 6492 insertions(+) create mode 100644 ANNOUNCE create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 MANIFEST create mode 100644 Makefile create mode 100644 NEWS create mode 100644 README.1st create mode 100644 README.linux create mode 100644 Sysklogd-1.3.lsm create mode 100644 kernel.patch create mode 100644 klogd.8 create mode 100644 klogd.c create mode 100644 klogd.h create mode 100644 ksym.c create mode 100644 pidfile.c create mode 100644 pidfile.h create mode 100644 sysklogd.8 create mode 100644 syslog-tst.conf create mode 100644 syslog.c create mode 100644 syslog.conf create mode 100644 syslog.conf.5 create mode 100644 syslog_tst.c create mode 100644 syslogd.8 create mode 100644 syslogd.c create mode 100644 version.h diff --git a/ANNOUNCE b/ANNOUNCE new file mode 100644 index 0000000..e0c48fe --- /dev/null +++ b/ANNOUNCE @@ -0,0 +1,59 @@ +On behalf of Martin Schulze, the beta-testers and other members of the +Linux INTERNET community who have helped shape and debug this package +I am pleased to announce version 1.3 of the sysklogd package. + +This package implements two system log daemons. The syslogd daemon is +an enhanced version of the standard Berkeley utility program. This +daemon is responsible for providing logging of messages received from +programs and facilities on the local host as well as from remote +hosts. The klogd daemon listens to kernel message sources and is +responsible for prioritizing and processing operating system +messages. The klogd daemon can run as a client of syslogd or +optionally as a standalone program. + +This package is the culmination of about two years of experience and +bug reports on the 1.2 version from both the INTERNET and our +corporate Linux networks. The utilities in this package should provide +VERY reliable system logging. Klogd and syslogd have both been stress +tested in kernel development environments where literally hundreds of +megabytes of kernel messages have been blasted through them. If either +utility should fail I would appreciate a report and debug information +so that the bug can be reproduced and squashed. + +This package includes some major improvements. Some of them are listed +here: + + * klogd supports on-the-fly kernel address to symbol + translations. This requires that a valid kernel symbol map be + found at execution. + + * syslogd has better handling of remote logging capabilities. + + * both klogd and syslogd can be controlled through commandline + options and signals. + + * both daemons are now FSSTND conform. + + * a syslog.conf(5) manpage is now available. + + * Spaces are now accepted in the syslog configuration + file. This should be a real crowd pleaser. + + * Syslogd now uses dynamic allocation of logging output + descriptors. There is no longer a static limit on the number + of log destinations that can be defined. + + * Numerous bug fixes and code cleanups. + +The new release can be obtained from either tsx-11.mit.edu or +sunsite.unc.edu. + +Thanks again to everyone who has contributed ideas, patches and bug +reports. Linux has a superior set of logging utilities thanks to +contributions from the entire community. + + +Dr. Greg Wettstein +Oncology Research Division Computing Facility +Roger Maris Cancer Center +greg@wind.rmcc.com 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. + + + Copyright (C) 19yy + + 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. + + , 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/INSTALL b/INSTALL new file mode 100644 index 0000000..c7a0ad9 --- /dev/null +++ b/INSTALL @@ -0,0 +1,37 @@ +1.) READ the README.linux file and the accompanying man pages. It will + save you some frustration. + +2.) 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. + Compilation has been tested with versions 2.5.8, 2.6.3 and 2.7.0 of + the gcc compiler and libc versions 4.5.26 and 4.6.27. + +3.) 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. + +4.) For proper functioning both of these utilities are best run as root. + This is probably not much of a problem since they will probably be + started either by init or as part of the rc.* startup process. There + may be security concerns with running syslogd as root. Please repeat + step 1 if you are unsure of why this may be the case. + +5.) If kernel address to symbol translation is desired there is the + possibility that a new kernel will need to be compiled. The patches + to delimit kernel addresses requiring translation were added to + kernel 1.3.43. If this kernel or a newer kernel is used there is + no need to modify the kernel sources. + + If a kernel earlier than this is used the kernel sources will have to + be patched. The patch to delimit addresses for translation is included + with the sysklogd sources. The necessary modifications are quite + generic and should require little modification over a wide range of + kernel sources. diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..233c898 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,48 @@ +A virgin copy of these sources should include 12 files: + +MANIFEST: This file. + +INSTALL: Brief installation instructions. + +NEWS: Important changes. + +Makefile: A makefile to generate the binaries. + +README.linux: Documentation which may prove useful. + +klogd.c: Source code for the kernel log daemon. + +klogd.h: Global definitions required for the kernel log daemon. + +ksym.c: Source module for the kernel log daemon which implements + kernel numeric address to symbol translations. + +syslogd.c: Source code for the system log daemon. + +syslog.c: A slightly modified version of the syslog.c file found in + the standard libraries. This special version is needed + so that klogd will pass messages with kernel priority to + the syslogd facility. + +pidfile.c: Source implementing utility functions which are useful + for managing pid files. Used by both syslogd and klogd. + +pidfile.h: Include file containing global definitions for the + pid file utility functions. + +version.h: An include file for setting the version and patchlevel + for the package. + +syslog.conf: A sample configuration file. Note that this file uses + extensions to the BSD syntax. See the syslog.conf(5) + manpage for more details. + +syslog_tst.c: A simple program to test the system log utility. + +sysklogd.8: Man page documenting the general characteristics of this + package. + +klogd.8: Man page documenting the kernel log daemon. + +kernel.patch: A source code patch which modifies the linux kernel to + delimit addresses for symbolic translation by klogd. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ffe8baa --- /dev/null +++ b/Makefile @@ -0,0 +1,91 @@ +# Makefile for syslogd and klogd daemons. + +CC= gcc +#CFLAGS= -g -DSYSV -Wall +#LDFLAGS= -g +CFLAGS= -O6 -DSYSV -fomit-frame-pointer -Wall +LDFLAGS= -s -N + +# Look where your install program is +# +INSTALL = /usr/bin/install +BINDIR = /usr/sbin +MANDIR = /usr/man + +# There is one report that under an all ELF system there may be a need to +# explicilty link with libresolv.a. If linking syslogd fails you may wish +# to try uncommenting the following define. +# LIBS = /usr/lib/libresolv.a + +# Define the following to impart start-up delay in klogd. This is +# useful if klogd is started simultaneously or in close-proximity to syslogd. +# KLOGD_START_DELAY = -DKLOGD_DELAY=5 + +# The following define determines whether the package adheres to the +# file system standard. +FSSTND = -DFSSTND + +# The following define establishes ownership for the man pages. +# Avery tells me that there is a difference between Debian and +# Slackware. Rather than choose sides I am leaving it up to the user. +MAN_OWNER = root +# MAN_OWNER = man + +# The following define establishes the name of the pid file for the +# syslogd daemon. The library include file (paths.h) defines the +# name for the syslogd pid to be syslog.pid. A number of people have +# suggested that this should be syslogd.pid. You may cast your +# ballot below. +# SYSLOGD_PIDNAME = -DSYSLOGD_PIDNAME=\"syslogd.pid\" + +SYSLOGD_FLAGS= -DSYSLOG_INET -DSYSLOG_UNIXAF -DNO_SCCS ${FSSTND} \ + ${SYSLOGD_PIDNAME} +SYSLOG_FLAGS= -DALLOW_KERNEL_LOGGING +KLOGD_FLAGS = ${FSSTND} ${KLOGD_START_DELAY} + +.c.o: + ${CC} ${CFLAGS} -c $*.c + +all: syslogd klogd syslog_tst + +install: install_man install_exec + +syslogd: syslogd.o pidfile.o + ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o ${LIBS} + +klogd: klogd.o syslog.o pidfile.o ksym.o + ${CC} ${LDFLAGS} -o klogd klogd.o syslog.o pidfile.o ksym.o + +syslog_tst: syslog_tst.o + ${CC} ${LDFLAGS} -o syslog_tst syslog_tst.o + +syslogd.o: syslogd.c version.h + ${CC} ${CFLAGS} ${SYSLOGD_FLAGS} -c syslogd.c + +syslog.o: syslog.c + ${CC} ${CFLAGS} ${SYSLOG_FLAGS} -c syslog.c + +klogd.o: klogd.c klogd.h version.h + ${CC} ${CFLAGS} ${KLOGD_FLAGS} -c klogd.c + +ksym.o: ksym.c klogd.h + ${CC} ${CFLAGS} ${KLOGD_FLAGS} -c ksym.c + +syslog_tst.o: syslog_tst.c + ${CC} ${CFLAGS} -c syslog_tst.c + +clean: + rm -f *.o *.log *~ *.orig; + +clobber: clean + rm -f syslogd klogd syslog_tst TAGS; + +install_exec: syslogd klogd + ${INSTALL} -m 500 -s syslogd ${BINDIR}/syslogd; + ${INSTALL} -m 500 -s klogd ${BINDIR}/klogd; + +install_man: + ${INSTALL} -o ${MAN_OWNER} -g ${MAN_OWNER} -m 644 sysklogd.8 ${MANDIR}/man8/sysklogd.8 + ${INSTALL} -o ${MAN_OWNER} -g ${MAN_OWNER} -m 644 syslogd.8 ${MANDIR}/man8/syslogd.8 + ${INSTALL} -o ${MAN_OWNER} -g ${MAN_OWNER} -m 644 syslog.conf.5 ${MANDIR}/man5/syslog.conf.5 + ${INSTALL} -o ${MAN_OWNER} -g ${MAN_OWNER} -m 644 klogd.8 ${MANDIR}/MAN8/klogd.8 diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e4591da --- /dev/null +++ b/NEWS @@ -0,0 +1,101 @@ +Version 1.3 + +Numerous changes, performance enhancements, code cleanups and bug fixes. +Too many to individually summarize. Have a look at the top of each +source file for more information. + +** Default behavior of sysklogd is not to accept any message that +is sent via syslog/udp. To allow remote reception add -r to the +command-line arguments. + +** Spaces are now accepted in the syslog configuration file. This +should be a real crowd pleaser. + +syslogd now uses dynamic allocation of logging output descriptors. +There is no longer a static limit on the number of log destinations +that can be defined. + +klogd supports on-the-fly kernel address to symbol translations. +This requires that a valid kernel symbol map be found at execution. + +** The default level for console log messages was changed to 6. This +means that kernel messages with a priority less than or equal to 5 +(KERN_NOTICE) will be logged to the console. + + This item has been flagged because it results in a behavior + change which will be different if version 1.3 replaces an + existing 1.2 binary. Linus strongly suggested that this + behavior be changed and in the 1.3.3x kernels Linus in fact + made it impossible to set the console log level lower than + about 5. + + There were good reasons from his perspective for doing so. + The most troublesome being that user's of packaged + distributions were not able to generate register dumps with + the kernel debugging keys, most notably altgr-SCRLCK. + + If a kernels prior to 1.3.3x are being used the klogd daemon + invocation must be changed to something like: klogd -c 1 + + This will turn off logging of kernel messages to the console. + If you understand the ramifications of this the 1.3.3x kernels + can be patched to allow the suppression of console log + messages. It is important to be cognizant of the effects of + these changes. None the least of which is that Linus and Alan + will yell at you if you complain about not being able to + generate kernel debugging information.. :-) + +--------------------------------------------------------------------------- +Version 1.2 +Fixes to both klogd and syslogd so that the package will compile without +errors due to the vararg procedures. + +Modified pid files produced so that the names of the files are +klogd.pid and syslogd.pid respectively. + +Fixed bug in klogd which prevented output from being directed to a file +when the program was compiled to auto-background itself. In the +auto-backgrounding configuration the forked process was closing all its +file descriptors which was causing the errant behavior. + +Modified signal handling in klogd so that all signal are set to ignored +before establishing specific signal handlers. + +Fixed bug in syslogd which was causing a delay in opening of the /dev/log +UNIX domain socket. This should correct the race condition which was +preventing klogd from properly logging kernel messages when the two +daemons were started in rapid succession. + +Modified the closing/opening of file descriptors when syslogd was +compiled with auto-backgrounding support. Closes the potential for +a somewhat obscure bug caused by the /dev/log socket being opened on +fd 0. + +Changed the names of the man pages from an extension of 1 to 8. +--------------------------------------------------------------------------- +Version 1.1 +Extensive changes and additional functionality added to klogd. Please +see sources and man-pages for documentation. + +Fixed bugs in both syslogd and klogd with respect to fragmented +message re-assembly. Bootup messages should now be display properly. + +Fixed bug in syslogd which prevented proper logging of messages with +priority classes of none and emerg. + +Fixed bug which caused core dump when messages were logged to users. +Also fixed bug with messages to login type of LOGIN. + +Fixed problem with zombies being left when messages were logged to +multiple users. + +Enhanced functionality of syslog_tst program. + +Added man-pages. +--------------------------------------------------------------------------- + +--------------------------------------------------------------------------- +Version 1.0 + +Initial release. +--------------------------------------------------------------------------- diff --git a/README.1st b/README.1st new file mode 100644 index 0000000..3946756 --- /dev/null +++ b/README.1st @@ -0,0 +1,65 @@ +Very important information before using version 1.3 +--------------------------------------------------- + +The included version of syslogd behaves in a slightly different manner +to the one in former releases. Please review the following important +differences: + +* By default the syslog daemon doesn't accept any message from the + syslog/udp port. To enable this add "-r" to the command-line + arguments. You _have to_ add this on every host that should run as a + centralized network log server. + + You also should take a look at other new command-line arguments: + "-l" and "-s". + + The syslog daemon by default does not forward to a remote host any + log messages which it received from a remote host. This is an + attempt to prevent syslog loops. If you desire this behavior the + -h command-line switch can be used to enable this behavior. + +* Syslogd was designed to strip off the local domain from every + message that comes from any host in the same domain. Unfortunately + this feature didn't work in every cases. This is now corrected. So + you might not get the fqdn anymore. + + If you use any scripts that analyze logfiles, please bare this in + mind. + +* Syslogd doesn't touch the filemode of any logfile. If it has to + create one, it will be world-readable. If you do not want this + (i.e. if auth.* is logged) you have to create the file by hand and + change permissions. + +* If you notice that some of your programs make heavy use of the + syslog facility and your disks get loud you might want to turn + fsync()ing after each line off. But note that in doing so you + increase the likelihood of lost information in the event of a + system crash. + +* If you're going to start klogd or syslogd by init(8), you don't have + to hack the code anymore. Instead add "-n" to the command-line + arguments. + +* Klogd can now be used to decode EIP addresses if it can determine a + System.map file (command-line argument "-k"). This is a very useful + feature if your system crashes, but its usability depends on an + actual and correct System.map file. + +* Both system utilities now check for and respect the existence of .pid + files. If the utilities are started by configuration scripts on + stable systems there is the potential that the process ID numbers of + the utilities will be identical from one system boot to another. + This will cause both klogd and syslogd to terminate. + + Both klogd and syslogd will attempt to remove their .pid files when + they receive termination signals. The difficulty noted above + typically occurs when a system crash occurs or an uncatchable signal + (kill -9) is used to stop the daemons. + + The cleanest solution to this problem is to insure that the system + configuration scripts (rc.*) provide a clean working environment for + a freshly booted system. As part of the initialization process + these scripts should remove all old .pid files found in /var/run. + This will insure that klogd and syslogd start properly even if prior + executions have been terminated harshly. diff --git a/README.linux b/README.linux new file mode 100644 index 0000000..bfeba2e --- /dev/null +++ b/README.linux @@ -0,0 +1,64 @@ +Welcome to the sysklogd package for Linux. All the utility +documentation has now been moved into the man pages. Please review +these carefully before proceeding. + +Version 1.3 of the package is the culmination of about two years of +experience and bug reports on the 1.2 version from both the INTERNET +and our corporate Linux networks. The utilities in this package should +provide VERY reliable system logging. Klogd and syslogd have both +been stress tested in kernel development environments where literally +hundreds of megabytes of kernel messages have been blasted through +them. If either utility should fail the development team would +appreciate debug information so that the bug can be reproduced and +squashed. + +Both utilities (syslogd, klogd) can be either run from init or started +as part of the rc.* sequence. Caution should be used when starting +these utilities from init since the default configuration is for both of +these utilities to auto-background themselves. Depending on the +version of init being used this could either result in the process +table being filled or at least 10 copies of the daemon being started. +If auto-backgrounding is NOT desired the command line option -n should +be used to disable the auto-fork feature. + +I have found work on the sysklogd package to be an interesting example +of the powers of the INTERNET. Stephen, Juha, Shane, Martin and +myself have successfully collaborated on the development of this +package without ever having met each other, in fact we could pass on +the street without realizing it. What I have developed is a profound +respect for the personal capabilities of each one of these +individuals. Perhaps the greatest `Linux Legacy' will be that its +development/enhancement is truly an example of the powers of +international cooperation through the worldwide INTERNET. + +We would be interested in keeping track of any and all bug +fixes/changes that are made. At the time that work was started on the +sysklogd package the syslog(d) sources seemed to have fallen into +neglect. This work started with and continues the believe that it is +important to maintain consistent standardized system utilities +sources. Hopefully the Linux community will find these sources to be +a useful addition to the software gene pool. + +Best regards, + +Dr. Wettstein +Oncology Research Division Computing Facility +Roger Maris Cancer Center +Fargo, ND +greg@wind.rmcc.com + +Stephen Tweedie +Department of Computer Science +Edinburgh University, Scotland + +Juha Virtanen +jiivee@hut.fi + +Shane Alderton +shane@scs.apana.org.au + +Martin Schulze +Infodrom Oldenburg +joey@linux.de + +And a host of bug reporters whose contributions cannot be underestimated. diff --git a/Sysklogd-1.3.lsm b/Sysklogd-1.3.lsm new file mode 100644 index 0000000..7acdbf6 --- /dev/null +++ b/Sysklogd-1.3.lsm @@ -0,0 +1,23 @@ +Begin3 +Title: sysklogd +Version: 1.3 +Entered-date: 960227 +Description: The sysklogd package implements two system log daemons. The + syslogd daemon is the general system logging daemon which + is responsible for handling requests for syslog services. + This version of syslogd is similar to the standard Berkeley + product but with a number of compatible extensions. The + klogd daemon runs either standalone or as a client of syslogd. + Klogd 'listens' to kernel log messages, prioritizes them and + routes them to either output files or to syslogd. This + version of klogd will optionally translate kernel addresses + to their symbolic equivalents if provided with a system map. +Keywords: logging, remote, kernel, syslogd, proc, daemon, klogd +Author: greg@wind.rmcc.com (Dr. G.W. Wettstein) +Maintained-by: greg@wind.rmcc.com (Dr. G.W. Wettstein) +Primary-site: tsx-11.mit.edu /pub/sources/sbin + 62kB sysklogd-1.3.tar.gz + 1kB sysklogd-1.3.lsm +Alternate-site: sunsite.unc.edu /pub/Linux/system/Daemons +Copying-policy: syslogd is under Berkeley copyright, klogd is under GPL. +End diff --git a/kernel.patch b/kernel.patch new file mode 100644 index 0000000..18b10d1 --- /dev/null +++ b/kernel.patch @@ -0,0 +1,70 @@ +diff -u --recursive --new-file v1.3.42/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c +--- v1.3.42/linux/arch/alpha/kernel/process.c Tue Oct 10 18:46:30 1995 ++++ linux/arch/alpha/kernel/process.c Sat Nov 18 12:23:19 1995 +@@ -57,8 +57,8 @@ + + void show_regs(struct pt_regs * regs) + { +- printk("\nps: %04lx pc: %016lx\n", regs->ps, regs->pc); +- printk("rp: %016lx sp: %p\n", regs->r26, regs+1); ++ printk("\nps: %04lx pc: [<%016lx>]\n", regs->ps, regs->pc); ++ printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1); + printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n", + regs->r0, regs->r1, regs->r2, regs->r3); + printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n", +diff -u --recursive --new-file v1.3.42/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c +--- v1.3.42/linux/arch/alpha/kernel/traps.c Wed Sep 27 15:59:56 1995 ++++ linux/arch/alpha/kernel/traps.c Sat Nov 18 12:22:52 1995 +@@ -25,8 +25,8 @@ + return; + printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); + sp = (unsigned long) (regs+1); +- printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps); +- printk("rp = %lx sp = %lx\n", regs->r26, sp); ++ printk("pc = [<%lx>] ps = %04lx\n", regs->pc, regs->ps); ++ printk("rp = [<%lx>] sp = %lx\n", regs->r26, sp); + printk("r0=%lx r1=%lx r2=%lx r3=%lx\n", + regs->r0, regs->r1, regs->r2, regs->r3); + printk("r8=%lx\n", regs->r8); +diff -u --recursive --new-file v1.3.42/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c +--- v1.3.42/linux/arch/i386/kernel/process.c Wed Nov 8 07:11:29 1995 ++++ linux/arch/i386/kernel/process.c Sat Nov 18 12:08:28 1995 +@@ -124,7 +124,7 @@ + void show_regs(struct pt_regs * regs) + { + printk("\n"); +- printk("EIP: %04x:%08lx",0xffff & regs->cs,regs->eip); ++ printk("EIP: %04x:[<%08lx>]",0xffff & regs->cs,regs->eip); + if (regs->cs & 3) + printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp); + printk(" EFLAGS: %08lx\n",regs->eflags); +diff -u --recursive --new-file v1.3.42/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c +--- v1.3.42/linux/arch/i386/kernel/traps.c Wed Nov 8 07:11:30 1995 ++++ linux/arch/i386/kernel/traps.c Tue Nov 21 08:34:54 1995 +@@ -27,7 +27,7 @@ + + asmlinkage int system_call(void); + asmlinkage void lcall7(void); +-struct desc_struct default_ldt; ++struct desc_struct default_ldt; + + static inline void console_verbose(void) + { +@@ -113,7 +113,7 @@ + console_verbose(); + printk("%s: %04lx\n", str, err & 0xffff); + printk("CPU: %d\n", smp_processor_id()); +- printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); ++ printk("EIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); + printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", +@@ -153,7 +153,7 @@ + ((addr >= module_start) && (addr <= module_end))) { + if (i && ((i % 8) == 0)) + printk("\n "); +- printk("%08lx ", addr); ++ printk("[<%08lx>] ", addr); + i++; + } + } diff --git a/klogd.8 b/klogd.8 new file mode 100644 index 0000000..dda03e2 --- /dev/null +++ b/klogd.8 @@ -0,0 +1,271 @@ +.\" 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 +.\" +.TH KLOGD 8 "24 November 1995" "Version 1.3" "Linux System Administration" +.SH NAME +klogd \- kernel log daemon. +.LP +.SH SYNOPSIS +.B klogd +.RB [ " \-c " +.I n +] +.RB [ " \-d " ] +.RB [ " \-f " +.I fname +] +.RB [ " \-n " ] +.RB [ " \-o " ] +.RB [ " \-s " ] +.RB [ " \-k " +.I fname +] +.RB [ " \-v " ] +.LP +.SH DESCRIPTION +.B klogd +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 +.B "\-n" +Avoid auto-backgrounding. This is needed especially if the +.B klogd +is started and controlled by +.BR init (8). +.TP +.B "-o" +Execute in 'one\-shot' mode. This causes \fBklogd\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 "-s" +Force \fBklogd\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. +.LP +.SH OVERVIEW +The functionality of klogd 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 +filesystem 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 +filesystem. If this is found the +.I /proc/kmsg +file is used as the source of kernel log +information. If the proc filesystem is not mounted +.B klogd +uses a +system call to obtain kernel messages. The command line switch +.RB ( "\-s" ) +can be used to force klogd to use the system call interface as its +messaging source. + +If kernel messages are directed through the +.BR syslogd " daemon the " klogd +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 klogd 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 klogd +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 klogd 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. + +By default the +.B klogd +daemon executes a system call to inhibit all +kernel messages (except for panics) from being displayed on the +console. The \fB\-c\fR switch can be used to alter this behavior. 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 + klogd \-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 klogd 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 + klogd -o -f ./krnl.msg +.fi +.PP +.SH KERNEL ADDRESS RESOLUTION +.B klogd +will attempt to resolve kernel numeric addresses to their symbolic +forms if a kernel symbol table is available at execution time. +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 klogd 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 klogd. Earlier +kernels require a source code patch be applied to the kernel sources. +This patch is supplied with the sysklogd sources. +.PP +.SH SIGNAL HANDLING +The +.B klogd +will respond to six signals: +.BR SIGHUP ", " SIGINT ", " SIGKILL ", " SIGTERM ", " SIGTSTP " 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 +singals 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. +.LP +.SH FILES +.PD 0 +.TP +.I /proc/kmsg +One Source for kernel messages +.B klogd +.TP +.I /var/run/klogd.pid +The file containing the process id of +.B klogd +.TP +.I /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 klogd +was originally written by Steve Lord (lord@cray.com), Greg Wettstein +made major improvements. + +.PD 0 +.TP +Dr. Greg Wettstein (greg@wind.rmcc.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/klogd.c b/klogd.c new file mode 100644 index 0000000..e84fb12 --- /dev/null +++ b/klogd.c @@ -0,0 +1,735 @@ +/* + klogd.c - main program for Linux kernel log daemon. + Copyright (c) 1995 Dr. G.W. Wettstein + + 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. +*/ + +/* + * 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. + * + */ + + +/* Includes. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "klogd.h" +#include "pidfile.h" +#include "version.h" + +#define __LIBRARY__ +#include +#define __NR_sys_syslog __NR_syslog +_syscall3(int,sys_syslog,int, type, char *, buf, int, len); + +#define LOG_BUFFER_SIZE 4096 +#define LOG_LINE_LENGTH 1024 + +#if defined(FSSTND) +static char *PidFile = _PATH_VARRUN "klogd.pid"; +#else +static char *PidFile = "/etc/klogd.pid"; +#endif + +static int kmsg, + change_state = 0, + terminate = 0, + caught_TSTP = 0, + console_log_level = 6; + +static int use_syscall = 0, + one_shot = 0, + NoFork = 0; /* don't fork - don't run in daemon mode */ + +static char log_buffer[LOG_BUFFER_SIZE]; + +static FILE *output_file = (FILE *) 0; + +static enum LOGSRC {none, proc, kernel} logsrc; + +int debugging = 0; + + +/* Function prototypes. */ +extern int sys_syslog(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); +static void Terminate(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[]); + + +static void CloseLogSrc() + +{ + /* Turn on logging of messages to console. */ + sys_syslog(7, NULL, 0); + + /* Shutdown the log sources. */ + switch ( logsrc ) + { + case kernel: + sys_syslog(0, 0, 0); + Syslog(LOG_INFO, "Kernel logging (sys_syslog) 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(sig) + + int sig; + +{ + signal(SIGCONT, restart); + change_state = 1; + caught_TSTP = 0; + return; +} + + +void stop_logging(sig) + + int sig; + +{ + signal(SIGTSTP, stop_logging); + change_state = 1; + caught_TSTP = 1; + return; +} + + +void stop_daemon(sig) + + int sig; + +{ + change_state = 1; + terminate = 1; + return; +} + + +static void Terminate() + +{ + CloseLogSrc(); + Syslog(LOG_INFO, "Kernel log daemon terminating."); + sleep(1); + if ( output_file != (FILE *) 0 ) + fclose(output_file); + closelog(); + (void) remove_pid(PidFile); + exit(1); +} + + +static void ChangeLogging(void) + +{ + /* Terminate kernel logging. */ + if ( terminate == 1 ) + Terminate(); + + /* 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 ( (sys_syslog(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."); + sys_syslog(6, NULL, 0); + } + + + /* + * First do a stat to determine whether or not the proc based + * file system is available to get kernel messages from. + */ + if ( use_syscall || + ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) ) + { + /* Initialize kernel logging. */ + sys_syslog(1, NULL, 0); + Syslog(LOG_INFO, "klogd %s-%s, log source = sys_syslog " + "started.", VERSION, PATCHLEVEL); + return(kernel); + } + + if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 ) + { + fputs("klogd: Cannot open proc file system.", stderr); + sys_syslog(7, NULL, 0); + exit(1); + } + + Syslog(LOG_INFO, "klogd %s-%s, log source = %s started.", \ + VERSION, PATCHLEVEL, _PATH_KLOG); + return(proc); +} + + +extern void Syslog(int priority, char *fmt, ...) + +{ + va_list ap; + + if ( debugging ) + { + fputs("Logging line:\n", stderr); + fprintf(stderr, "\tLine: %s\n", fmt); + fprintf(stderr, "\tPriority: %c\n", *(fmt+1)); + } + + /* 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); + fsync(fileno(output_file)); + return; + } + + /* Output using syslog. */ + if ( *fmt == '<' ) + { + switch ( *(fmt+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; + } + fmt += 3; + } + + va_start(ap, fmt); + vsyslog(priority, fmt, ap); + va_end(ap); + + return; +} + + +static void LogLine(char *ptr, int len) + +{ + auto int idx = 0; + static int index = 0; + auto char *nl; + static char line[LOG_LINE_LENGTH], + eline[LOG_LINE_LENGTH]; + + + if ( debugging && (len != 0) ) + { + fprintf(stderr, "Log buffer contains: %d characters.\n", len); + fprintf(stderr, "Line buffer contains: %d characters.\n", \ + index); + while ( idx <= len ) + { + fprintf(stderr, "Character #%d - %d:%c\n", idx, \ + ptr[idx], ptr[idx]); + ++idx; + } + if ( index != 0 ) + { + fputs("Line buffer contains an unterminated line:\n", \ + stderr); + fprintf(stderr, "\tCount: %d\n", index); + fprintf(stderr, "%s\n\n", line); + } + } + + if ( index == 0 ) + memset(line, '\0', sizeof(line)); + + while (len) { + nl = strpbrk(ptr, "\r\n"); /* Find first line terminator */ + if (nl) { + len -= nl - ptr + 1; + strncat(line, ptr, nl - ptr); + ptr = nl + 1; + /* Check for empty log line (may be produced if + kernel messages have multiple terminators, eg. + \n\r) */ + if ( (*line != '\n') && (*line != '\r') ) + { + memset(eline, '\0', sizeof(eline)); + ExpandKadds(line, eline); + Syslog(LOG_INFO, eline); + } + index = 0; + memset(line, '\0', sizeof(line)); + } + else + { + if ( debugging ) + { + fputs("No terminator - leftover:\n", stderr); + fprintf(stderr, "\tCharacters: %d\n", len); + fprintf(stderr, "\tIndex: %d\n", index); + fputs("\tLine: ", stderr); + fprintf(stderr, "%s\n", line); + } + + strncat(line, ptr, len); + index += len; + len = 0; + } + } + + 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 = sys_syslog(2, log_buffer, sizeof(log_buffer))) < 0 ) + { + if ( errno == EINTR ) + return; + fprintf(stderr, "Error return from sys_sycall: %d - %s\n", \ + errno, strerror(errno)); + } + + 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))) < 0 ) + { + if ( errno == EINTR ) + return; + Syslog(LOG_ERR, "Cannot read proc file system."); + } + + LogLine(log_buffer, rdcnt); + + return; +} + + +int main(argc, argv) + + int argc; + + char *argv[]; + +{ + auto int ch, use_output = 0; + + auto char *symfile = (char *) 0, + *log_level = (char *) 0, + *output = (char *) 0; + + /* Parse the command-line. */ + while ((ch = getopt(argc, argv, "c:df:k:nosv")) != EOF) + switch((char)ch) + { + 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 'k': /* Kernel symbol file. */ + symfile = optarg; + break; + case 'n': /* don't fork */ + NoFork++; + break; + case 'o': /* One-shot mode. */ + one_shot = 1; + break; + case 's': /* Use syscall interface. */ + use_syscall = 1; + break; + case 'v': + printf("klogd %s-%s\n", VERSION, PATCHLEVEL); + exit (1); + } + + + /* Set console logging level. */ + if ( log_level != (char *) 0 ) + { + if ( (strlen(log_level) > 1) || \ + (strchr("1234567", *log_level) == (char *) 0) ) + { + fprintf(stderr, "klogd: Invalid console logging " + "level <%s> specified.\n", log_level); + return(1); + } + console_log_level = *log_level - '0'; + } + + + /* + * 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) && (!NoFork) ) + { + 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("klogd: Already running.\n", stderr); + exit(1); + } + } + + + /* tuck my process id away */ + if (!check_pid(PidFile)) + { + if (!write_pid(PidFile)) + Terminate(); + } + else + { + fputs("klogd: Already running.\n", stderr); + Terminate(); + } + + + /* Signal setups. */ + for (ch= 1; ch < NSIG; ++ch) + signal(ch, SIG_IGN); + signal(SIGINT, stop_daemon); + signal(SIGKILL, stop_daemon); + signal(SIGTERM, stop_daemon); + signal(SIGHUP, stop_daemon); + signal(SIGTSTP, stop_logging); + signal(SIGCONT, restart); + + + /* Open outputs. */ + if ( use_output ) + { + if ( strcmp(output, "-") == 0 ) + output_file = stdout; + else if ( (output_file = fopen(output, "w")) == (FILE *) 0 ) + { + fprintf(stderr, "klogd: Cannot open output file %s - "\ + "%s\n", output, strerror(errno)); + return(1); + } + } + else + openlog("kernel", 0, LOG_KERN); + + + /* Handle one-shot logging. */ + if ( one_shot ) + { + InitKsyms(symfile); + 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(); + InitKsyms(symfile); + + /* The main loop. */ + while (1) + { + if ( change_state ) + ChangeLogging(); + switch ( logsrc ) + { + case kernel: + LogKernelLine(); + break; + case proc: + LogProcLine(); + break; + case none: + pause(); + break; + } + } +} diff --git a/klogd.h b/klogd.h new file mode 100644 index 0000000..ef6022b --- /dev/null +++ b/klogd.h @@ -0,0 +1,17 @@ +/* + * Symbols and definitions needed by klogd. + * + * Thu Nov 16 12:45:06 CST 1995: Dr. Wettstein + * Initial version. + */ + +/* Useful include files. */ +#include +#include +#include + + +/* Function prototypes. */ +extern int InitKsyms(char *); +extern char * ExpandKadds(char *, char *); +extern void Syslog(int priority, char *fmt, ...); diff --git a/ksym.c b/ksym.c new file mode 100644 index 0000000..f8f6618 --- /dev/null +++ b/ksym.c @@ -0,0 +1,713 @@ +/* + ksym.c - functions for kernel address->symbol translation + Copyright (c) 1995 Dr. G.W. Wettstein + + 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. + * + */ + + +/* Includes. */ +#include +#include +#include +#include "klogd.h" + +#define VERBOSE_DEBUGGING 0 + + +/* Variables, structures and type definitions static to this module. */ +struct sym_table +{ + unsigned long value; + char *name; +}; + +struct symbol +{ + char *name; + int size; + int offset; +}; + +static struct sym_table *sym_array = (struct sym_table *) 0; + +static int num_syms = 0; + +static char *system_maps[] = +{ + "/boot/System.map", + "/System.map", + "/usr/src/linux/System.map", +#if defined(TEST) + "./System.map", +#endif + (char *) 0 +}; + + +#if defined(TEST) +static int debugging = 1; +#else +extern int debugging; +#endif + + +/* Function prototypes. */ +static char * FindSymbolFile(void); +static int AddSymbol(unsigned long, char*); +static char * LookupSymbol(unsigned long, struct symbol *); +static int CheckVersion(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; + + + /* + * 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, "%8lx %c %s\n", &address, &type, sym) + != 3 ) + { + Syslog(LOG_ERR, "Error in symbol table input."); + 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); + 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."); + 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 type, + *file = (char *) 0, + **mf = system_maps, + sym[512]; + + auto int version; + + auto unsigned long int address; + + auto FILE *sym_file = (FILE *) 0; + + + if ( debugging ) + fputs("Searching for symbol map.\n", stderr); + + for (mf = system_maps; *mf != (char *) 0; ++mf) + { + if ( debugging ) + fprintf(stderr, "Trying %s.\n", *mf); + if ( (sym_file = fopen(*mf, "r")) == (FILE *) 0 ) + continue; + + /* + * At this point a map file was successfully opened. We + * now need to search this file and look for a version + * version information. + */ + version = 0; + while ( !feof(sym_file) && (version == 0) ) + { + if ( fscanf(sym_file, "%8lx %c %s\n", &address, \ + &type, sym) != 3 ) + { + Syslog(LOG_ERR, "Error in symbol table input."); + fclose(sym_file); + return((char *) 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: + if ( debugging ) + fprintf(stderr, "Symbol table has incorrect " \ + "version number.\n"); + break; + + case 0: + if ( debugging ) + fprintf(stderr, "No version information " \ + "found.\n"); + if ( file == (char *) 0 ) + { + if ( debugging ) + fputs("Saving filename.\n", stderr); + file = *mf; + } + break; + case 1: + if ( debugging ) + fprintf(stderr, "Found table with " \ + "matching version number.\n"); + return(*mf); + break; + } + } + + + /* + * At this stage of the game we are at the end of the symbol + * tables. We have evidently not found a symbol map whose version + * information matches the currently executing kernel. If possible + * we return a pointer to the first valid symbol map that was + * encountered. + */ + 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 kernrel. + * + * 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 char vstring[6]; + + auto int vnum, + major, + minor, + patch; + + auto struct utsname utsname; + + 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. + */ + memset(vstring, '\0', sizeof(vstring)); + strncpy(vstring, version + strlen(prefix), sizeof(vstring)-1); + vnum = atoi(vstring); + major = vnum / 65536; + vnum -= (major * 65536); + minor = vnum / 256; + patch = vnum - (minor * 256); + if ( debugging ) + fprintf(stderr, "Version string = %s, Major = %d, " \ + "Minor = %d, Patch = %d.\n", vstring, major, minor, \ + patch); + sprintf(vstring, "%d.%d.%d", major, minor, patch); + + /* + * 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); + + /* Failure. */ + if ( strcmp(vstring, utsname.release) != 0 ) + return(-1); + + /* Success. */ + return(1); +} + + +/************************************************************************** + * 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. + **************************************************************************/ + +extern char * LookupSymbol(value, sym) + + unsigned long value; + + struct symbol *sym; + +{ + auto int lp; + + auto char *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; + } + + return((char *) 0); +} + + +/************************************************************************** + * 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; + + auto int value; + + auto struct symbol sym; + + + /* + * Early return if there do not appear to be any kernel + * messages in this line. + */ + if ( (num_syms == 0) || + (kp = strstr(line, "[<")) == (char *) 0 ) + { + 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; + *kp = '\0'; + value = strtol(sl+1, (char **) 0, 16); + if ( (symbol = LookupSymbol(value, &sym)) == (char *) 0 ) + symbol = sl; + + strcat(elp, symbol); + elp += strlen(symbol); + if ( debugging ) + fprintf(stderr, "Symbol: %s = %x = %s, %d/%d\n", \ + sl+1, value, \ + (sym.size==0) ? symbol+1 : symbol, \ + sym.offset, sym.size); + + *kp = dlm; + value = 2; + if ( sym.size != 0 ) + { + --value; + ++kp; + elp += sprintf(elp, "+%d/%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); +} + + +/* + * 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 + +extern int main(int, char **); + + +extern int main(int argc, char *argv[]) +{ + auto long int value; + auto char line[1024], eline[2048]; + + +#if 0 + value = atol(argv[1]); + fprintf(stdout, "Value of %ld: %s\n", value, LookupSymbol(value)); +#endif + + if ( !InitKsyms((char *) 0) ) + { + fputs("ksym: Error loading system map.\n", stderr); + return(1); + } + + while ( !feof(stdin) ) + { + gets(line); + 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 diff --git a/pidfile.c b/pidfile.c new file mode 100644 index 0000000..144606c --- /dev/null +++ b/pidfile.c @@ -0,0 +1,130 @@ +/* + pidfile.c - interact with pidfiles + Copyright (c) 1995 Martin Schulze + + 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. +*/ + +/* + * Sat Aug 19 13:24:33 MET DST 1995: Martin Schulze + * First version (v0.2) released + */ + +#include +#include +#include +#include +#include +#include +#include + +/* 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; + } + + 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; + } + + pid = getpid(); + if (!fprintf(f,"%d\n", pid)) { + printf("Can't write pid , %s.\n", strerror(errno)); + close(fd); + return 0; + } + fflush(f); + + if (flock(fd, LOCK_UN) == -1) { + printf("Can't unlock pidfile %s, %s.\n", pidfile, strerror(errno)); + close(fd); + return 0; + } + 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..00aeca9 --- /dev/null +++ b/pidfile.h @@ -0,0 +1,50 @@ +/* + pidfile.h - interact with pidfiles + Copyright (c) 1995 Martin Schulze + + 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. +*/ + +/* 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/sysklogd.8 b/sysklogd.8 new file mode 100644 index 0000000..8c0d136 --- /dev/null +++ b/sysklogd.8 @@ -0,0 +1,585 @@ +.\" Copyright 1994 Dr. Greg Wettstein, Enjellic Systems Development. +.\" May be distributed under the GNU General Public License +.\" Sun Aug 30 11:35:55 MET: Martin Schulze: Updates +.\" +.TH SYSKLOGD 8 "13 December 1995" "Version 1.3" "Linux System Administration" +.SH NAME +sysklogd \- Linux system logging utilities. +.SH SYNOPSIS +.B syslogd +.RB [ " \-d " ] +.RB [ " \-f " +.I config file +] +.RB [ " \-h " ] +.RB [ " \-l " +.I hostlist +] +.RB [ " \-m " +.I interval +] +.RB [ " \-n " ] +.RB [ " \-p" +.IB socket +] +.RB [ " \-r " ] +.RB [ " \-s " +.I domainlist +] +.RB [ " \-v " ] +.LP +.SH DESCRIPTION +.B Sysklogd +provides two system utilities which provide support for +system logging and kernel message trapping. Support of both internet and +unix domain sockets enables this utility package to support both local +and remote logging. + +System logging is provided by a version of +.BR syslogd (8) +derived from the +stock BSD sources. Support for kernel logging is provided by the +.BR syslogd (8) +utility which allows kernel logging to be conducted in either a +standalone fashion or as a client of syslogd. + +.B Syslogd +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. + +While the +.B syslogd +sources have been heavily modified a couple of notes +are in order. First of all there has been a systematic attempt to +insure that syslogd follows its default, standard BSD behavior. +The second important concept to note is that this version of syslogd +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/syslog.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 whole line is ignored. + +.LP +.SH OPTIONS +.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 +.BI "\-f " "config file" +Specify an alternative configuration file instead of +.IR /etc/syslog.conf "," +which is the default. +.TP +.BI "\-h " +By default syslogd 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 "\-l " "hostlist" +Specify a hostname that should be logged only with its simple hostname +and not the the fqdn. Multiple hosts may be specified using the colon +(``:'') separator. +.TP +.BI "\-m " "interval" +The +.B syslogd +logs a mark timestamp regularly. The default +\fIinterval\fR between two \fI-- MARK --\fR lines is 20 minutes. This +can be changed with this option. +.TP +.B "\-n" +Avoid auto-backgrounding. This is needed especially if the +.B syslogd +is started and controlled by +.BR init (8). +.TP +.BI "\-p " "socket" +You can specify an alternative unix domain socket instead of +.IR /dev/log "." +.TP +.B "\-r" +This option will enable the facility to receive message from the +network using an internet domain socket with the syslog service (see +.BR services (5)). +The default is to not receive any messages from the network. + +This option is introduced in version 1.3 of the sysklogd +package. Please note that the default behavior is the opposite of +how older versions behave, so you might have to turn this on. +.TP +.BI "\-s " "domainlist" +Specify a domainname that should be stripped off before +logging. Multiple domains may be specified using the colon (``:'') +separator. Remember that the first match is used, not the best. +.TP +.B "\-v" +Print version and exit. +.LP +.SH SIGNALS +.B Syslogd +reacts to a set of signals. You may easily send a signal to +.B syslogd +using the following: +.IP +.nf +kill -SIGNAL `cat /var/run/syslogd.pid` +.fi +.PP +.TP +.B SIGHUP +This lets +.B syslogd +perform a re-initialization. All open files are closed, the +configuration file (default is +.IR /etc/syslog.conf ")" +will be reread and the +.BR syslog (3) +facility is started again. +.TP +.B SIGTERM +The +.B syslogd +will die. +.TP +.BR SIGINT ", " SIGQUIT +If debugging is enabled these are ignored, otherwise +.B syslogd +will die. +.TP +.B SIGUSR1 +Switch debugging on/off. This option can only be used if +.B syslogd +is started with the +.B "\-d" +debug option. +.TP +.B SIGCHLD +Wait for childs if some were born, because of wall'ing messages. +.TP +.B SIGALRM +Every time +.B syslogd +receives this signal it will log the mark line. Normally this is done +by +.BR alarm (2). +.LP +.SH CONFIGURATION FILE SYNTAX DIFFERENCES +.B Syslogd +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. +.IP +For example the following line caused ALL output from daemons using +the daemon facilities (debug is the lowest priority, so every higher +will also match) to go into +.IR /usr/adm/daemons : +.IP +.nf + # Sample syslog.conf + daemon.debug /usr/adm/daemons +.fi +.PP +Under the new scheme this behavior remains the same. The difference +is the addition of four new specifiers, the asterisk (\fB*\fR) +wildcard the equation sign (\fB=\fR), the exclamation mark +(\fB!\fR) and the minus sign (\fB-\fR). + +The \fB*\fR specifies that all messages for the +specified facility are to be directed to the destination. Note that +this behavior is degenerate with specifying a priority level of debug. +Users have indicated that the asterisk notation is more intuitive. + +The \fB=\fR wildcard is used to restrict logging to the specified priority +class. This allows, for example, routing only debug messages to a +particular logging source. +.IP +For example the following line in +.I syslog.conf +would direct debug messages from all sources to the +.I /usr/adm/debug +file. +.IP +.nf + # Sample syslog.conf + daemon.=debug /usr/adm/debug +.fi +.PP +.\" The \fB!\fR as the first character of a priority inverts the above +.\" mentioned interpretation. +The \fB!\fR is used to exclude logging of the specified +priorities. This affects all (!) possibilities of specifying priorities. +.IP +For example the following lines would log all messages of the facility +mail except those with the priority info to the +.I /usr/adm/mail +file. And all messages from news.info (including) to news.crit +(excluding) would be logged to the +.I /usr/adm/news +file. +.IP +.nf + # Sample syslog.conf + mail.*;mail.!=info /usr/adm/mail + news.info;news.!crit /usr/adm/news +.fi +.PP +You may use it intuitively as an exception specifier. The above +mentioned interpretation is simply inverted. Doing that you may use + +.nf + mail.none +.fi +or +.nf + mail.!* +.fi +or +.nf + mail.!debug +.fi + +to skip every message that comes with a mail facility. There is much +room to play with it. :-) + +The \fB-\fR may only be used to prefix a filename if you want to omit +sync'ing the file after every write to it. + +This may take some acclimatization for those individuals used to the +pure BSD behavior but testers have indicated that this syntax is +somewhat more flexible than the BSD behavior. Note that these changes +should not affect standard +.BR syslog.conf (5) +files. You must specifically +modify the configuration files to obtain the enhanced behavior. +.LP +.SH SUPPORT FOR REMOTE LOGGING +These modifications provide network support to the syslogd facility. +Network support means that messages can be forwarded from one node +running syslogd to another node running syslogd where they will be +actually logged to a disk file. + +To enable this you have to specify the +.B "\-r" +option on the command line. The default behavior is that +.B syslogd +won't listen to the network. + +The strategy is to have syslogd listen on a unix domain socket for +locally generated log messages. This behavior will allow syslogd to +inter-operate with the syslog found in the standard C library. At the +same time syslogd 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 syslogd +neither can receive remote messages nor send them, because the UDP +port cant be opened. Instead +.B syslogd +will die immediately, blowing out an error message. + +To cause messages to be forwarded to another host replace +the normal file line in the +.I syslog.conf +file with the name of the host to which the messages is to be sent +prepended with an @. +.IP +For example, to forward +.B ALL +messages to a remote host use the +following +.I syslog.conf +entry: +.IP +.nf + # Sample syslogd configuration file to + # messages to a remote host forward all. + *.* @hostname +.fi + +To forward all \fBkernel\fP messages to a remote host the +configuration file would be as follows: +.IP +.nf + # Sample configuration file to forward all kernel + # messages to a remote host. + kern.* @hostname +.fi +.PP + +If the remote hostname cannot be resolved at startup, because the +name-server might not be accessible (it may be started after syslogd) +you don't have to worry. +.B Syslogd +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). In my domain +(Infodrom Oldenburg) we accidently got one and our disks filled up +with the same single message. :-( + +To avoid this in further times no messages that were received from a +remote host are sent out to another (or the same) remote host +anymore. If there are scenarios where this doesn't make sense, please +drop me (Joey) a line. + +If the remote host is located in the same domain as the host, +.B syslogd +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 the +.B syslogd +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 NAMED PIPES (FIFOs) +This version of syslogd 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 syslogd 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 this +version of syslogd. This version of syslogd 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 syslogd 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. + +Both the +.BR syslogd "(8) and the " klogd (8) +can either 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 syslogd daemon to be +used as a conduit for a denial of service attack. Thanks go to John +Morrison (jmorriso@rflab.ee.ubc.ca) for alerting me to this potential. +A rogue program(mer) could very easily flood the syslogd 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 syslogd to be run as a non-root process. +\fBALSO NOTE\fP that this will prevent usage of remote logging since +syslogd 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. +.LP +.SH DEBUGGING +When debugging is turned on using +.B "\-d" +option the +.B syslogd +will 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 on 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/syslog.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 +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. +.SH FILES +.PD 0 +.TP +.I /etc/syslog.conf +Configuration file for +.BR syslogd . +See +.BR syslog.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/syslogd.pid +The file containing the process id of +.BR syslogd . +.PD +.SH BUGS +If an error occurs in one line the whole rule is ignored. + +.B Syslogd +doesn't change the filemode of opened logfiles at any stage of +process. If a file is created it is world readable. If you want to +avoid this, you have to create it and change permissions on your own. +This could be done in combination with rotating logfiles using the +.BR savelog (8) +program that is shipped in the +.B smail +3.x distribution. Remember that it might be a security hole if +everybody is able to read auth.* messages as these might contain +passwords. +.LP +.SH SEE ALSO +.BR syslog.conf (5), +.BR klogd (8), +.BR logger (1), +.BR syslog (2), +.BR syslog (3), +.BR services (5), +.BR savelog (8) +.LP +.SH COLLABORATORS +.B Syslogd +is taken from BSD sources, Greg Wettstein (greg@wind.rmcc.com) +performed the port to Linux, Martin Schulze (joey@linux.de) +fixed some bugs and added several new features. +.B Klogd +was originally written by Steve Lord (lord@cray.com), Greg Wettstein +made major improvements. + +.PD 0 +.TP +Dr. Greg Wettstein +.TP +Enjellic Systems Development +.TP +Oncology Research Division Computing Facility +.TP +Roger Maris Cancer Center +.TP +Fargo, ND +.TP +greg@wind.rmcc.com + +.TP +Stephen Tweedie +.TP +Department of Computer Science +.TP +Edinburgh University, Scotland +.TP +sct@dcs.ed.ac.uk + +.TP +Juha Virtanen +.TP +jiivee@hut.fi + +.TP +Shane Alderton +.TP +shane@scs.apana.org.au + +.TP +Martin Schulze +.TP +Infodrom Oldenburg +.TP +joey@linux.de +.PD +.zZ diff --git a/syslog-tst.conf b/syslog-tst.conf new file mode 100644 index 0000000..e69de29 diff --git a/syslog.c b/syslog.c new file mode 100644 index 0000000..d9ffa61 --- /dev/null +++ b/syslog.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1983, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted provided + * that: (1) source distributions retain this entire copyright notice and + * comment, and (2) distributions including binaries display the following + * acknowledgement: ``This product includes software developed by the + * University of California, Berkeley and its contributors'' in the + * documentation or other materials provided with the distribution and in + * all advertising materials mentioning features or use of this software. + * Neither the name of the University nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)syslog.c 5.28 (Berkeley) 6/27/90"; +#endif /* LIBC_SCCS and not lint */ + +/* + * SYSLOG -- print message on log file + * + * This routine looks a lot like printf, except that it outputs to the + * log file instead of the standard output. Also: + * adds a timestamp, + * prints the module name in front of the message, + * has some other formatting types (or will sometime), + * adds a newline on the end of the message. + * + * The output of this routine is intended to be read by syslogd(8). + * + * Author: Eric Allman + * Modified to use UNIX domain IPC by Ralph Campbell + * + * Sat Dec 11 11:58:31 CST 1993: Dr. Wettstein + * Changes to allow compilation with no complains under -Wall. + * + * Thu Jan 18 11:16:11 CST 1996: Dr. Wettstein + * Added patch to close potential security hole. This is the same + * patch which was announced in the linux-security mailing lists + * and incorporated into the libc version of syslog.c. + * + */ + +#include +#include +#include +#include +#include +#if 0 +#include "syslog.h" +#include "pathnames.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _PATH_LOGNAME "/dev/log" + +static int LogFile = -1; /* fd for log */ +static int connected; /* have done connect */ +static int LogStat = 0; /* status bits, set by openlog() */ +static const char *LogTag = "syslog"; /* string to tag the entry with */ +static int LogFacility = LOG_USER; /* default facility code */ + +void +syslog(int pri, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(pri, fmt, ap); + va_end(ap); +} + +void +vsyslog(pri, fmt, ap) + int pri; + const char *fmt; + va_list ap; +{ + register int cnt; + register char *p; + time_t now; + int fd, saved_errno; + char tbuf[2048], fmt_cpy[1024], *stdp = (char *) 0; + + saved_errno = errno; + + /* see if we should just throw out this message */ + if (!LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) + return; + if (LogFile < 0 || !connected) + openlog(LogTag, LogStat | LOG_NDELAY, 0); + + /* set default facility if none specified */ + if ((pri & LOG_FACMASK) == 0) + pri |= LogFacility; + + /* build the message */ + (void)time(&now); + (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); + for (p = tbuf; *p; ++p); + if (LogStat & LOG_PERROR) + stdp = p; + if (LogTag) { + (void)strcpy(p, LogTag); + for (; *p; ++p); + } + if (LogStat & LOG_PID) { + (void)sprintf(p, "[%d]", getpid()); + for (; *p; ++p); + } + if (LogTag) { + *p++ = ':'; + *p++ = ' '; + } + + /* substitute error message for %m */ + { + register char ch, *t1, *t2; + char *strerror(); + + for (t1 = fmt_cpy; + (ch = *fmt) != '\0' && t1iov_base = stdp; + v->iov_len = cnt - (stdp - tbuf); + ++v; + v->iov_base = "\n"; + v->iov_len = 1; + (void)writev(2, iov, 2); + } + + /* output the message to the local logger */ + if (write(LogFile, tbuf, cnt + 1) >= 0 || !(LogStat&LOG_CONS)) + return; + + /* + * output the message to the console; don't worry about + * blocking, if console blocks everything will. + */ + if ((fd = open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) < 0) + return; + (void)strcat(tbuf, "\r\n"); + cnt += 2; + p = index(tbuf, '>') + 1; + (void)write(fd, p, cnt - (p - tbuf)); + (void)close(fd); +} + +static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ +/* + * OPENLOG -- open system log + */ +void +openlog(ident, logstat, logfac) + const char *ident; + int logstat, logfac; +{ + if (ident != NULL) + LogTag = ident; + LogStat = logstat; + +#ifdef ALLOW_KERNEL_LOGGING + if ((logfac &~ LOG_FACMASK) == 0) +#else + if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) +#endif + LogFacility = logfac; + + if (LogFile == -1) { + SyslogAddr.sa_family = AF_UNIX; + strncpy(SyslogAddr.sa_data, _PATH_LOGNAME, + sizeof(SyslogAddr.sa_data)); + if (LogStat & LOG_NDELAY) { + LogFile = socket(AF_UNIX, SOCK_STREAM, 0); +/* fcntl(LogFile, F_SETFD, 1); */ + } + } + if (LogFile != -1 && !connected && + connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+ + strlen(SyslogAddr.sa_data)) != -1) + connected = 1; +} + +/* + * CLOSELOG -- close the system log + */ +void +closelog() +{ + (void) close(LogFile); + LogFile = -1; + connected = 0; +} + +static int LogMask = 0xff; /* mask of priorities to be logged */ +/* + * SETLOGMASK -- set the log mask level + */ +int +setlogmask(pmask) + int pmask; +{ + int omask; + + omask = LogMask; + if (pmask != 0) + LogMask = pmask; + return (omask); +} diff --git a/syslog.conf b/syslog.conf new file mode 100644 index 0000000..86b7fc6 --- /dev/null +++ b/syslog.conf @@ -0,0 +1,46 @@ +# /etc/syslog.conf - Configuration file for sysklogd(8) +# +# For info about the format of this file, see "man syslog.conf". +# +*.=debug -/usr/adm/debug +*.warning /usr/adm/syslog + +# Store critical stuff in critical +# +*.=crit;kern.none /var/adm/critical + +# Kernel messages are first, stored in the kernel file, +# critical messages and higher ones also go to another +# host and to the console +# +kern.* /var/adm/kernel +kern.crit @finlandia +kern.crit /dev/console +kern.info;kern.!err /var/adm/kernel-info + +# The tcp wrapper loggs with mail.info, we display all +# the connections on tty12 +# +mail.=info /dev/tty12 + +# Store all mail concearning stuff in a file +# +mail.*;mail.!=info -/var/adm/mail + +# Log all mail.info and news.info messages to info +# +mail,news.=info -/var/adm/info + +# Log info and notice mesages to messages file +# +*.=info;*.=notice;mail.none -/usr/adm/messages +#*.=info;mail,news.none -/usr/adm/messages + +# Emergency messages will be displayed using wall +# +*.=emerg * + +# Messages of the priority alert will be directed +# to the operator +# +*.alert root,joey diff --git a/syslog.conf.5 b/syslog.conf.5 new file mode 100644 index 0000000..6a1e42b --- /dev/null +++ b/syslog.conf.5 @@ -0,0 +1,389 @@ +.\" syslog.conf - sysklogd(8) configuration file +.\" Copyright (c) 1995 Martin Schulze +.\" +.\" 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. +.\" +.TH SYSLOG.CONF 5 "24 November 1995" "Version 1.3" "Linux System Administration" +.SH NAME +syslog.conf \- sysklogd(8) configuration file +.SH DESCRIPTION +The +.I syslog.conf +file is the main configuration file for the +.BR syslogd (8) +which logs system messages on *nix systems. This file specifies rules +for logging. For special features see the +.BR sysklogd (8) +manpage. + +Every rule consists of two fields, a +.I selector +field and an +.I 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. + +Lines starting with a hash mark (``#'') and empty lines are ignored. + +.SH SELECTORS +The selector field itself again consists of two parts, a +.I facility +and a +.IR priority , +separated by a period (``.''). +Both parts are case insensitive and can also be specified as decimal +numbers, but don't do that, you have been warned. Both facilities and +priorities are described in +.BR syslog (3). +The names mentioned below correspond to the similar +.BR LOG_ -values +in +.IR /usr/include/syslog.h . + +The +.I facility +is one of the following keywords: +.BR auth ", " authpriv ", " cron ", " daemon ", " kern ", " lpr ", " +.BR mail ", " mark ", " news ", " security " (same as " auth "), " +.BR syslog ", " user ", " uucp " and " local0 " through " local7 . +The keyword +.B security +should not be used anymore and +.B 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 +.I facility +specifies the subsystem that produced the message, i.e. all mail +programs log with the mail facility +.BR "" ( LOG_MAIL ) +if they log using syslog. + +The +.I priority +is one of the following keywords, in ascending order: +.BR debug ", " info ", " notice ", " warning ", " warn " (same as " +.BR warning "), " err ", " error " (same as " err "), " crit ", " +.BR alert ", " emerg ", " panic " (same as " emerg ). +The keywords +.BR error ", " warn " and " panic +are deprecated and should not be used anymore. The +.I priority +defines the severity of the message + +The behavior of the original BSD syslogd is that all messages of the +specified priority and higher are logged according to the given +action. This +.BR syslogd (8) +behaves the same, but has some extensions. + +In addition to the above mentioned names the +.BR syslogd (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 +.B none +stands for no priority of the given facility. + +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. + +Multiple selectors may be specified for a single +.I action +using the semicolon (``;'') separator. Remember that each selector in +the +.I selector +field is capable to overwrite the preceding ones. Using this +behavior you can exclude some priorities from the pattern. + +This +.BR syslogd (8) +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. + +.SH ACTIONS +The action field of a rule describes the abstract term +``logfile''. A ``logfile'' need not to be a real file, btw. The +.BR syslogd (8) +provides the following actions. + +.SS Regular File +Typically messages are logged to real files. The file has to be +specified with full pathname, beginning with a slash ``/''. + +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. + +.SS Named Pipes +This version of +.BR syslogd (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 +.BR mkfifo (1) +command before +.BR syslogd (8) +is started. + +.SS Terminal and Console +If the file you specified is a tty, special tty-handling is done, same +with +.IR /dev/console . + +.SS Remote Machine +This +.BR syslogd (8) +provides full remote logging, i.e. is able to send messages to a +remote host running +.BR syslogd (8) +and to receive messages from remote hosts. The remote +host won't forward the message again, it will just log them +locally. To forward messages to another host, prepend the hostname +with the at sign (``@''). + +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 +administration needs. + +.SS List of Users +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 (``,''). If they're logged in they +get the message. Don't think a mail would be sent, that might be too +late. + +.SS Everyone logged on +Emergency messages often go to all users currently online to notify +them that something strange is happening with the system. To specify +this +.IR wall (1)-feature +use an asterisk (``*''). + +.SH EXAMPLES +Here are some example, partially taken from a real existing site and +configuration. Hopefully they rub out all questions to the +configuration, if not, drop me (Joey) a line. +.IP +.nf +# Store critical stuff in critical +# +*.=crit;kern.none /var/adm/critical +.fi +.LP +This will store all messages with the priority +.B crit +or higher in the file +.IR /var/adm/critical , +except for any kernel message. + +.IP +.nf +# Kernel messages are first, stored in the kernel +# file, critical messages and higher ones also go +# to another host and to the console +# +kern.* /var/adm/kernel +kern.crit @finlandia +kern.crit /dev/console +kern.info;kern.!err /var/adm/kernel-info +.fi +.LP +The first rule direct any message that has the kernel facility to the +file +.IR /var/adm/kernel . + +The second statement directs all kernel messages of the priority +.B 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. + +The third rule directs these messages to the actual console, so the +person who works on the machine will get them, too. + +The fourth line tells the syslogd to save all kernel messages that +come with priorities from +.BR info " up to " warning +in the file +.IR /var/adm/kernel-info . +Everything from +.I err +and higher is excluded. + +.IP +.nf +# The tcp wrapper loggs with mail.info, we display +# all the connections on tty12 +# +mail.=info /dev/tty12 +.fi +.LP +This directs all messages that uses +.BR mail.info " (in source " LOG_MAIL " | " LOG_INFO ) +to +.IR /dev/tty12 , +the 12th console. For example the tcpwrapper +.BR tcpd (8) +uses this as it's default. + +.IP +.nf +# Store all mail concerning stuff in a file +# +mail.*;mail.!=info /var/adm/mail +.fi +.LP +This pattern matches all messages that come with the +.B mail +facility, except for the +.B info +priority. These will be stored in the file +.IR /var/adm/mail . + +.IP +.nf +# Log all mail.info and news.info messages to info +# +mail,news.=info /var/adm/info +.fi +.LP +This will extract all messages that come either with +.BR mail.info " or with " news.info +and store them in the file +.IR /var/adm/info . + +.IP +.nf +# Log info and notice messages to messages file +# +*.=info;*.=notice;mail.none /var/log/messages +.fi +.LP +This lets the +.B syslogd +log all messages that come with either the +.BR info " or the " notice +facility into the file +.IR /var/log/messages , +except for all messages that use the +.B mail +facility. + +.IP +.nf +# Log info messages to messages file +# +*.=info;mail,news.none /var/log/messages +.fi +.LP +This statement causes the +.B syslogd +to log all messages that come with the +.B info +priority to the file +.IR /var/log/messages . +But any message coming either with the +.BR mail " or the " news +facility will not be stored. + +.IP +.nf +# Emergency messages will be displayed using wall +# +*.=emerg * +.fi +.LP +This rule tells the +.B syslogd +to write all emergency messages to all currently logged in users. This +is the wall action. + +.IP +.nf +# Messages of the priority alert will be directed +# to the operator +# +*.alert root,joey +.fi +.LP +This rule directs all messages with a priority of +.B alert +or higher to the terminals of the operator, i.e. of the users ``root'' +and ``joey'' if they're logged in. + +.IP +.nf +*.* @finlandia +.fi +.LP +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. + +.SH CONFIGURATION FILE SYNTAX DIFFERENCES +.B Syslogd +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 the +.B syslogd +more flexible and to use it in a more intuitive manner. + +The original BSD syslogd doesn't understand spaces as separators between +the selector and the action field. +.SH FILES +.PD 0 +.TP +.I /etc/syslog.conf +Configuration file for +.B syslogd + +.SH BUGS +The effects of multiple selectors are sometimes not intuitive. For +example ``mail.crit,*.err'' will select ``mail'' facility messages at +the level of ``err'' or higher, not at the level of ``crit'' or +higher. + +.SH SEE ALSO +.BR sysklogd (8), +.BR klogd (8), +.BR logger (1), +.BR syslog (2), +.BR syslog (3) + +.SH AUTHORS +The +.B syslogd +is taken from BSD sources, Greg Wettstein (greg@wind.rmcc.com) +performed the port to Linux, Martin Schulze (joey@linux.de) +made some bugfixes and added some new features. diff --git a/syslog_tst.c b/syslog_tst.c new file mode 100644 index 0000000..ca78601 --- /dev/null +++ b/syslog_tst.c @@ -0,0 +1,74 @@ +/* Program to test daemon logging. */ + +/* + * Sat Dec 11 12:07:50 CST 1993: Dr. Wettstein + * Compiles clean with -Wall. Renamed for first public distribution. + * Use this freely but if you make a ton of money with it I + * expect a cut... :-) + * + * Thu Jan 6 11:52:10 CST 1994: Dr. Wettstein + * Added support for reading getting log input from the standard + * input. To activate this use a - as the single arguement to the + * the program. Note that there is a hack in the code to pause + * after each 1K has been written. This eliminates what appears + * to be a problem with overrunning a UNIX domain socket with + * excessive amounts of input. + */ + +#include +#include +#include +#include +#include + +extern int main(int, char **); + + +int main(int argc, char *argv[]) +{ + auto char *nl, + bufr[512]; + auto int logged = 0; + + openlog("DOTEST", LOG_PID, LOG_DAEMON); + if (argc > 1) + { + if ( (*argv[1] == '-') && (*(argv[1]+1) == '\0') ) + { + while (!feof(stdin)) + if ( fgets(bufr, sizeof(bufr), stdin) != \ + (char *) 0 ) + { + if ( (nl = strrchr(bufr, '\n')) != \ + (char *) 0) + *nl = '\0'; + syslog(LOG_INFO, bufr); + logged += strlen(bufr); + if ( logged > 1024 ) + { + sleep(1); + logged = 0; + } + + } + } + else + while (argc-- > 1) + syslog(LOG_INFO, argv++[1]); + } + else + { + syslog(LOG_EMERG, "EMERG log."); + syslog(LOG_ALERT, "Alert log."); + syslog(LOG_CRIT, "Critical log."); + syslog(LOG_ERR, "Error log."); + syslog(LOG_WARNING, "Warning log."); + syslog(LOG_NOTICE, "Notice log."); + syslog(LOG_INFO, "Info log."); + syslog(LOG_DEBUG, "Debug log."); + closelog(); + return(0); + } + + return(0); +} diff --git a/syslogd.8 b/syslogd.8 new file mode 100644 index 0000000..d5ef84b --- /dev/null +++ b/syslogd.8 @@ -0,0 +1 @@ +.so man8/sysklogd.8 diff --git a/syslogd.c b/syslogd.c new file mode 100644 index 0000000..596f08c --- /dev/null +++ b/syslogd.c @@ -0,0 +1,2339 @@ +/* + * Copyright (c) 1983, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if !defined(lint) && !defined(NO_SCCS) +char copyright2[] = +"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#if !defined(lint) && !defined(NO_SCCS) +static char sccsid[] = "@(#)syslogd.c 5.27 (Berkeley) 10/10/88"; +#endif /* not lint */ + +/* + * syslogd -- log system messages + * + * This program implements a system log. It takes a series of lines. + * Each line may have a priority, signified as "" as + * the first characters of the line. If this is + * not present, a default priority is used. + * + * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will + * cause it to reread its configuration file. + * + * Defined Constants: + * + * MAXLINE -- the maximum line length that can be handled. + * DEFUPRI -- the default priority for user messages + * DEFSPRI -- the default priority for kernel messages + * + * 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@scs.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 + * 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. + */ + + +#define MAXLINE 1024 /* maximum line length */ +#define MAXSVLINE 240 /* maximum saved line length */ +#define DEFUPRI (LOG_USER|LOG_NOTICE) +#define DEFSPRI (LOG_KERN|LOG_CRIT) +#define TIMERINTVL 30 /* interval for checking flush, mark */ + +#include +#include +#include +#ifdef SYSV +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SYSV +#include +#else +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "pidfile.h" +#include "version.h" + +#if defined(__linux__) +#include +#endif + +#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/syslog.conf" +#endif + +#if defined(SYSLOGD_PIDNAME) +#undef _PATH_LOGPID +#if defined(FSSTND) +#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 "syslogd.pid" +#else +#define _PATH_LOGPID "/etc/syslogd.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 +#define _PATH_LOG "/dev/log" +#endif + +char *LogName = _PATH_LOG; +char *ConfFile = _PATH_LOGCONF; +char *PidFile = _PATH_LOGPID; +char ctty[] = _PATH_CONSOLE; + +char **parts; + +int inetm = 0, funix = 0; +static int debugging_on = 0; +static int nlogs = -1; +static int restart = 0; + +#define UNAMESZ 8 /* length of a login name */ +#define MAXUNAMES 20 /* maximum number of user names */ +#define MAXFNAME 200 /* max file pathname length */ + +#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" */ + +/* + * Flags to logmsg(). + */ + +#define IGN_CONS 0x001 /* don't print on console */ +#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 */ + +/* + * This table contains plain text for h_errno errors used by the + * net subsystem. + */ +const char *sys_h_errlist[] = { + "No problem", /* NETDB_SUCCESS */ + "Authoritative answer: host not found", /* HOST_NOT_FOUND */ + "Non-authoritative answer: host not found, or serverfail", /* TRY_AGAIN */ + "Non recoverable errors", /* NO_RECOVERY */ + "Valid name, no data record of requested type", /* NO_DATA */ + "no address, look for MX record" /* NO_ADDRESS */ + }; + +/* + * This structure represents the files that will have log + * copies printed. + */ + +struct filed { +#ifndef SYSV + struct filed *f_next; /* next in linked list */ +#endif + short f_type; /* entry type, see below */ + short f_file; /* file descriptor */ + time_t f_time; /* time this was last written */ + u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ + union { + char f_uname[MAXUNAMES][UNAMESZ+1]; + struct { + char f_hname[MAXHOSTNAMELEN+1]; + struct sockaddr_in f_addr; + } f_forw; /* forwarding address */ + char f_fname[MAXFNAME]; + } f_un; + char f_prevline[MAXSVLINE]; /* last message logged */ + char f_lasttime[16]; /* time of last occurrence */ + char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */ + int f_prevpri; /* pri of f_prevline */ + int f_prevlen; /* length of f_prevline */ + int f_prevcount; /* repetition cnt of prevline */ + int f_repeatcount; /* number of "repeated" msgs */ + int f_flags; /* store some additional flags */ +}; + +/* + * 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 ((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 +#define INET_SUSPEND_TIME 180 /* equal to 3 minutes */ +#define INET_RETRY_MAX 10 /* maximum of retries for gethostbyname() */ +#endif + +#define LIST_DELIMITER ':' /* delimiter between two hosts */ + +/* values for f_type */ +#define F_UNUSED 0 /* unused entry */ +#define F_FILE 1 /* regular file */ +#define F_TTY 2 /* terminal */ +#define F_CONSOLE 3 /* console terminal */ +#define F_FORW 4 /* remote machine */ +#define F_USERS 5 /* list of users */ +#define F_WALL 6 /* everyone logged on */ +#define F_FORW_SUSP 7 /* suspended host forwarding */ +#define F_FORW_UNKN 8 /* unknown host forwarding */ +char *TypeNames[9] = { + "UNUSED", "FILE", "TTY", "CONSOLE", + "FORW", "USERS", "WALL", "FORW(SUSPENDED)", + "FORW(UNKNOWN)" +}; + +struct filed *Files = (struct filed *) 0; +struct filed consfile; + +struct code { + char *c_name; + int c_val; +}; + +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} +}; + +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}, + {"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}, +}; + +int Debug; /* debug flag */ +char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */ +char *LocalDomain; /* our local domain name */ +int InetInuse = 0; /* non-zero if INET sockets are being used */ +int finet; /* Internet datagram socket */ +int LogPort; /* port number for INET connections */ +int Initialized = 0; /* set when we have initialized ourselves */ +int MarkInterval = 20 * 60; /* interval between marks in seconds */ +int MarkSeq = 0; /* mark sequence number */ +int NoFork = 0; /* don't fork - don't run in daemon mode */ +int AcceptRemote = 0; /* receive messages that come via UDP */ +char **StripDomains = NULL; /* these domains may be stripped before writing logs */ +char **LocalHosts = NULL; /* these hosts are logged with their hostname */ +int NoHops = 1; /* Can we bounce syslog messages through an + intermediate host. */ + +extern int errno, sys_nerr; +extern char *sys_errlist[]; +extern char *ctime(), *index(); + +/* Function prototypes. */ +int main(int argc, char **argv); +char **crunch_list(char *list); +int usage(void); +void untty(void); +void printchopped(const char *hname, char *msg, int len, int fd); +void printline(const char *hname, char *msg); +void printsys(char *msg); +void logmsg(int pri, char *msg, const char *from, int flags); +void fprintlog(register struct filed *f, char *from, int flags, char *msg); +void endtty(); +void wallmsg(register struct filed *f, struct iovec *iov); +void reapchild(); +const char *cvthname(struct sockaddr_in *f); +void domark(); +void debug_switch(); +void logerror(char *type); +void die(int sig); +void init(); +void cfline(char *line, register struct filed *f); +int decode(char *name, struct code *codetab); +static void dprintf(char *, ...); +static void allocate_log(void); +void sighup_handler(); + + +int main(argc, argv) + int argc; + char **argv; +{ + register int i; + register char *p; + int len, num_fds; + fd_set unixm, readfds; + + int fd; +#ifdef SYSLOG_UNIXAF + struct sockaddr_un sunx, fromunix; +#endif +#ifdef SYSLOG_INET + struct sockaddr_in sin, frominet; + char *from; +#endif + int ch; + struct hostent *hent; + + char line[MAXLINE +1]; + extern int optind; + extern char *optarg; + + int quitpid = 0; + + while ((ch = getopt(argc, argv, "dhf:l:m:np:rs:v")) != EOF) + switch((char)ch) { + case 'd': /* debug */ + Debug = 1; + break; + case 'f': /* configuration file */ + ConfFile = optarg; + break; + case 'h': + NoHops = 0; + break; + case 'l': + if (LocalHosts) { + printf ("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 'p': /* path */ + LogName = optarg; + break; + case 'r': /* accept remote messages */ + AcceptRemote = 1; + break; + case 's': + if (StripDomains) { + printf ("Only one -s argument allowed," \ + "the first one is taken.\n"); + break; + } + StripDomains = crunch_list(optarg); + break; + case 'v': + printf("syslogd %s-%s\n", VERSION, PATCHLEVEL); + exit (1); + case '?': + default: + usage(); + } + if (argc -= optind) + usage(); + + if ( !(Debug || NoFork) ) + { + dprintf("Checking pidfile.\n"); + if (!check_pid(PidFile)) + { + quitpid = getpid(); + if (fork()) + { + /* We try to wait the end of initialization */ + sleep(10); + exit(0); + } + num_fds = getdtablesize(); + for (i= 0; i < num_fds; i++) + (void) close(i); + untty(); + } + else + { + fputs("syslogd: Already running.\n", stderr); + exit(1); + } + } + else + debugging_on = 1; +#ifndef SYSV + else + setlinebuf(stdout); +#endif + + /* tuck my process id away */ + if ( !Debug ) + { + dprintf("Writing pidfile.\n"); + if (!check_pid(PidFile)) + { + if (!write_pid(PidFile)) + { + dprintf("Can't write pid.\n"); + exit(1); + } + } + else + { + dprintf("Pidfile (and pid) already exist.\n"); + exit(1); + } + } /* if ( !Debug ) */ + + consfile.f_type = F_CONSOLE; + (void) strcpy(consfile.f_un.f_fname, ctty); + (void) gethostname(LocalHostName, sizeof(LocalHostName)); + if ( (p = index(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 + */ + hent = gethostbyname(LocalHostName); + sprintf(LocalHostName, "%s", hent->h_name); + if ( (p = index(LocalHostName, '.')) ) + { + *p++ = '\0'; + LocalDomain = p; + } + } + + /* + * Convert to lower case to recognize the correct domain laterly + */ + for (p = (char *)LocalDomain; *p ; p++) + if (isupper(*p)) + *p = tolower(*p); + + (void) signal(SIGTERM, die); + (void) signal(SIGINT, Debug ? die : SIG_IGN); + (void) signal(SIGQUIT, Debug ? die : SIG_IGN); + (void) signal(SIGCHLD, reapchild); + (void) signal(SIGALRM, domark); + (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN); + (void) alarm(TIMERINTVL); + (void) unlink(LogName); + +#ifdef SYSLOG_UNIXAF + sunx.sun_family = AF_UNIX; + (void) strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path)); + funix = socket(AF_UNIX, SOCK_STREAM, 0); + if (funix < 0 || bind(funix, (struct sockaddr *) &sunx, + sizeof(sunx.sun_family)+strlen(sunx.sun_path)) < 0 || + chmod(LogName, 0666) < 0 || listen(funix, 5) < 0) { + (void) sprintf(line, "cannot create %s", LogName); + logerror(line); + dprintf("cannot create %s (%d).\n", LogName, errno); +#ifndef SYSV + die(0); +#endif + } +#endif + +#ifdef SYSLOG_INET + finet = socket(AF_INET, SOCK_DGRAM, 0); + if (finet >= 0) { + auto int on = 1; + struct servent *sp; + + sp = getservbyname("syslog", "udp"); + if (sp == NULL) { + errno = 0; + logerror("network logging disabled (syslog/udp service unknown)."); + logerror("see syslogd(8) for details of whether and how to enable it."); + } + else { + sin.sin_family = AF_INET; + sin.sin_port = LogPort = sp->s_port; + sin.sin_addr.s_addr = 0; + if ( setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, \ + (char *) &on, sizeof(on)) < 0 ) { + logerror("setsockopt, suspending inet"); + } + else { + if (bind(finet, (struct sockaddr *) &sin, \ + sizeof(sin)) < 0) { + logerror("bind, suspending inet"); + } else { + inetm = finet; + InetInuse = 1; + dprintf("listening on syslog UDP port.\n"); + } + } + } + } + else + logerror("syslog: Unknown protocol, suspending inet service."); +#endif + + + /* Create a partial message table for all file descriptors. */ + num_fds = getdtablesize(); + dprintf("Allocated parts table for %d file descriptors.\n", num_fds); + if ( (parts = (char **) malloc(num_fds * sizeof(char *))) == \ + (char **) 0 ) + { + logerror("Cannot allocate memory for message parts table."); + die(0); + } + for(i= 0; i < num_fds; ++i) + parts[i] = (char *) 0; + + dprintf("Starting.\n"); + init(); + if ( Debug ) + { + dprintf("Debugging disabled, SIGUSR1 to turn on debugging.\n"); + debugging_on = 0; + } + + if (quitpid) { + kill(quitpid, SIGINT); + } + + /* Main loop begins here. */ + FD_ZERO(&unixm); + FD_ZERO(&readfds); + for (;;) { + int nfds; + errno = 0; +#ifdef SYSLOG_UNIXAF + /* + * Add the Unix Domain Socket to the list of read + * descriptors. + */ + FD_SET(funix, &readfds); + for (nfds= 0; nfds < FD_SETSIZE; ++nfds) + if ( FD_ISSET(nfds, &unixm) ) + FD_SET(nfds, &readfds); +#endif +#ifdef SYSLOG_INET + /* + * Add the Internet Domain Socket to the list of read + * descriptors. + */ + if ( InetInuse && AcceptRemote ) + FD_SET(inetm, &readfds); +#endif + + if ( debugging_on ) + { + dprintf("Calling select, active file descriptors: "); + for (nfds= 0; nfds < FD_SETSIZE; ++nfds) + if ( FD_ISSET(nfds, &readfds) ) + dprintf("%d ", nfds); + dprintf("\n"); + } + nfds = select(FD_SETSIZE, (fd_set *) &readfds, (fd_set *) NULL, + (fd_set *) NULL, (struct timeval *) NULL); + if ( restart ) + { + dprintf("\nReceived SIGHUP, reloading syslogd.\n"); + init(); + restart = 0; + continue; + } + if (nfds == 0) { + dprintf("No select activity.\n"); + continue; + } + if (nfds < 0) { + if (errno != EINTR) + logerror("select"); + dprintf("Select interrupted.\n"); + continue; + } + + if ( debugging_on ) + { + dprintf("\nSuccessful select, descriptor count = %d, " \ + "Activity on: ", nfds); + for (nfds= 0; nfds < FD_SETSIZE; ++nfds) + if ( FD_ISSET(nfds, &readfds) ) + dprintf("%d ", nfds); + dprintf(("\n")); + } + +#ifdef SYSLOG_UNIXAF + if ( debugging_on ) + { + dprintf("Checking UNIX connections, active: "); + for (nfds= 0; nfds < FD_SETSIZE; ++nfds) + if ( FD_ISSET(nfds, &unixm) ) + dprintf("%d ", nfds); + dprintf("\n"); + } + for (fd= 0; fd <= FD_SETSIZE; ++fd) + if ( FD_ISSET(fd, &readfds) && FD_ISSET(fd, &unixm) ) { + dprintf("Message from UNIX socket #%d.\n", fd); + memset(line, '\0', sizeof(line)); + i = read(fd, line, MAXLINE); + if (i > 0) { + printchopped(LocalHostName, line, i, fd); + } else if (i < 0) { + if (errno != EINTR) { + logerror("recvfrom unix"); + } + } else { + dprintf("Unix socket (%d) closed.\n", fd); + if ( parts[fd] != (char *) 0 ) + { + logerror("Printing partial message"); + line[0] = '\0'; + printchopped(LocalHostName, line, \ + strlen(parts[fd]) + 1, \ + fd); + } + close(fd); + FD_CLR(fd, &unixm); + FD_CLR(fd, &readfds); + } + } + /* Accept a new unix connection */ + if (FD_ISSET(funix, &readfds)) { + len = sizeof(fromunix); + if ((fd = accept(funix, (struct sockaddr *) &fromunix,\ + &len)) >= 0) { + FD_SET(fd, &unixm); + dprintf("New UNIX connect assigned to fd: " \ + "%d.\n", fd); + FD_SET(fd, &readfds); + } + else { + dprintf("Error accepting UNIX connection: " \ + "%d = %s.\n", errno, strerror(errno)); + } + } + +#endif + +#ifdef SYSLOG_INET + if (InetInuse && AcceptRemote && FD_ISSET(inetm, &readfds)) { + len = sizeof(frominet); + memset(line, '\0', sizeof(line)); + i = recvfrom(finet, line, MAXLINE - 2, 0, \ + (struct sockaddr *) &frominet, &len); + dprintf("Message from inetd socket: #%d, host: %s\n", + inetm, inet_ntoa(frominet.sin_addr)); + if (i > 0) { + line[i] = line[i+1] = '\0'; + from = (char *)cvthname(&frominet); + /* + * Here we could check if the host is permitted + * to send us syslog messages. We just have to + * catch the result of cvthname, look for a dot + * and if that doesn't exist, replace the first + * '\0' with '.' and we have the fqdn in lowercase + * letters so we could match them against whatever. + * -Joey + */ + printchopped(from, line, \ + i + 2, finet); + } else if (i < 0 && errno != EINTR) { + dprintf("INET socket error: %d = %s.\n", \ + errno, strerror(errno)); + logerror("recvfrom inet"); + sleep(10); + } + } +#endif + } +} + +int usage() +{ + fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \ + " [-s domainlist] [-f conffile]\n"); + exit(1); +} + + +char ** +crunch_list(list) + char *list; +{ + int count; + int i; + char *p; + 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); + } + + /* + * 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 ((i=(int)index(p, LIST_DELIMITER))) { + if ((result[count] = \ + (char *)malloc(sizeof(char) * i - (int)p +1)) == NULL) { + printf ("Sorry, can't get enough memory, exiting.\n"); + exit(0); + } + strncpy(result[count],p, i - (int)p); + result[count][i - (int)p] = '\0'; + p = (char *)i;p++; + count++; + } + if ((result[count] = \ + (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) { + printf ("Sorry, can't get enough memory, exiting.\n"); + exit(0); + } + strcpy(result[count],p); + result[++count] = NULL; + +#if 0 + count=0; + while (result[count]) + dprintf ("#%d: %s\n", count, StripDomains[count++]); +#endif + return result; +} + + +void untty() +#ifdef SYSV +{ + 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 + + +/* + * Parse the line to make sure that the msg is not a composite of more + * than one message. + */ + +void printchopped(hname, msg, len, fd) + const char *hname; + char *msg; + int len; + int fd; +{ + auto int ptlngth; + + auto char *start = msg, + *p, + *end, + tmpline[MAXLINE + 1]; + + dprintf("Message length: %d, File descriptor: %d.\n", len, fd); + tmpline[0] = '\0'; + if ( parts[fd] != (char *) 0 ) + { + dprintf("Including part from messages.\n"); + strcpy(tmpline, parts[fd]); + free(parts[fd]); + parts[fd] = (char *) 0; + if ( (strlen(msg) + strlen(tmpline)) > MAXLINE ) + { + logerror("Cannot glue message parts together"); + printline(hname, tmpline); + start = msg; + } + else + { + dprintf("Previous: %s\n", tmpline); + dprintf("Next: %s\n", msg); + strcat(tmpline, msg); + printline(hname, tmpline); + if ( (strlen(msg) + 1) == len ) + return; + else + start = strchr(msg, '\0') + 1; + } + } + + if ( msg[len-1] != '\0' ) + { + msg[len] = '\0'; + for(p= msg+len-1; *p != '\0' && p > msg; ) + --p; + ptlngth = strlen(++p); + if ( (parts[fd] = malloc(ptlngth + 1)) == (char *) 0 ) + logerror("Cannot allocate memory for message part."); + else + { + strcpy(parts[fd], p); + dprintf("Saving partial msg: %s\n", parts[fd]); + memset(p, '\0', ptlngth); + } + } + + do { + end = strchr(start + 1, '\0'); + printline(hname, start); + start = end + 1; + } while ( *start != '\0' ); + + return; +} + + + +/* + * Take a raw input line, decode the message, and print the message + * on the appropriate log files. + */ + +void printline(hname, msg) + const char *hname; + char *msg; +{ + register char *p, *q; + register int c; + char line[MAXLINE + 1]; + int pri; + + /* test for special codes */ + pri = DEFUPRI; + p = msg; + if (*p == '<') { + pri = 0; + while (isdigit(*++p)) + { + pri = 10 * pri + (*p - '0'); + } + if (*p == '>') + ++p; + } + if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) + pri = DEFUPRI; + + q = line; + while ((c = *p++ & 0177) != '\0' && + q < &line[sizeof(line) - 1]) + if (c == '\n') + *q++ = ' '; + else if (iscntrl(c)) { + *q++ = '^'; + *q++ = c ^ 0100; + } else + *q++ = c; + *q = '\0'; + + logmsg(pri, line, hname, SYNC_FILE); + return; +} + + + +/* + * Take a raw input line from /dev/klog, split and format similar to syslog(). + */ + +void printsys(msg) + char *msg; +{ + register char *p, *q; + register int c; + char line[MAXLINE + 1]; + int pri, flags; + char *lp; + + (void) sprintf(line, "vmunix: "); + lp = line + strlen(line); + for (p = msg; *p != '\0'; ) { + flags = ADDDATE; + pri = DEFSPRI; + if (*p == '<') { + pri = 0; + while (isdigit(*++p)) + pri = 10 * pri + (*p - '0'); + if (*p == '>') + ++p; + } else { + /* kernel printf's come out on console */ + flags |= IGN_CONS; + } + if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) + pri = DEFSPRI; + q = lp; + while (*p != '\0' && (c = *p++) != '\n' && + q < &line[MAXLINE]) + *q++ = c; + *q = '\0'; + logmsg(pri, line, LocalHostName, flags); + } + return; +} + +time_t now; + +/* + * Log a message to the appropriate log files, users, etc. based on + * the priority. + */ + +void logmsg(pri, msg, from, flags) + int pri; + char *msg; + const char *from; + int flags; +{ + register struct filed *f; + int fac, prilev, lognum; + int msglen; + char *timestamp; + + dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg); + +#ifndef SYSV + omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); +#endif + + /* + * Check to see if msg looks non-standard. + */ + msglen = strlen(msg); + if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || + msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') + flags |= ADDDATE; + + (void) time(&now); + if (flags & ADDDATE) + timestamp = ctime(&now) + 4; + else { + timestamp = msg; + msg += 16; + msglen -= 16; + } + + /* extract facility and priority level */ + if (flags & MARK) + fac = LOG_NFACILITIES; + else + fac = LOG_FAC(pri); + prilev = LOG_PRI(pri); + + /* log the message to the particular outputs */ + if (!Initialized) { + f = &consfile; + f->f_file = open(ctty, O_WRONLY|O_NOCTTY); + + if (f->f_file >= 0) { + untty(); + fprintlog(f, (char *)from, flags, msg); + (void) close(f->f_file); + } +#ifndef SYSV + (void) sigsetmask(omask); +#endif + return; + } +#ifdef SYSV + for (lognum = 0; lognum <= nlogs; lognum++) { + f = &Files[lognum]; +#else + for (f = Files; f; f = f->f_next) { +#endif + + /* skip messages that are incorrect priority */ + if ( (f->f_pmask[fac] == TABLE_NOPRI) || \ + ((f->f_pmask[fac] & (1<f_type == F_CONSOLE && (flags & IGN_CONS)) + continue; + + /* don't output marks to recently written files */ + if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2) + continue; + + /* + * suppress duplicate lines to this file + */ + if ((flags & MARK) == 0 && msglen == f->f_prevlen && + !strcmp(msg, f->f_prevline) && + !strcmp(from, f->f_prevhost)) { + (void) strncpy(f->f_lasttime, timestamp, 15); + f->f_prevcount++; + dprintf("msg repeated %d times, %ld sec of %d.\n", + f->f_prevcount, now - f->f_time, + repeatinterval[f->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(f)) { + fprintlog(f, (char *)from, flags, (char *)NULL); + BACKOFF(f); + } + } else { + /* new line, save it */ + if (f->f_prevcount) + fprintlog(f, (char *)from, 0, (char *)NULL); + f->f_repeatcount = 0; + (void) strncpy(f->f_lasttime, timestamp, 15); + (void) strncpy(f->f_prevhost, from, + sizeof(f->f_prevhost)); + if (msglen < MAXSVLINE) { + f->f_prevlen = msglen; + f->f_prevpri = pri; + (void) strcpy(f->f_prevline, msg); + fprintlog(f, (char *)from, flags, (char *)NULL); + } else { + f->f_prevline[0] = 0; + f->f_prevlen = 0; + fprintlog(f, (char *)from, flags, msg); + } + } + } +#ifndef SYSV + (void) sigsetmask(omask); +#endif +} + +void fprintlog(f, from, flags, msg) + register struct filed *f; + char *from; + int flags; + char *msg; +{ + struct iovec iov[6]; + register struct iovec *v = iov; + register int l; + char line[MAXLINE + 1]; + char repbuf[80]; + time_t fwd_suspend; + struct hostent *hp; + + dprintf("Called fprintlog, "); + + v->iov_base = f->f_lasttime; + v->iov_len = 15; + v++; + v->iov_base = " "; + v->iov_len = 1; + v++; + v->iov_base = f->f_prevhost; + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = " "; + v->iov_len = 1; + v++; + if (msg) { + v->iov_base = msg; + v->iov_len = strlen(msg); + } else if (f->f_prevcount > 1) { + (void) sprintf(repbuf, "last message repeated %d times", + f->f_prevcount); + v->iov_base = repbuf; + v->iov_len = strlen(repbuf); + } else { + v->iov_base = f->f_prevline; + v->iov_len = f->f_prevlen; + } + v++; + + dprintf("logging to %s", TypeNames[f->f_type]); + + switch (f->f_type) { + case F_UNUSED: + f->f_time = now; + dprintf("\n"); + break; + + case F_FORW_SUSP: + fwd_suspend = time((time_t *) 0) - f->f_time; + if ( fwd_suspend >= INET_SUSPEND_TIME ) { + dprintf("\nForwarding suspension over, " \ + "retrying FORW "); + f->f_type = F_FORW; + goto f_forw; + } + else { + dprintf(" %s\n", f->f_un.f_forw.f_hname); + dprintf("Forwarding suspension not over, time " \ + "left: %d.\n", INET_SUSPEND_TIME - \ + fwd_suspend); + } + break; + + /* + * The trick is to wait some time, then retry to get the + * address. If that fails retry x times and then give up. + * + * You'll run into this problem mostly if the name server you + * need for resolving the address is on the same machine, but + * is started after syslogd. + */ + case F_FORW_UNKN: + dprintf(" %s\n", f->f_un.f_forw.f_hname); + fwd_suspend = time((time_t *) 0) - f->f_time; + if ( fwd_suspend >= INET_SUSPEND_TIME ) { + dprintf("Forwarding suspension to unknown over, retrying\n"); + if ( (hp = gethostbyname(f->f_un.f_forw.f_hname)) == NULL ) { + dprintf("Failure: %s\n", sys_h_errlist[h_errno]); + dprintf("Retries: %d\n", f->f_prevcount); + if ( --f->f_prevcount < 0 ) { + dprintf("Giving up.\n"); + f->f_type = F_UNUSED; + } + else + dprintf("Left retries: %d\n", f->f_prevcount); + } + else { + dprintf("%s found, resuming.\n", f->f_un.f_forw.f_hname); + bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length); + f->f_type = F_FORW; + goto f_forw; + } + } + else + dprintf("Forwarding suspension not over, time " \ + "left: %d\n", INET_SUSPEND_TIME - fwd_suspend); + break; + + case F_FORW: + /* + * Don't send any message to a remote host if it + * already comes from one. (we don't care 'bout who + * sent the message, we don't send it anyway) -Joey + */ + f_forw: + dprintf(" %s\n", f->f_un.f_forw.f_hname); + if ( strcmp(from, LocalHostName) && NoHops ) + dprintf("Not sending message to remote.\n"); + else { + f->f_time = now; + (void) sprintf(line, "<%d>%s", f->f_prevpri, \ + (char *) iov[4].iov_base); + strcat(line, "\n"); /* ASP */ + l = strlen(line); + if (l > MAXLINE) + l = MAXLINE; + if (sendto(finet, line, l, 0, \ + (struct sockaddr *) &f->f_un.f_forw.f_addr, + sizeof(f->f_un.f_forw.f_addr)) != l) { + int e = errno; + dprintf("INET sendto error: %d = %s.\n", + e, strerror(e)); + f->f_type = F_FORW_SUSP; + errno = e; + logerror("sendto"); + } + } + break; + + case F_CONSOLE: + f->f_time = now; +#ifdef UNIXPC + if (1) { +#else + if (flags & IGN_CONS) { +#endif + dprintf(" (ignored).\n"); + break; + } + /* FALLTHROUGH */ + + case F_TTY: + case F_FILE: + f->f_time = now; + dprintf(" %s\n", f->f_un.f_fname); + if (f->f_type != F_FILE) { + v->iov_base = "\r\n"; + v->iov_len = 2; + } else { + v->iov_base = "\n"; + v->iov_len = 1; + } + again: + if (writev(f->f_file, iov, 6) < 0) { + int e = errno; + (void) close(f->f_file); + /* + * Check for EBADF on TTY's due to vhangup() XXX + */ + if (e == EBADF && f->f_type != F_FILE) { + f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND|O_NOCTTY); + if (f->f_file < 0) { + f->f_type = F_UNUSED; + logerror(f->f_un.f_fname); + } else { + untty(); + goto again; + } + } else { + f->f_type = F_UNUSED; + errno = e; + logerror(f->f_un.f_fname); + } + } else if (f->f_flags & SYNC_FILE) + (void) fsync(f->f_file); + break; + + case F_USERS: + case F_WALL: + f->f_time = now; + dprintf("\n"); + v->iov_base = "\r\n"; + v->iov_len = 2; + wallmsg(f, iov); + break; + } /* switch */ + if (f->f_type != F_FORW_UNKN) + f->f_prevcount = 0; + return; +} + +jmp_buf ttybuf; + +void endtty() +{ + longjmp(ttybuf, 1); +} + +/* + * WALLMSG -- Write a message to the world at large + * + * Write the specified message to either the entire + * world, or a list of approved users. + */ + +void wallmsg(f, iov) + register struct filed *f; + struct iovec *iov; +{ + char p[6 + UNAMESZ]; + register int i; + int ttyf, len; + FILE *uf; + static int reenter = 0; + struct utmp ut; + char greetings[200]; + + if (reenter++) + return; + + /* open the user login file */ + if ((uf = fopen(UTMP_FILE, "r")) == NULL) { + logerror(UTMP_FILE); + reenter = 0; + return; + } + + /* + * Might as well fork instead of using nonblocking I/O + * and doing notty(). + */ + if (fork() == 0) { + (void) signal(SIGTERM, SIG_DFL); + (void) alarm(0); + (void) signal(SIGALRM, endtty); +#ifndef SYSV + (void) signal(SIGTTOU, SIG_IGN); + (void) sigsetmask(0); +#endif + (void) sprintf(greetings, + "\r\n\7Message from syslogd@%s at %.24s ...\r\n", + (char *) iov[2].iov_base, ctime(&now)); + len = strlen(greetings); + + /* scan the user login file */ + while (fread((char *) &ut, sizeof(ut), 1, uf) == 1) { + /* is this slot used? */ + if (ut.ut_name[0] == '\0') + continue; + if (ut.ut_type == LOGIN_PROCESS) + continue; + if (!(strcmp (ut.ut_name,"LOGIN"))) /* paranoia */ + continue; + + /* should we send the message to this user? */ + if (f->f_type == F_USERS) { + for (i = 0; i < MAXUNAMES; i++) { + if (!f->f_un.f_uname[i][0]) { + i = MAXUNAMES; + break; + } + if (strncmp(f->f_un.f_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 (f->f_type == F_WALL) { + iov[0].iov_base = greetings; + iov[0].iov_len = len; + iov[1].iov_len = 0; + } + if (setjmp(ttybuf) == 0) { + (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) writev(ttyf, iov, 6); + close(ttyf); + ttyf = -1; + } + } + (void) alarm(0); + } + exit(0); + } + /* close the user login file */ + (void) fclose(uf); + reenter = 0; +} + +void reapchild() +{ +#if defined(SYSV) && !defined(linux) + (void) signal(SIGCHLD, reapchild); /* reset signal handler -ASP */ + wait ((int *)0); +#else + union wait status; + + while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) + ; +#endif +#ifdef linux + (void) signal(SIGCHLD, reapchild); /* reset signal handler -ASP */ +#endif +} + +/* + * Return a printable representation of a host address. + */ +const char *cvthname(f) + struct sockaddr_in *f; +{ + struct hostent *hp; + register char *p; + int count; + + if (f->sin_family != AF_INET) { + dprintf("Malformed from address.\n"); + return ("???"); + } + hp = gethostbyaddr((char *) &f->sin_addr, sizeof(struct in_addr), \ + f->sin_family); + if (hp == 0) { + dprintf("Host name for your address (%s) unknown.\n", + inet_ntoa(f->sin_addr)); + return (inet_ntoa(f->sin_addr)); + } + /* + * Convert to lower case, just like LocalDomain above + */ + for (p = (char *)hp->h_name; *p ; p++) + if (isupper(*p)) + *p = tolower(*p); + + /* + * Notice that the string still contains the fqdn, but your + * hostname and domain are separated by a '\0'. + */ + if ((p = index(hp->h_name, '.'))) { + if (strcmp(p + 1, LocalDomain) == 0) { + *p = '\0'; + return (hp->h_name); + } else { + if (StripDomains) { + count=0; + while (StripDomains[count]) { + if (strcmp(p + 1, StripDomains[count]) == 0) { + *p = '\0'; + return (hp->h_name); + } + count++; + } + } + if (LocalHosts) { + count=0; + while (LocalHosts[count]) { + if (!strcmp(hp->h_name, LocalHosts[count])) { + *p = '\0'; + return (hp->h_name); + } + count++; + } + } + } + } + + return (hp->h_name); +} + +void domark() +{ + register struct filed *f; +#ifdef SYSV + int lognum; +#endif + + now = time(0); + MarkSeq += TIMERINTVL; + if (MarkSeq >= MarkInterval) { + logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK); + MarkSeq = 0; + } + +#ifdef SYSV + for (lognum = 0; lognum <= nlogs; lognum++) { + f = &Files[lognum]; +#else + for (f = Files; f; f = f->f_next) { +#endif + if (f->f_prevcount && now >= REPEATTIME(f)) { + dprintf("flush %s: repeated %d times, %d sec.\n", + TypeNames[f->f_type], f->f_prevcount, + repeatinterval[f->f_repeatcount]); + fprintlog(f, LocalHostName, 0, (char *)NULL); + BACKOFF(f); + } + } + (void) signal(SIGALRM, domark); + (void) alarm(TIMERINTVL); +} + +void debug_switch() + +{ + dprintf("Switching debugging_on to %s\n", (debugging_on == 0) ? "true" : "false"); + debugging_on = (debugging_on == 0) ? 1 : 0; + signal(SIGUSR1, debug_switch); +} + + +/* + * Print syslogd errors some place. + */ +void logerror(type) + char *type; +{ + char buf[100]; + + dprintf("Called loggerr, msg: %s\n", type); + + if (errno == 0) + (void) sprintf(buf, "syslogd: %s", type); + else if ((unsigned) errno > sys_nerr) + (void) sprintf(buf, "syslogd: %s: error %d", type, errno); + else + (void) sprintf(buf, "syslogd: %s: %s", type, sys_errlist[errno]); + errno = 0; + logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); + return; +} + +void die(sig) + + int sig; + +{ + register struct filed *f; + char buf[100]; + int lognum; + + for (lognum = 0; lognum <= nlogs; lognum++) { + f = &Files[lognum]; + /* flush any pending output */ + if (f->f_prevcount) + fprintlog(f, LocalHostName, 0, (char *)NULL); + } + + if (sig) { + dprintf("syslogd: exiting on signal %d\n", sig); + (void) sprintf(buf, "exiting on signal %d", sig); + errno = 0; + logerror(buf); + } + + /* Close the sockets. */ + close(funix); + close(inetm); + + /* Clean-up files. */ + (void) unlink(LogName); + (void) remove_pid(PidFile); + exit(0); +} + +/* + * INIT -- Initialize syslogd from configuration table + */ + +void init() +{ + register int i, lognum; + register FILE *cf; + register struct filed *f, **nextp = (struct filed **) 0; + register char *p; + char cline[BUFSIZ]; + + dprintf("Called init.\n"); + + /* + * Close all open log files. + */ + Initialized = 0; + if ( nlogs > -1 ) + { + dprintf("Initializing log structures.\n"); + nlogs = -1; + free((void *) Files); + Files = (struct filed *) 0; + } + +#ifdef SYSV + for (lognum = 0; lognum <= nlogs; lognum++ ) { + f = &Files[lognum]; +#else + for (f = Files; f != NULL; f = next) { +#endif + /* flush any pending output */ + if (f->f_prevcount) + fprintlog(f, LocalHostName, 0, (char *)NULL); + + switch (f->f_type) { + case F_FILE: + case F_TTY: + case F_CONSOLE: + (void) close(f->f_file); + break; + } +#ifdef SYSV + f->f_type = F_UNUSED; /* clear entry - ASP */ + } +#else + next = f->f_next; + free((char *) f); + } + Files = NULL; + nextp = &OBFiles; +#endif + + /* open the configuration file */ + if ((cf = fopen(ConfFile, "r")) == NULL) { + dprintf("cannot open %s.\n", ConfFile); +#ifdef SYSV + cfline("*.ERR\t" _PATH_CONSOLE, *nextp); +#else + *nextp = (struct filed *)calloc(1, sizeof(*f)); + cfline("*.ERR\t" _PATH_CONSOLE, *nextp); + (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)) /* ASP */ + cfline("*.PANIC\t*", (*nextp)->f_next); +#endif + Initialized = 1; + return; + } + + /* + * Foreach line in the conf table, open that file. + */ +#ifdef SYSV + lognum = 0; +#else + f = NULL; +#endif + while (fgets(cline, sizeof(cline), cf) != NULL) { + /* + * check for end-of-section, comments, strip off trailing + * spaces and newline character. + */ + for (p = cline; isspace(*p); ++p); + if (*p == '\0' || *p == '#') + continue; + for (p = index(cline, '\0'); isspace(*--p);); + *++p = '\0'; +#ifndef SYSV + f = (struct filed *)calloc(1, sizeof(*f)); + *nextp = f; + nextp = &f->f_next; +#endif + allocate_log(); + f = &Files[lognum++]; + cfline(cline, f); + } + + /* close the configuration file */ + (void) fclose(cf); + + Initialized = 1; + + if ( Debug ) { +#ifdef SYSV + for (lognum = 0; lognum <= nlogs; lognum++) { + f = &Files[lognum]; + if (f->f_type != F_UNUSED) { + printf ("%2d: ", lognum); +#else + for (f = Files; f; f = f->f_next) { + if (f->f_type != F_UNUSED) { +#endif + for (i = 0; i <= LOG_NFACILITIES; i++) + if (f->f_pmask[i] == TABLE_NOPRI) + printf(" X "); + else + printf("%2X ", f->f_pmask[i]); + printf("%s: ", TypeNames[f->f_type]); + switch (f->f_type) { + case F_FILE: + case F_TTY: + case F_CONSOLE: + printf("%s", f->f_un.f_fname); + break; + + case F_FORW: + case F_FORW_SUSP: + case F_FORW_UNKN: + printf("%s", f->f_un.f_forw.f_hname); + break; + + case F_USERS: + for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++) + printf("%s, ", f->f_un.f_uname[i]); + break; + } + printf("\n"); + } + } + } + + if ( AcceptRemote ) + logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "-" PATCHLEVEL \ + ": restart (remote reception)." , LocalHostName, \ + ADDDATE); + else + logmsg(LOG_SYSLOG|LOG_INFO, "syslogd " VERSION "-" PATCHLEVEL \ + ": restart." , LocalHostName, ADDDATE); + (void) signal(SIGHUP, sighup_handler); + dprintf("syslogd: restarted.\n"); +} + +/* + * Crack a configuration file line + */ + +void cfline(line, f) + char *line; + register struct filed *f; +{ + register char *p; + register char *q; + register int i, i2; + char *bp; + int pri; + int singlpri = 0; + int ignorepri = 0; + int syncfile; + struct hostent *hp; + char buf[MAXLINE]; + + dprintf("cfline(%s)\n", line); + + errno = 0; /* keep sys_errlist stuff out of logerror messages */ + + /* clear out file entry */ +#ifndef SYSV + bzero((char *) f, sizeof(*f)); +#endif + for (i = 0; i <= LOG_NFACILITIES; i++) { + f->f_pmask[i] = TABLE_NOPRI; + f->f_flags = 0; + } + + /* scan through the list of selectors */ + for (p = line; *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 && !index("\t ,;", *q); ) + *bp++ = *q++; + *bp = '\0'; + + /* skip cruft */ + while (index(",;", *q)) + q++; + + /* decode priority name */ + if ( *buf == '!' ) { + ignorepri = 1; + for (bp=buf; *(bp+1); bp++) + *bp=*(bp+1); + *bp='\0'; + } + if ( *buf == '=' ) + { + singlpri = 1; + pri = decode(&buf[1], PriNames); + } + else { + singlpri = 0; + pri = decode(buf, PriNames); + } + + if (pri < 0) { + char xbuf[200]; + + (void) sprintf(xbuf, "unknown priority name \"%s\"", buf); + logerror(xbuf); + return; + } + + /* scan facilities */ + while (*p && !index("\t .;", *p)) { + for (bp = buf; *p && !index("\t ,;.", *p); ) + *bp++ = *p++; + *bp = '\0'; + if (*buf == '*') { + for (i = 0; i < LOG_NFACILITIES; i++) { + if ( pri == INTERNAL_NOPRI ) { + if ( ignorepri ) + f->f_pmask[i] = TABLE_ALLPRI; + else + f->f_pmask[i] = TABLE_NOPRI; + } + else if ( singlpri ) { + if ( ignorepri ) + f->f_pmask[i] &= ~(1<f_pmask[i] |= (1<f_pmask[i] = TABLE_NOPRI; + else + f->f_pmask[i] = TABLE_ALLPRI; + } + else + { + if ( ignorepri ) + for (i2= 0; i2 <= pri; ++i2) + f->f_pmask[i] &= ~(1<f_pmask[i] |= (1<f_pmask[i >> 3] = TABLE_ALLPRI; + else + f->f_pmask[i >> 3] = TABLE_NOPRI; + } else if ( singlpri ) { + if ( ignorepri ) + f->f_pmask[i >> 3] &= ~(1<f_pmask[i >> 3] |= (1<f_pmask[i >> 3] = TABLE_NOPRI; + else + f->f_pmask[i >> 3] = TABLE_ALLPRI; + } else { + if ( ignorepri ) + for (i2= 0; i2 <= pri; ++i2) + f->f_pmask[i >> 3] &= ~(1<f_pmask[i >> 3] |= (1<f_un.f_forw.f_hname, ++p); + dprintf("forwarding host: %s\n", p); /*ASP*/ + if ( (hp = gethostbyname(p)) == NULL ) { + f->f_type = F_FORW_UNKN; + f->f_prevcount = INET_RETRY_MAX; + } else { + f->f_type = F_FORW; + } + bzero((char *) &f->f_un.f_forw.f_addr, + sizeof(f->f_un.f_forw.f_addr)); + f->f_un.f_forw.f_addr.sin_family = AF_INET; + f->f_un.f_forw.f_addr.sin_port = LogPort; + if ( f->f_type == F_FORW ) + bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length); + /* + * 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. + */ +#endif + break; + + case '|': + case '/': + (void) strcpy(f->f_un.f_fname, p); + dprintf ("filename: %s\n", p); /*ASP*/ + if (syncfile) + f->f_flags |= SYNC_FILE; + if ( *p == '|' ) + f->f_file = open(++p, O_RDWR); + else + f->f_file = open(p, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY, + 0644); + + if ( f->f_file < 0 ){ + f->f_file = F_UNUSED; + dprintf("Error opening log file: %s\n", p); + logerror(p); + break; + } + if (isatty(f->f_file)) { + f->f_type = F_TTY; + untty(); + } + else + f->f_type = F_FILE; + if (strcmp(p, ctty) == 0) + f->f_type = F_CONSOLE; + break; + + case '*': + dprintf ("write-all\n"); + f->f_type = F_WALL; + break; + + default: + dprintf ("users: %s\n", p); /* ASP */ + for (i = 0; i < MAXUNAMES && *p; i++) { + for (q = p; *q && *q != ','; ) + q++; + (void) strncpy(f->f_un.f_uname[i], p, UNAMESZ); + if ((q - p) > UNAMESZ) + f->f_un.f_uname[i][UNAMESZ] = '\0'; + else + f->f_un.f_uname[i][q - p] = '\0'; + while (*q == ',' || *q == ' ') + q++; + p = q; + } + f->f_type = F_USERS; + break; + } + return; +} + + +/* + * Decode a symbolic name to a numeric value + */ + +int decode(name, codetab) + char *name; + struct code *codetab; +{ + register struct code *c; + register char *p; + char buf[40]; + + dprintf ("symbolic name: %s", name); + if (isdigit(*name)) + { + dprintf ("\n"); + return (atoi(name)); + } + (void) strcpy(buf, name); + for (p = buf; *p; p++) + if (isupper(*p)) + *p = tolower(*p); + for (c = codetab; c->c_name; c++) + if (!strcmp(buf, c->c_name)) + { + dprintf (" ==> %d\n", c->c_val); + return (c->c_val); + } + return (-1); +} + +static void dprintf(char *fmt, ...) + +{ + va_list ap; + + if ( !(Debug && debugging_on) ) + return; + + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); + + fflush(stdout); + return; +} + + +/* + * The following function is responsible for allocating/reallocating the + * array which holds the structures which define the logging outputs. + */ +static void allocate_log() + +{ + dprintf("Called allocate_log, nlogs = %d.\n", nlogs); + + /* + * Decide whether the array needs to be initialized or needs to + * grow. + */ + if ( nlogs == -1 ) + { + Files = (struct filed *) malloc(sizeof(struct filed)); + if ( Files == (void *) 0 ) + { + dprintf("Cannot initialize log structure."); + logerror("Cannot initialize log structure."); + return; + } + } + else + { + /* Re-allocate the array. */ + Files = (struct filed *) realloc(Files, (nlogs+2) * \ + sizeof(struct filed)); + if ( Files == (struct filed *) 0 ) + { + dprintf("Cannot grow log structure."); + logerror("Cannot grow log structure."); + return; + } + } + + /* + * Initialize the array element, bump the number of elements in the + * the array and return. + */ + ++nlogs; + memset(&Files[nlogs], '\0', sizeof(struct filed)); + 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; +} diff --git a/version.h b/version.h new file mode 100644 index 0000000..6797014 --- /dev/null +++ b/version.h @@ -0,0 +1,2 @@ +#define VERSION "1.3" +#define PATCHLEVEL "0"