summaryrefslogtreecommitdiffstats
path: root/syslog.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2007-06-14 13:07:32 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2007-06-14 13:07:32 +0000
commit2112ef22ae40b421279221f77140f90e09308c39 (patch)
tree1e704e1ca6784ddd436963f39f71746e75253278 /syslog.c
parentf925aba4ad669c6b96b348c0761ed0531c6f41b4 (diff)
downloadrsyslog-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.
Diffstat (limited to 'syslog.c')
-rw-r--r--syslog.c322
1 files changed, 104 insertions, 218 deletions
diff --git a/syslog.c b/syslog.c
index 59822220..889b0057 100644
--- a/syslog.c
+++ b/syslog.c
@@ -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);
-}