/* klog for BSD, based on the FreeBSD syslogd implementation.
*
* This contains OS-specific functionality to read the BSD
* kernel log. For a general overview, see head comment in
* imklog.c.
*
* Copyright (C) 2008 by Rainer Gerhards for the modifications of
* the original FreeBSD sources.
*
* I would like to express my gratitude to those folks which
* layed an important foundation for rsyslog to build on.
*
* 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 .
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*
* This file is based on earlier work included in the FreeBSD sources. We
* integrated it into the rsyslog project. The copyright below applies, and
* I also reproduce the original license under which we aquired the code:
*
* Copyright (c) 1983, 1988, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* If you would like to use the code under the BSD license, you should
* aquire your own copy of BSD's syslogd, from which we have taken it. The
* code in this file is modified and may only be used under the terms of
* the GPLv3+ as specified above.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
#include
#include
#include
#include
#include "rsyslog.h"
#include "imklog.h"
/* globals */
static int fklog = -1; /* /dev/klog */
#ifndef _PATH_KLOG
# define _PATH_KLOG "/dev/klog"
#endif
static uchar *GetPath(void)
{
return pszPath ? pszPath : _PATH_KLOG;
}
/* open the kernel log - will be called inside the willRun() imklog
* entry point. -- rgerhards, 2008-04-09
*/
rsRetVal
klogWillRun(void)
{
DEFiRet;
fklog = open(GetPath(), O_RDONLY, 0);
if (fklog < 0) {
dbgprintf("can't open %s (%d)\n", GetPath(), errno);
iRet = RS_RET_ERR; // TODO: better error code
}
RETiRet;
}
/* Read /dev/klog while data are available, split into lines.
* Contrary to standard BSD syslogd, we do a blocking read. We can
* afford this as imklog is running on its own threads. So if we have
* a single file, it really doesn't matter if we wait inside a 1-file
* select or the read() directly.
*/
static void
readklog(void)
{
char *p, *q;
int len, i;
int iMaxLine;
uchar bufRcv[4096+1];
uchar *pRcv = NULL; /* receive buffer */
iMaxLine = klog_getMaxLine();
/* we optimize performance: if iMaxLine is below 4K (which it is in almost all
* cases, we use a fixed buffer on the stack. Only if it is higher, heap memory
* is used. We could use alloca() to achive a similar aspect, but there are so
* many issues with alloca() that I do not want to take that route.
* rgerhards, 2008-09-02
*/
if((size_t) iMaxLine < sizeof(bufRcv) - 1) {
pRcv = bufRcv;
} else {
if((pRcv = (uchar*) malloc(sizeof(uchar) * (iMaxLine + 1))) == NULL)
iMaxLine = sizeof(bufRcv) - 1; /* better this than noting */
}
len = 0;
for (;;) {
dbgprintf("----------imklog(BSD) waiting for kernel log line\n");
i = read(fklog, pRcv + len, iMaxLine - len);
if (i > 0) {
pRcv[i + len] = '\0';
} else {
if (i < 0 && errno != EINTR && errno != EAGAIN) {
imklogLogIntMsg(LOG_ERR,
"imklog error %d reading kernel log - shutting down imklog",
errno);
fklog = -1;
}
break;
}
for (p = pRcv; (q = strchr(p, '\n')) != NULL; p = q + 1) {
*q = '\0';
Syslog(LOG_INFO, (uchar*) p);
}
len = strlen(p);
if (len >= iMaxLine - 1) {
Syslog(LOG_INFO, (uchar*)p);
len = 0;
}
if (len > 0)
memmove(pRcv, p, len + 1);
}
if (len > 0)
Syslog(LOG_INFO, pRcv);
if(pRcv != NULL && (size_t) iMaxLine >= sizeof(bufRcv) - 1)
free(pRcv);
}
/* to be called in the module's AfterRun entry point
* rgerhards, 2008-04-09
*/
rsRetVal klogAfterRun(void)
{
DEFiRet;
if(fklog != -1)
close(fklog);
RETiRet;
}
/* to be called in the module's WillRun entry point, this is the main
* "message pull" mechanism.
* rgerhards, 2008-04-09
*/
rsRetVal klogLogKMsg(void)
{
DEFiRet;
readklog();
RETiRet;
}
/* provide the (system-specific) default facility for internal messages
* rgerhards, 2008-04-14
*/
int
klogFacilIntMsg(void)
{
return LOG_SYSLOG;
}