commit 7834544c60a0a3f5a50c2c6e73d7d8741cbfd28d Author: Joey Schulze Date: Mon Jun 2 17:21:41 1997 +0000 Import of bare source for 1.3 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"