Implemented syslog output. For now, it will be put into /tmp (i.e. the tests

won't clobber your existing syslog).
The time stamp is currently #ifdef'd out. We might think about adding some
prefs; the facility could also only printed for kernel messages (like in
Be's implementation).


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5343 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2003-11-13 02:56:57 +00:00
parent fe4817d5c0
commit 1cb317b43c

View File

@ -6,13 +6,151 @@
#include "syslog_output.h"
#include <FindDirectory.h>
#include <Path.h>
#include <syslog.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
static const size_t kMaxLogSize = 524288; // 512kB
static const char *kFacilities[] = {
"KERN", "USER", "MAIL", "DAEMON",
"AUTH", "SYSLOGD", "LPR", "NEWS",
"UUCP", "CRON", "AUTHPRIV",
"", "", "", "", "",
"LOCAL0", "LOCAL1", "LOCAL2", "LOCAL3",
"LOCAL4", "LOCAL5", "LOCAL6", "LOCAL7",
NULL
};
static const int32 kNumFacilities = 24;
int sLog = -1;
char sLastMessage[1024];
thread_id sLastThread;
int32 sRepeatCount;
static status_t
prepare_output()
{
bool needNew = true;
bool tooLarge = false;
if (sLog > 0) {
// check file size
struct stat stat;
if (fstat(sLog, &stat) == 0) {
if (stat.st_size < kMaxLogSize)
needNew = false;
else
tooLarge = true;
}
}
if (needNew) {
// get path
BPath base;
find_directory(/*B_COMMON_LOG_DIRECTORY*/B_COMMON_TEMP_DIRECTORY, &base);
// ToDo: change to correct "which" parameter!
BPath syslog(base);
syslog.Append("syslog");
// move old file if it already exists
if (tooLarge) {
base.Append("syslog.old");
rename(syslog.Path(), base.Path());
// ToDo: remove old file if space on device is tight?
}
// open file
sLog = open(syslog.Path(), O_APPEND | O_CREAT | O_WRONLY, 644);
}
return sLog >= 0 ? B_OK : B_ERROR;
}
static status_t
write_to_log(const char *buffer, int32 length)
{
if (sRepeatCount > 0) {
char repeat[64];
ssize_t size = snprintf(repeat, sizeof(repeat),
"Last message repeated %ld time%s\n", sRepeatCount,
sRepeatCount > 1 ? "s" : "");
sRepeatCount = 0;
if (write(sLog, repeat, strlen(repeat)) < size)
return B_ERROR;
}
if (write(sLog, buffer, length) < length)
return B_ERROR;
return B_OK;
}
static void
syslog_output(syslog_message &message)
{
printf("'%s'[%ld]: %s\n", message.ident, message.from, message.message);
// did we get this message already?
if (message.from == sLastThread
&& !strncmp(message.message, sLastMessage, sizeof(sLastMessage))) {
sRepeatCount++;
return;
}
char buffer[4096];
#if 0
// parse & nicely print the time stamp from the message
struct tm when;
localtime_r(&message.when, &when);
int32 pos = strftime(buffer, sizeof(buffer), "%b %d, %H:%M:%S ", &when);
#else
int32 pos = 0;
#endif
// add facility
int facility = SYSLOG_FACILITY_INDEX(message.priority);
if (facility >= kNumFacilities)
facility = SYSLOG_FACILITY_INDEX(LOG_USER);
pos += snprintf(buffer + pos, sizeof(buffer) - pos, "%s", kFacilities[facility]);
// add ident/thread ID
if (message.ident[0] == '\0') {
// ToDo: find out team name?
} else
pos += snprintf(buffer + pos, sizeof(buffer) - pos, " '%s'", message.ident);
if (message.options & LOG_PID)
pos += snprintf(buffer + pos, sizeof(buffer) - pos, "[%ld]", message.from);
// add message itself
int32 length = pos + snprintf(buffer + pos, sizeof(buffer) - pos, ": %s\n", message.message);
// ToDo: be less lazy about it - there is virtually no reason to truncate the message
if (strlen(message.message) > sizeof(buffer) - pos - 1)
strcpy(&buffer[sizeof(buffer) - 8], "<TRUNC>\n");
// dump message
if (prepare_output() < B_OK
|| write_to_log(buffer, length) < B_OK) {
// cannot write to syslog!
fputs(buffer, stderr);
}
// save this message to suppress repeated messages
strlcpy(sLastMessage, message.message, sizeof(sLastMessage));
sLastThread = message.from;
}