summaryrefslogtreecommitdiffstats
path: root/klogd.c
diff options
context:
space:
mode:
Diffstat (limited to 'klogd.c')
-rw-r--r--klogd.c1201
1 files changed, 0 insertions, 1201 deletions
diff --git a/klogd.c b/klogd.c
deleted file mode 100644
index e2e9df21..00000000
--- a/klogd.c
+++ /dev/null
@@ -1,1201 +0,0 @@
-/*
- klogd.c - main program for Linux kernel log daemon.
- Copyright (c) 1995 Dr. G.W. Wettstein <greg@wind.rmcc.com>
- *
- * This file is part of rsyslog.
- *
- * Rsyslog is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Rsyslog is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
-*/
-#include "config.h"
-
-#ifdef FEATURE_KLOGD
-/*
- * Steve Lord (lord@cray.com) 7th Nov 92
- *
- * Modified to check for kernel info by Dr. G.W. Wettstein 02/17/93.
- *
- * Fri Mar 12 16:53:56 CST 1993: Dr. Wettstein
- * Modified LogLine to use a newline as the line separator in
- * the kernel message buffer.
- *
- * Added debugging code to dump the contents of the kernel message
- * buffer at the start of the LogLine function.
- *
- * Thu Jul 29 11:40:32 CDT 1993: Dr. Wettstein
- * Added syscalls to turn off logging of kernel messages to the
- * console when klogd becomes responsible for kernel messages.
- *
- * klogd now catches SIGTERM and SIGKILL signals. Receipt of these
- * signals cases the clean_up function to be called which shuts down
- * kernel logging and re-enables logging of messages to the console.
- *
- * Sat Dec 11 11:54:22 CST 1993: Dr. Wettstein
- * Added fixes to allow compilation with no complaints with -Wall.
- *
- * When the daemon catches a fatal signal (SIGTERM, SIGKILL) a
- * message is output to the logfile advising that the daemon is
- * going to terminate.
- *
- * Thu Jan 6 11:54:10 CST 1994: Dr. Wettstein
- * Major re-write/re-organization of the code.
- *
- * Klogd now assigns kernel messages to priority levels when output
- * to the syslog facility is requested. The priority level is
- * determined by decoding the prioritization sequence which is
- * tagged onto the start of the kernel messages.
- *
- * Added the following program options: -f arg -c arg -s -o -d
- *
- * The -f switch can be used to specify that output should
- * be written to the named file.
- *
- * The -c switch is used to specify the level of kernel
- * messages which are to be directed to the console.
- *
- * The -s switch causes the program to use the syscall
- * interface to the kernel message facility. This can be
- * used to override the presence of the /proc filesystem.
- *
- * The -o switch causes the program to operate in 'one-shot'
- * mode. A single call will be made to read the complete
- * kernel buffer. The contents of the buffer will be
- * output and the program will terminate.
- *
- * The -d switch causes 'debug' mode to be activated. This
- * will cause the daemon to generate LOTS of output to stderr.
- *
- * The buffer decomposition function (LogLine) was re-written to
- * squash a bug which was causing only partial kernel messages to
- * be written to the syslog facility.
- *
- * The signal handling code was modified to properly differentiate
- * between the STOP and TSTP signals.
- *
- * Added pid saving when the daemon detaches into the background. Thank
- * you to Juha Virtanen (jiivee@hut.fi) for providing this patch.
- *
- * Mon Feb 6 07:31:29 CST 1995: Dr. Wettstein
- * Significant re-organization of the signal handling code. The
- * signal handlers now only set variables. Not earth shaking by any
- * means but aesthetically pleasing to the code purists in the group.
- *
- * Patch to make things more compliant with the file system standards.
- * Thanks to Chris Metcalf for prompting this helpful change.
- *
- * The routines responsible for reading the kernel log sources now
- * initialize the buffers before reading. I think that this will
- * solve problems with non-terminated kernel messages producing
- * output of the form: new old old old
- *
- * This may also help influence the occassional reports of klogd
- * failing under significant load. I think that the jury may still
- * be out on this one though. My thanks to Joerg Ahrens for initially
- * tipping me off to the source of this problem. Also thanks to
- * Michael O'Reilly for tipping me off to the best fix for this problem.
- * And last but not least Mark Lord for prompting me to try this as
- * a means of attacking the stability problem.
- *
- * Specifying a - as the arguement to the -f switch will cause output
- * to be directed to stdout rather than a filename of -. Thanks to
- * Randy Appleton for a patch which prompted me to do this.
- *
- * Wed Feb 22 15:37:37 CST 1995: Dr. Wettstein
- * Added version information to logging startup messages.
- *
- * Wed Jul 26 18:57:23 MET DST 1995: Martin Schulze
- * Added an commandline argument "-n" to avoid forking. This obsoletes
- * the compiler define NO_FORK. It's more useful to have this as an
- * argument as there are many binary versions and one doesn't need to
- * recompile the daemon.
- *
- * Thu Aug 10 19:01:08 MET DST 1995: Martin Schulze
- * Added my pidfile.[ch] to it to perform a better handling with pidfiles.
- * Now both, syslogd and klogd, can only be started once. They check the
- * pidfile.
- *
- * Fri Nov 17 15:05:43 CST 1995: Dr. Wettstein
- * Added support for kernel address translation. This required moving
- * some definitions and includes to the new klogd.h file. Some small
- * code cleanups and modifications.
- *
- * Mon Nov 20 10:03:39 MET 1995
- * Added -v option to print the version and exit.
- *
- * Thu Jan 18 11:19:46 CST 1996: Dr. Wettstein
- * Added suggested patches from beta-testers. These address two
- * two problems. The first is segmentation faults which occur with
- * the ELF libraries. This was caused by passing a null pointer to
- * the strcmp function.
- *
- * Added a second patch to remove the pidfile as part of the
- * termination cleanup sequence. This minimizes the potential for
- * conflicting pidfiles causing immediate termination at boot time.
- *
- * Wed Aug 21 09:13:03 CDT 1996: Dr. Wettstein
- * Added ability to reload static symbols and kernel module symbols
- * under control of SIGUSR1 and SIGUSR2 signals.
- *
- * Added -p switch to select 'paranoid' behavior with respect to the
- * loading of kernel module symbols.
- *
- * Informative line now printed whenever a state change occurs due
- * to signal reception by the daemon.
- *
- * Added the -i and -I command line switches to signal the currently
- * executing daemon.
- *
- * Tue Nov 19 10:15:36 PST 1996: Leland Olds <olds@eskimo.com>
- * Corrected vulnerability to buffer overruns by rewriting LogLine
- * routine. Obscenely long kernel messages will now be broken up
- * into lines no longer than LOG_LINE_LENGTH.
- *
- * The last version of LogLine was vulnerable to buffer overruns:
- * - Kernel messages longer than LOG_LINE_LENGTH caused a buffer
- * overrun.
- * - If a line was determined to be shorter than LOG_LINE_LENGTH,
- * the routine "ExpandKadds" could cause the line grow by
- * an unknown amount and overrun a buffer.
- * I turned these routines into a little parsing state machine that
- * should not have these problems.
- *
- * Sun Jun 15 16:23:29 MET DST 1997: Michael Alan Dorman
- * Some more glibc patches made by <mdorman@debian.org>.
- *
- * Thu Aug 21 12:11:27 MET DST 1997: Martin Schulze <joey@infodrom.north.de>
- * Fixed little mistake which prevented klogd from accepting a
- * console log
- *
- * Fri Jan 9 00:39:52 CET 1998: Martin Schulze <joey@infodrom.north.de>
- * Changed the behaviour of klogd when receiving a terminate
- * signal. Now the program terminates immediately instead of
- * completing the receipt of a kernel message, i.e the read()
- * call. The old behaveiour could result in klogd being
- * recognized as being undead, because it'll only die after a
- * message has been received.
- *
- * Fri Jan 9 11:03:48 CET 1998: Martin Schulze <joey@infodrom.north.de>
- * Corrected some code that caused klogd to dump core when
- * receiving messages containing '%', some of them exist in
- * 2.1.78. Thanks to Chu-yeon Park <kokids@doit.ajou.ac.kr> for
- * informing me.
- *
- * Fri Jan 9 23:38:19 CET 1998: Florian La Roche <florian@knorke.saar.de>
- * Added -x switch to omit EIP translation and System.map evaluation.
- *
- * Sun Jan 25 20:47:46 CET 1998: Martin Schulze <joey@infodrom.north.de>
- * As the bug covering the %'s introduced a problem with
- * unevaluated priorities I've worked out a real fix that strips
- * %'s to an even number which is harmless for printf.
- *
- * Sat Oct 10 20:01:48 CEST 1998: Martin Schulze <joey@infodrom.north.de>
- * Added support for TESTING define which will turn klogd into
- * stdio-mode used for debugging.
- *
- * Mon Apr 13 18:18:45 CEST 1998: Martin Schulze <joey@infodrom.north.de>
- * Modified System.map read function to try all possible map
- * files until a file with matching version is found. Added support for
- * Debian release.
- *
- * Mon Oct 12 13:01:27 MET DST 1998: Martin Schulze <joey@infodrom.north.de>
- * Used unsigned long and strtoul() to resolve kernel oops symbols.
- *
- * Sun Jan 3 18:38:03 CET 1999: Martin Schulze <joey@infodrom.north.de>
- * Shortened LOG_LINE_LENGTH in order to get long lines splitted
- * up earlier and syslogd has a better chance concatenating them
- * together again.
- *
- * Sat Aug 21 12:27:02 CEST 1999: Martin Schulze <joey@infodrom.north.de>
- * Skip newline when reading in messages.
- *
- * Tue Sep 12 22:14:33 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
- * Don't feed a buffer directly to a printf-type routine, use
- * "%s" as format string instead. Thanks to Jouko Pynnönen
- * <jouko@solutions.fi> for pointing this out.
- *
- * Tue Sep 12 22:44:57 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
- * Commandline option `-2': When symbols are expanded, print the
- * line twice. Once with addresses converted to symbols, once with the
- * raw text. Allows external programs such as ksymoops do their own
- * processing on the original data. Thanks to Keith Owens
- * <kaos@ocs.com.au> for the patch.
- *
- * Mon Sep 18 09:32:27 CEST 2000: Martin Schulze <joey@infodrom.ffis.de>
- * Added patch to fix priority decoding after moving kernel
- * messgages into "%s". Thanks to Solar Designer
- * <solar@false.com> for the patch.
- *
- * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de>
- * Stop LogLine() from being called with wrong argument when a
- * former calculation failed already. Thanks to Thomas Roessler
- * <roessler@does-not-exist.org> for providing a patch.
- *
- * Ignore zero bytes, no busy loop is entered anymore. Several
- * people have submitted patches: Troels Walsted Hansen
- * <troels@thule.no>, Wolfgang Oertl <Wolfgang.Oertl@uibk.ac.at>
- * and Thomas Roessler.
- */
-
-
-/* Includes. */
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#if !defined(__GLIBC__)
-#include <linux/time.h>
-#endif /* __GLIBC__ */
-#include <stdarg.h>
-#include <paths.h>
-#include <stdlib.h>
-#include "klogd.h"
-#include "ksyms.h"
-#ifndef TESTING
-#include "pidfile.h"
-#endif
-
-#define __LIBRARY__
-#include <linux/unistd.h>
-#if !defined(__GLIBC__)
-# define __NR_ksyslog __NR_syslog
-_syscall3(int,ksyslog,int, type, char *, buf, int, len);
-#else
-#include <sys/klog.h>
-#define ksyslog klogctl
-#endif
-extern int writeSyslogV(int pri, const char *szFmt, va_list va);
-extern int writeSyslog(int iPri, const char *szFmt, ...);
-
-#ifndef _PATH_KLOG
-#define _PATH_KLOG "/proc/kmsg"
-#endif
-
-#define LOG_BUFFER_SIZE 4096
-#define LOG_LINE_LENGTH 1000
-
-#ifndef TESTING
-#if defined(FSSTND)
-static char *PidFile = _PATH_VARRUN "rklogd.pid";
-#else
-static char *PidFile = "/etc/rklogd.pid";
-#endif
-#endif
-
-static int kmsg,
- change_state = 0,
- terminate = 0,
- caught_TSTP = 0,
- reload_symbols = 0,
- console_log_level = -1;
-
-static int use_syscall = 0,
- one_shot = 0,
- symbol_lookup = 1,
- no_fork = 0; /* don't fork - don't run in daemon mode */
-
-static char *symfile = (char *) 0,
- log_buffer[LOG_BUFFER_SIZE];
-
-static FILE *output_file = (FILE *) 0;
-
-static enum LOGSRC {none, proc, kernel} logsrc;
-
-int debugging = 0;
-int symbols_twice = 0;
-
-
-/* Function prototypes. */
-extern int ksyslog(int type, char *buf, int len);
-static void CloseLogSrc(void);
-extern void restart(int sig);
-extern void stop_logging(int sig);
-extern void stop_daemon(int sig);
-extern void reload_daemon(int sig);
-static void Terminate(void);
-static void SignalDaemon(int);
-static void ReloadSymbols(void);
-static void ChangeLogging(void);
-static enum LOGSRC GetKernelLogSrc(void);
-static void LogLine(char *ptr, int len);
-static void LogKernelLine(void);
-static void LogProcLine(void);
-extern int main(int argc, char *argv[]);
-
-
-extern void Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3)));
-extern void Syslog(int priority, char *fmt, ...)
-{
- va_list ap;
- char *argl;
-
- if(debugging)
- {
- fputs("Logging line:\n", stderr);
- fprintf(stderr, "\tLine: %s\n", fmt);
- fprintf(stderr, "\tPriority: %d\n", priority);
- }
-
- /* Handle output to a file. */
- if ( output_file != (FILE *) 0 ) {
- va_start(ap, fmt);
- vfprintf(output_file, fmt, ap);
- va_end(ap);
- fputc('\n', output_file);
- fflush(output_file);
- if (!one_shot)
- fsync(fileno(output_file));
- return;
- }
-
- /* Output using syslog. */
- if (!strcmp(fmt, "%s")) {
- va_start(ap, fmt);
- argl = va_arg(ap, char *);
- if (argl[0] == '<' && argl[1] && argl[2] == '>') {
- switch ( argl[1] )
- {
- case '0':
- priority = LOG_EMERG;
- break;
- case '1':
- priority = LOG_ALERT;
- break;
- case '2':
- priority = LOG_CRIT;
- break;
- case '3':
- priority = LOG_ERR;
- break;
- case '4':
- priority = LOG_WARNING;
- break;
- case '5':
- priority = LOG_NOTICE;
- break;
- case '6':
- priority = LOG_INFO;
- break;
- case '7':
- default:
- priority = LOG_DEBUG;
- }
- argl += 3;
- }
- writeSyslog(priority, fmt, argl);
- va_end(ap);
-#ifdef TESTING
- putchar('\n');
-#endif
- return;
- }
-
- va_start(ap, fmt);
- writeSyslogV(priority, fmt, ap);
- va_end(ap);
-#ifdef TESTING
- printf ("\n");
-#endif
-
- return;
-}
-
-
-static void CloseLogSrc(void)
-{
- /* Turn on logging of messages to console, but only if we had the -c
- * option -- rgerhards, 2007-08-01
- */
- if (console_log_level != -1)
- ksyslog(7, NULL, 0);
-
- /* Shutdown the log sources. */
- switch ( logsrc )
- {
- case kernel:
- ksyslog(0, 0, 0);
- Syslog(LOG_INFO, "Kernel logging (ksyslog) stopped.");
- break;
- case proc:
- close(kmsg);
- Syslog(LOG_INFO, "Kernel logging (proc) stopped.");
- break;
- case none:
- break;
- }
-
- if ( output_file != (FILE *) 0 )
- fflush(output_file);
- return;
-}
-
-
-void restart(int __attribute__((unused)) sig)
-{
- change_state = 1;
- caught_TSTP = 0;
- return;
-}
-
-
-void stop_logging(int __attribute__((unused)) sig)
-{
- change_state = 1;
- caught_TSTP = 1;
- return;
-}
-
-
-void stop_daemon(int __attribute__((unused)) sig)
-{
- change_state = 1;
- terminate = 1;
- return;
-}
-
-
-void reload_daemon(int sig)
-{
- change_state = 1;
- reload_symbols = 1;
-
- if ( sig == SIGUSR2 )
- {
- ++reload_symbols;
- }
-
- return;
-}
-
-
-static void Terminate(void)
-{
- CloseLogSrc();
- Syslog(LOG_INFO, "Kernel log daemon terminating.");
- sleep(1);
- if ( output_file != (FILE *) 0 )
- fclose(output_file);
- closelog();
-#ifndef TESTING
- (void) remove_pid(PidFile);
-#endif
- exit(1);
-}
-
-static void SignalDaemon(int sig)
-{
-#ifndef TESTING
- auto int pid = check_pid(PidFile);
-
- kill(pid, sig);
-#else
- kill(getpid(), sig);
-#endif
- return;
-}
-
-
-static void ReloadSymbols(void)
-{
- if (symbol_lookup) {
- if ( reload_symbols > 1 )
- InitKsyms(symfile);
- InitMsyms();
- }
- reload_symbols = change_state = 0;
- return;
-}
-
-
-static void ChangeLogging(void)
-{
- /* Terminate kernel logging. */
- if ( terminate == 1 )
- Terminate();
-
- /* Indicate that something is happening. */
- Syslog(LOG_INFO, "rklogd %s, ---------- state change ----------\n", \
- VERSION);
-
- /* Reload symbols. */
- if ( reload_symbols > 0 )
- {
- ReloadSymbols();
- return;
- }
-
- /* Stop kernel logging. */
- if ( caught_TSTP == 1 )
- {
- CloseLogSrc();
- logsrc = none;
- change_state = 0;
- return;
- }
-
- /*
- * The rest of this function is responsible for restarting
- * kernel logging after it was stopped.
- *
- * In the following section we make a decision based on the
- * kernel log state as to what is causing us to restart. Somewhat
- * groady but it keeps us from creating another static variable.
- */
- if ( logsrc != none )
- {
- Syslog(LOG_INFO, "Kernel logging re-started after SIGSTOP.");
- change_state = 0;
- return;
- }
-
- /* Restart logging. */
- logsrc = GetKernelLogSrc();
- change_state = 0;
- return;
-}
-
-
-static enum LOGSRC GetKernelLogSrc(void)
-{
- auto struct stat sb;
-
- /* Set level of kernel console messaging.. */
- if ( (console_log_level != -1) &&
- (ksyslog(8, NULL, console_log_level) < 0) &&
- (errno == EINVAL) )
- {
- /*
- * An invalid arguement error probably indicates that
- * a pre-0.14 kernel is being run. At this point we
- * issue an error message and simply shut-off console
- * logging completely.
- */
- Syslog(LOG_WARNING, "Cannot set console log level - disabling "
- "console output.");
- }
-
- /*
- * First do a stat to determine whether or not the proc based
- * file system is available to get kernel messages from.
- */
- if ( use_syscall ||
- ((stat(_PATH_KLOG, &sb) < 0) && (errno == ENOENT)) )
- {
- /* Initialize kernel logging. */
- ksyslog(1, NULL, 0);
-#ifdef DEBRELEASE
- Syslog(LOG_INFO, "rklogd %s#%s, log source = ksyslog "
- "started.", VERSION, DEBRELEASE);
-#else
- Syslog(LOG_INFO, "rklogd %s, log source = ksyslog "
- "started.", VERSION);
-#endif
- return(kernel);
- }
-
-#ifndef TESTING
- if ( (kmsg = open(_PATH_KLOG, O_RDONLY)) < 0 )
- {
- fprintf(stderr, "rklogd: Cannot open proc file system, " \
- "%d - %s.\n", errno, strerror(errno));
- ksyslog(7, NULL, 0);
- exit(1);
- }
-#else
- kmsg = fileno(stdin);
-#endif
-
-#ifdef DEBRELEASE
- Syslog(LOG_INFO, "rklogd %ss#%s, log source = %s started.", \
- VERSION, DEBRELEASE, _PATH_KLOG);
-#else
- Syslog(LOG_INFO, "rklogd %s, log source = %s started.", \
- VERSION, _PATH_KLOG);
-#endif
- return(proc);
-}
-
-
-/*
- * Copy characters from ptr to line until a char in the delim
- * string is encountered or until min( space, len ) chars have
- * been copied.
- *
- * Returns the actual number of chars copied.
- */
-static int copyin( char *line, int space,
- const char *ptr, int len,
- const char *delim )
-{
- auto int i;
- auto int count;
-
- count = len < space ? len : space;
-
- for(i=0; i<count && !strchr(delim, *ptr); i++ ) {
- *line++ = *ptr++;
- }
-
- return( i );
-}
-
-/*
- * Messages are separated by "\n". Messages longer than
- * LOG_LINE_LENGTH are broken up.
- *
- * Kernel symbols show up in the input buffer as : "[<aaaaaa>]",
- * where "aaaaaa" is the address. These are replaced with
- * "[symbolname+offset/size]" in the output line - symbolname,
- * offset, and size come from the kernel symbol table.
- *
- * If a kernel symbol happens to fall at the end of a message close
- * in length to LOG_LINE_LENGTH, the symbol will not be expanded.
- * (This should never happen, since the kernel should never generate
- * messages that long.
- *
- * To preserve the original addresses, lines containing kernel symbols
- * are output twice. Once with the symbols converted and again with the
- * original text. Just in case somebody wants to run their own Oops
- * analysis on the syslog, e.g. ksymoops.
- */
-static void LogLine(char *ptr, int len)
-{
- enum parse_state_enum {
- PARSING_TEXT,
- PARSING_SYMSTART, /* at < */
- PARSING_SYMBOL,
- PARSING_SYMEND /* at ] */
- };
-
- static char line_buff[LOG_LINE_LENGTH];
-
- static char *line =line_buff;
- static enum parse_state_enum parse_state = PARSING_TEXT;
- static int space = sizeof(line_buff)-1;
-
- static char *sym_start; /* points at the '<' of a symbol */
-
- auto int delta = 0; /* number of chars copied */
- auto int symbols_expanded = 0; /* 1 if symbols were expanded */
- auto int skip_symbol_lookup = 0; /* skip symbol lookup on this pass */
- auto char *save_ptr = ptr; /* save start of input line */
- auto int save_len = len; /* save length at start of input line */
-
- while( len > 0 )
- {
- if( space == 0 ) /* line buffer is full */
- {
- /*
- ** Line too long. Start a new line.
- */
- *line = 0; /* force null terminator */
-
- if ( debugging )
- {
- fputs("Line buffer full:\n", stderr);
- fprintf(stderr, "\tLine: %s\n", line);
- }
-
- Syslog( LOG_INFO, "%s", line_buff );
- line = line_buff;
- space = sizeof(line_buff)-1;
- parse_state = PARSING_TEXT;
- symbols_expanded = 0;
- skip_symbol_lookup = 0;
- save_ptr = ptr;
- save_len = len;
- }
-
- switch( parse_state )
- {
- case PARSING_TEXT:
- delta = copyin( line, space, ptr, len, "\n[" );
- line += delta;
- ptr += delta;
- space -= delta;
- len -= delta;
-
- if( space == 0 || len == 0 )
- {
- break; /* full line_buff or end of input buffer */
- }
-
- if( *ptr == '\0' ) /* zero byte */
- {
- ptr++; /* skip zero byte */
- space -= 1;
- len -= 1;
-
- break;
- }
-
- if( *ptr == '\n' ) /* newline */
- {
- ptr++; /* skip newline */
- space -= 1;
- len -= 1;
-
- *line = 0; /* force null terminator */
- Syslog( LOG_INFO, "%s", line_buff );
- line = line_buff;
- space = sizeof(line_buff)-1;
- if (symbols_twice) {
- if (symbols_expanded) {
- /* reprint this line without symbol lookup */
- symbols_expanded = 0;
- skip_symbol_lookup = 1;
- ptr = save_ptr;
- len = save_len;
- }
- else
- {
- skip_symbol_lookup = 0;
- save_ptr = ptr;
- save_len = len;
- }
- }
- break;
- }
- if( *ptr == '[' ) /* possible kernel symbol */
- {
- *line++ = *ptr++;
- space -= 1;
- len -= 1;
- if (!skip_symbol_lookup)
- parse_state = PARSING_SYMSTART; /* at < */
- break;
- }
- /* Now that line_buff is no longer fed to *printf as format
- * string, '%'s are no longer "dangerous".
- */
- break;
-
- case PARSING_SYMSTART:
- if( *ptr != '<' )
- {
- parse_state = PARSING_TEXT; /* not a symbol */
- break;
- }
-
- /*
- ** Save this character for now. If this turns out to
- ** be a valid symbol, this char will be replaced later.
- ** If not, we'll just leave it there.
- */
-
- sym_start = line; /* this will point at the '<' */
-
- *line++ = *ptr++;
- space -= 1;
- len -= 1;
- parse_state = PARSING_SYMBOL; /* symbol... */
- break;
-
- case PARSING_SYMBOL:
- delta = copyin( line, space, ptr, len, ">\n[" );
- line += delta;
- ptr += delta;
- space -= delta;
- len -= delta;
- if( space == 0 || len == 0 )
- {
- break; /* full line_buff or end of input buffer */
- }
- if( *ptr != '>' )
- {
- parse_state = PARSING_TEXT;
- break;
- }
-
- *line++ = *ptr++; /* copy the '>' */
- space -= 1;
- len -= 1;
-
- parse_state = PARSING_SYMEND;
-
- break;
-
- case PARSING_SYMEND:
- if( *ptr != ']' )
- {
- parse_state = PARSING_TEXT; /* not a symbol */
- break;
- }
-
- /*
- ** It's really a symbol! Replace address with the
- ** symbol text.
- */
- {
- auto int sym_space;
-
- unsigned long value;
- auto struct symbol sym;
- auto char *symbol;
-
- *(line-1) = 0; /* null terminate the address string */
- value = strtoul(sym_start+1, (char **) 0, 16);
- *(line-1) = '>'; /* put back delim */
-
- if ( !symbol_lookup || (symbol = LookupSymbol(value, &sym)) == (char *)0 )
- {
- parse_state = PARSING_TEXT;
- break;
- }
-
- /*
- ** verify there is room in the line buffer
- */
- sym_space = space + ( line - sym_start );
- if( (unsigned) sym_space < strlen(symbol) + 30 ) /*(30 should be overkill)*/
- {
- parse_state = PARSING_TEXT; /* not enough space */
- break;
- }
-
- delta = sprintf( sym_start, "%s+%d/%d]",
- symbol, sym.offset, sym.size );
-
- space = sym_space + delta;
- line = sym_start + delta;
- symbols_expanded = 1;
- }
- ptr++;
- len--;
- parse_state = PARSING_TEXT;
- break;
-
- default: /* Can't get here! */
- parse_state = PARSING_TEXT;
-
- }
- }
-
- return;
-}
-
-
-static void LogKernelLine(void)
-{
- auto int rdcnt;
-
- /*
- * Zero-fill the log buffer. This should cure a multitude of
- * problems with klogd logging the tail end of the message buffer
- * which will contain old messages. Then read the kernel log
- * messages into this fresh buffer.
- */
- memset(log_buffer, '\0', sizeof(log_buffer));
- if ( (rdcnt = ksyslog(2, log_buffer, sizeof(log_buffer)-1)) < 0 )
- {
- if ( errno == EINTR )
- return;
- fprintf(stderr, "rklogd: Error return from sys_sycall: " \
- "%d - %s\n", errno, strerror(errno));
- }
- else
- LogLine(log_buffer, rdcnt);
- return;
-}
-
-
-static void LogProcLine(void)
-{
- auto int rdcnt;
-
- /*
- * Zero-fill the log buffer. This should cure a multitude of
- * problems with klogd logging the tail end of the message buffer
- * which will contain old messages. Then read the kernel messages
- * from the message pseudo-file into this fresh buffer.
- */
- memset(log_buffer, '\0', sizeof(log_buffer));
- if ( (rdcnt = read(kmsg, log_buffer, sizeof(log_buffer)-1)) < 0 )
- {
- if ( errno == EINTR )
- return;
- Syslog(LOG_ERR, "Cannot read proc file system: %d - %s.", \
- errno, strerror(errno));
- }
- else
- LogLine(log_buffer, rdcnt);
-
- return;
-}
-
-
-/* helper routine to spit out an error message and terminate
- * klogd when setting a signal error fails.
- */
-void sigactionErrAbort()
-{
- fprintf(stderr, "rklogd: could net set a signal handler - terminating. Error: %s\n",
- strerror(errno));
- exit(1);
-}
-
-
-int main(int argc, char *argv[])
-{
- int ch,
- use_output = 0;
-
- char *log_level = (char *) 0,
- *output = (char *) 0;
- struct sigaction sigAct;
-
-#ifndef TESTING
- chdir ("/");
-#endif
- /* Parse the command-line. */
- while ((ch = getopt(argc, argv, "c:df:iIk:nopsvx2")) != EOF)
- switch((char)ch)
- {
- case '2': /* Print lines with symbols twice. */
- symbols_twice = 1;
- break;
- case 'c': /* Set console message level. */
- log_level = optarg;
- break;
- case 'd': /* Activity debug mode. */
- debugging = 1;
- break;
- case 'f': /* Define an output file. */
- output = optarg;
- use_output++;
- break;
- case 'i': /* Reload module symbols. */
- SignalDaemon(SIGUSR1);
- return(0);
- case 'I':
- SignalDaemon(SIGUSR2);
- return(0);
- case 'k': /* Kernel symbol file. */
- symfile = optarg;
- break;
- case 'n': /* don't fork */
- no_fork++;
- break;
- case 'o': /* One-shot mode. */
- one_shot = 1;
- break;
- case 'p':
- SetParanoiaLevel(1); /* Load symbols on oops. */
- break;
- case 's': /* Use syscall interface. */
- use_syscall = 1;
- break;
- case 'v':
- printf("rklogd %s\n", VERSION);
- exit (1);
- case 'x':
- symbol_lookup = 0;
- break;
- }
-
-
- /* Set console logging level. */
- if ( log_level != (char *) 0 )
- {
- if ( (strlen(log_level) > 1) || \
- (strchr("12345678", *log_level) == (char *) 0) )
- {
- fprintf(stderr, "rklogd: Invalid console logging "
- "level <%s> specified.\n", log_level);
- return(1);
- }
- console_log_level = *log_level - '0';
- }
-
-
-#ifndef TESTING
- /*
- * The following code allows klogd to auto-background itself.
- * What happens is that the program forks and the parent quits.
- * The child closes all its open file descriptors, and issues a
- * call to setsid to establish itself as an independent session
- * immune from control signals.
- *
- * fork() is only called if it should run in daemon mode, fork is
- * not disabled with the command line argument and there's no
- * such process running.
- */
- if ( (!one_shot) && (!no_fork) )
- {
- if (!check_pid(PidFile))
- {
- if ( fork() == 0 )
- {
- auto int fl;
- int num_fds = getdtablesize();
-
- /* This is the child closing its file descriptors. */
- for (fl= 0; fl <= num_fds; ++fl)
- {
- if ( fileno(stdout) == fl && use_output )
- if ( strcmp(output, "-") == 0 )
- continue;
- close(fl);
- }
-
- setsid();
- }
- else
- exit(0);
- }
- else
- {
- fputs("rklogd: Already running.\n", stderr);
- exit(1);
- }
- }
-
-
- /* tuck my process id away */
- if (!check_pid(PidFile))
- {
- if (!write_pid(PidFile))
- Terminate();
- }
- else
- {
- fputs("rklogd: Already running.\n", stderr);
- Terminate();
- }
-#endif
-
- /* Signal setups.
- * Please note that the "original" klogd in sysklogd tries to
- * handle SIGKILL and SIGSTOP. That does not work - but as the
- * original klogd had no error checking, nobody ever noticed. We
- * do now have error checking and consequently those ever-failing
- * calls are now removed.
- */
- sigemptyset(&sigAct.sa_mask);
- sigAct.sa_flags = 0;
-
- /* first, set all signals to ignore
- * In this loop, we try blindly to ignore all signals. I am leaving
- * intentionally out all error checking. If we can ignore the signal,
- * that's nice, but if we can't ... well, so be it ;)
- * RGerhards, 2007-06-15
- */
- sigAct.sa_handler = SIG_IGN;
- for (ch= 1; ch < NSIG ; ++ch)
- {
- if(ch != SIGKILL && ch != SIGSTOP)
- sigaction(ch, &sigAct, NULL);
- }
-
- /* Now specific handlers (one after another) */
- sigAct.sa_handler = stop_daemon;
- if(sigaction(SIGINT, &sigAct, NULL) != 0) sigactionErrAbort();
- if(sigaction(SIGTERM, &sigAct, NULL) != 0) sigactionErrAbort();
- if(sigaction(SIGHUP, &sigAct, NULL) != 0) sigactionErrAbort();
-
- sigAct.sa_handler = stop_daemon;
- if(sigaction(SIGTSTP, &sigAct, NULL) != 0) sigactionErrAbort();
-
- sigAct.sa_handler = restart;
- if(sigaction(SIGCONT, &sigAct, NULL) != 0) sigactionErrAbort();
-
- sigAct.sa_handler = reload_daemon;
- if(sigaction(SIGUSR1, &sigAct, NULL) != 0) sigactionErrAbort();
- if(sigaction(SIGUSR2, &sigAct, NULL) != 0) sigactionErrAbort();
-
-
- /* Open outputs. */
- if ( use_output )
- {
- if ( strcmp(output, "-") == 0 )
- output_file = stdout;
- else if ( (output_file = fopen(output, "w")) == (FILE *) 0 )
- {
- fprintf(stderr, "rklogd: Cannot open output file " \
- "%s - %s\n", output, strerror(errno));
- return(1);
- }
- }
-
- /* Handle one-shot logging. */
- if ( one_shot )
- {
- if (symbol_lookup) {
- symbol_lookup = (InitKsyms(symfile) == 1);
- symbol_lookup |= InitMsyms();
- if (symbol_lookup == 0) {
- Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n");
- }
- }
- if ( (logsrc = GetKernelLogSrc()) == kernel )
- LogKernelLine();
- else
- LogProcLine();
- Terminate();
- }
-
- /* Determine where kernel logging information is to come from. */
-#if defined(KLOGD_DELAY)
- sleep(KLOGD_DELAY);
-#endif
- logsrc = GetKernelLogSrc();
- if (symbol_lookup) {
- symbol_lookup = (InitKsyms(symfile) == 1);
- symbol_lookup |= InitMsyms();
- if (symbol_lookup == 0) {
- Syslog(LOG_WARNING, "cannot find any symbols, turning off symbol lookups\n");
- }
- }
-
- /* The main loop. */
- /* The main loop will be broken by a signal handler which set the
- * terminate variable. That is then cheked in ChangeLogging(), which
- * will then terminate klogd.
- * RGerhards, 2007-06-15
- */
- while(1)
- {
- if ( change_state )
- ChangeLogging();
- switch ( logsrc )
- {
- case kernel:
- LogKernelLine();
- break;
- case proc:
- LogProcLine();
- break;
- case none:
- pause();
- break;
- }
- }
-}
-#else /* #ifdef FEATURE_KLOGD */
-#include <stdio.h>
-int main()
-{
- fprintf(stderr, "FEATURE_KLOGD was disabled during make, so rklogd is not available.\n");
- return(1);
-}
-#endif /* #ifdef WITH_KLOGD */
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- * vi:set ai:
- */