diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2007-06-14 13:07:32 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2007-06-14 13:07:32 +0000 |
commit | 2112ef22ae40b421279221f77140f90e09308c39 (patch) | |
tree | 1e704e1ca6784ddd436963f39f71746e75253278 | |
parent | f925aba4ad669c6b96b348c0761ed0531c6f41b4 (diff) | |
download | rsyslog-2112ef22ae40b421279221f77140f90e09308c39.tar.gz rsyslog-2112ef22ae40b421279221f77140f90e09308c39.tar.xz rsyslog-2112ef22ae40b421279221f77140f90e09308c39.zip |
re-wrote syslog.c from scratch to solve a license compatibility issue,
provide some bug fixes and performance enhancemnts. Also required
changes to klogd.c to support the new interface.
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | klogd.c | 200 | ||||
-rw-r--r-- | klogd.h | 1 | ||||
-rw-r--r-- | syslog.c | 322 | ||||
-rw-r--r-- | syslogd.c | 3 | ||||
-rw-r--r-- | version.h | 2 |
6 files changed, 203 insertions, 336 deletions
@@ -1,4 +1,15 @@ --------------------------------------------------------------------------- +Version 1.13.3 (RGer), 2007-??-?? +- create a version of syslog.c from scratch. This is now + - highly optimized for rsyslog + - removes an incompatible license problem as the original + version had a BSD license with advertising clause + - fixed in the regard that rklogd will continue to work when + rsysogd has been restarted (the original version, as well + as sysklogd, will remain silent then) + - solved an issue with an extra NUL char at message end that the + original version had +--------------------------------------------------------------------------- Version 1.13.2 (RGer), 2007-06-13 - lib order in makefile patched to facilitate static linking - thanks to Bennett Todd for providing the patch @@ -275,6 +275,8 @@ _syscall3(int,ksyslog,int, type, char *, buf, int, len); #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" @@ -332,8 +334,84 @@ static void LogProcLine(void); extern int main(int argc, char *argv[]); -static void CloseLogSrc() +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. */ ksyslog(7, NULL, 0); @@ -371,10 +449,7 @@ void restart(sig) } -void stop_logging(sig) - - int sig; - +void stop_logging(int sig) { signal(SIGTSTP, stop_logging); change_state = 1; @@ -383,20 +458,14 @@ void stop_logging(sig) } -void stop_daemon(sig) - - int sig; - +void stop_daemon(int sig) { Terminate(); return; } -void reload_daemon(sig) - - int sig; - +void reload_daemon(int sig) { change_state = 1; reload_symbols = 1; @@ -415,7 +484,6 @@ void reload_daemon(sig) static void Terminate() - { CloseLogSrc(); Syslog(LOG_INFO, "Kernel log daemon terminating."); @@ -429,10 +497,7 @@ static void Terminate() exit(1); } -static void SignalDaemon(sig) - - int sig; - +static void SignalDaemon(int sig) { #ifndef TESTING auto int pid = check_pid(PidFile); @@ -445,8 +510,7 @@ static void SignalDaemon(sig) } -static void ReloadSymbols() - +static void ReloadSymbols(void) { if (symbol_lookup) { if ( reload_symbols > 1 ) @@ -459,7 +523,6 @@ static void ReloadSymbols() static void ChangeLogging(void) - { /* Terminate kernel logging. */ if ( terminate == 1 ) @@ -508,11 +571,9 @@ static void ChangeLogging(void) static enum LOGSRC GetKernelLogSrc(void) - { auto struct stat sb; - /* Set level of kernel console messaging.. */ if ( (ksyslog(8, NULL, console_log_level) < 0) && \ (errno == EINVAL) ) @@ -570,87 +631,6 @@ static enum LOGSRC GetKernelLogSrc(void) } -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; - } - syslog(priority, fmt, argl); - va_end(ap); -#ifdef TESTING - putchar('\n'); -#endif - return; - } - - va_start(ap, fmt); - vsyslog(priority, fmt, ap); - va_end(ap); -#ifdef TESTING - printf ("\n"); -#endif - - return; -} - - /* * Copy characters from ptr to line until a char in the delim * string is encountered or until min( space, len ) chars have @@ -909,7 +889,6 @@ static void LogLine(char *ptr, int len) static void LogKernelLine(void) - { auto int rdcnt; @@ -934,7 +913,6 @@ static void LogKernelLine(void) static void LogProcLine(void) - { auto int rdcnt; @@ -959,12 +937,7 @@ static void LogProcLine(void) } -int main(argc, argv) - - int argc; - - char *argv[]; - +int main(int argc, char *argv[]) { auto int ch, use_output = 0; @@ -1117,9 +1090,6 @@ int main(argc, argv) return(1); } } - else - openlog("kernel", 0, LOG_KERN); - /* Handle one-shot logging. */ if ( one_shot ) @@ -40,6 +40,5 @@ extern int InitMsyms(void); extern char * ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); extern void Syslog(int priority, char *fmt, ...); -extern void syslog(int pri, const char *fmt, ...); extern void vsyslog(int pri, const char *fmt, va_list ap); extern void openlog(const char *ident, int logstat, int logfac); @@ -1,252 +1,138 @@ -/* - * 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. - */ - -/* - * 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. +/* logger.c + * Helper routines for klogd. It replaces the regular glibc syslog() + * call. The reason is that the glibc version does not support + * logging with the kernel facility. This file is a re-implementation + * of the functions with only the functionality required for klogd. + * So it can NOT be used as a general-purpose replacment. + * Thanks to being special, this version is deemed to be considerable + * faster than its glibc counterpart. + * To avoid confusion, the syslog() replacement is named writeSyslog(). + * all other functions are just helpers to it. + * RGerhards, 2007-06-14 * - * The output of this routine is intended to be read by syslogd(8). + * Copyright (C) 2007 Rainer Gerhards * - * Author: Eric Allman - * Modified to use UNIX domain IPC by Ralph Campbell + * 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. * - * Sat Dec 11 11:58:31 CST 1993: Dr. Wettstein - * Changes to allow compilation with no complains under -Wall. + * 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. * - * 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. - * - * Sun Mar 11 20:23:44 CET 2001: Martin Schulze <joey@infodrom.ffis.de> - * Use SOCK_DGRAM for loggin, renables it to work. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * A copy of the GPL can be found in the file "COPYING" in this distribution. */ - -#include <sys/types.h> +#include <stdio.h> +#include <assert.h> #include <sys/socket.h> -#include <sys/file.h> -#include <sys/signal.h> -#include <sys/syslog.h> -#undef syslog -#undef vsyslog -#if 0 -#include "syslog.h" -#include "pathnames.h" -#endif - -#include <sys/uio.h> -#include <sys/wait.h> -#include <netdb.h> #include <string.h> #include <time.h> -#include <unistd.h> -#include <errno.h> #include <stdarg.h> -#include <paths.h> -#include <stdio.h> +#include <unistd.h> -#define _PATH_LOGNAME "/dev/log" +#define PATH_LOGNAME "/dev/log" /* be sure you know what you do if you change this! */ -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 */ +static struct sockaddr LoggerAddr; /* AF_UNIX address of local logger */ +static int connected; /* have done connect */ +static int fdLog = -1; /* fd for log - -1 if closed */ -void -syslog(int pri, const char *fmt, ...) +/* klogOpenLog + * opens the system log for writing. The log is opened immediately. + * If it is already open, no action is taken) + */ +static void klogOpenlog(void) { - va_list ap; - - va_start(ap, fmt); - vsyslog(pri, fmt, ap); - va_end(ap); + if (fdLog == -1) { + LoggerAddr.sa_family = AF_UNIX; + strncpy(LoggerAddr.sa_data, PATH_LOGNAME, sizeof(LoggerAddr.sa_data)); + fdLog = socket(AF_UNIX, SOCK_DGRAM, 0); + } + if (fdLog != -1 && !connected) + if(connect(fdLog, &LoggerAddr, sizeof(LoggerAddr.sa_family) + + sizeof(PATH_LOGNAME) - 1 /* for \0 byte!*/ ) != -1) + connected = 1; } -void -vsyslog(pri, fmt, ap) - int pri; - const char *fmt; - va_list ap; +/* Close the log file if it is currently open. + */ +static void klogCloselog(void) { - register int cnt; - register char *p; - time_t now; - int fd, saved_errno; - char tbuf[2048], fmt_cpy[1024], *stdp = (char *) 0; + if(fdLog != -1) + close(fdLog); + fdLog = -1; + connected = 0; +} - saved_errno = errno; +/* Write a message to the syslogd. + * returns -1 if it fails, something else otherwise + */ +int writeSyslogV(int iPRI, const char *szFmt, va_list va) +{ + int iChars; + int iLen; + time_t tNow; + int iWritten; /* number of bytes written */ + char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ - /* 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, LogFacility); + assert(szFmt != NULL); - /* set default facility if none specified */ - if ((pri & LOG_FACMASK) == 0) - pri |= LogFacility; + if (fdLog < 0 || !connected) + klogOpenlog(); /* 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' && t1<fmt_cpy+sizeof(fmt_cpy); - ++fmt) - if (ch == '%' && fmt[1] == 'm') { - ++fmt; - for (t2 = strerror(saved_errno); - (*t1 = *t2++); ++t1); - } - else - *t1++ = ch; - *t1 = '\0'; - } - - (void)vsprintf(p, fmt_cpy, ap); - - cnt = strlen(tbuf); - - /* output to stderr if requested */ - if (LogStat & LOG_PERROR) { - struct iovec iov[2]; - register struct iovec *v = iov; + time(&tNow); + /* we can use sprintf safely below, because we know the size of the constants. + * By doing so, we save some cpu cycles and code complexity (for unnecessary + * error checking). + */ + iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4); - v->iov_base = stdp; - v->iov_len = cnt - (stdp - tbuf); - ++v; - v->iov_base = "\n"; - v->iov_len = 1; - (void)writev(2, iov, 2); - } + iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va); + if(iChars > sizeof(msgBuf) / sizeof(char) - iLen) + iLen = sizeof(msgBuf) / sizeof(char) - 1; /* full buffer siz minus \0 byte */ + else + iLen += iChars; /* output the message to the local logger */ - if (write(LogFile, tbuf, cnt + 1) >= 0 || !(LogStat&LOG_CONS)) - return; + iWritten = write(fdLog, msgBuf, iLen); + /* Debug aid below - uncomment to use + printf("wrote to log(%d): '%s'\n", iWritten, msgBuf); */ + + if(iWritten == -1) { + /* retry */ + klogCloselog(); + klogOpenlog(); + iWritten = write(fdLog, msgBuf, iLen); + } - /* - * 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); + return(iWritten); } -#ifndef TESTING -static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ -#endif -/* - * OPENLOG -- open system log - */ -void -openlog(ident, logstat, logfac) - const char *ident; - int logstat, logfac; +/* And now the same with variable arguments */ +int writeSyslog(int iPRI, const char *szFmt, ...) { - 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; - -#ifndef TESTING - 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_DGRAM, 0); -/* fcntl(LogFile, F_SETFD, 1); */ - } - } - if (LogFile != -1 && !connected && - connect(LogFile, &SyslogAddr, sizeof(SyslogAddr.sa_family)+ - strlen(SyslogAddr.sa_data)) != -1) -#else - LogFile = fileno(stdout); -#endif - connected = 1; -} + int iRet; + va_list va; -/* - * CLOSELOG -- close the system log - */ -void -closelog() -{ -#ifndef TESTING - (void) close(LogFile); -#endif - LogFile = -1; - connected = 0; + assert(szFmt != NULL); + va_start(va, szFmt); + iRet = writeSyslogV(iPRI, szFmt, va); + va_end(va); + + return(iRet); } -static int LogMask = 0xff; /* mask of priorities to be logged */ /* - * SETLOGMASK -- set the log mask level + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + * vi:set ai: */ -int -setlogmask(pmask) - int pmask; -{ - int omask; - - omask = LogMask; - if (pmask != 0) - LogMask = pmask; - return (omask); -} @@ -1442,12 +1442,13 @@ static int TCPSessDataRcvd(int iTCPSess, char *pData, int iLen) * rgerhards, 2006-12-19 */ if(isdigit(*pData)) { + int iCnt; /* the frame count specified */ TCPSessions[iTCPSess].eFraming = TCP_FRAMING_OCTET_COUNTING; /* in this mode, we have OCTET-COUNT SP MSG - so we now need * to extract the OCTET-COUNT and the SP and then extract * the msg. */ - int iCnt = 0; /* the frame count specified */ + iCnt = 0; /* IETF20061218 int iNbrOctets = 0; / * number of octets already consumed */ while(isdigit(*pData)) { iCnt = iCnt * 10 + *pData - '0'; @@ -1,2 +1,2 @@ #define VERSION "1.13" -#define PATCHLEVEL "2" +#define PATCHLEVEL "3" |