From 3b737adbdaf9a23a2644bf79ad8398791ef68547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 12 Nov 2003 14:35:22 +0000 Subject: [PATCH] Implemented the POSIX syslog API including the BeOS extensions. In BeOS, this API is found in libbe.so, in OpenBeOS, it's directly in libroot.so. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5326 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/libroot/posix/Jamfile | 7 +- src/kernel/libroot/posix/syslog.cpp | 246 ++++++++++++++++++++++++++++ 2 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 src/kernel/libroot/posix/syslog.cpp diff --git a/src/kernel/libroot/posix/Jamfile b/src/kernel/libroot/posix/Jamfile index df300d2174..ac292f966f 100644 --- a/src/kernel/libroot/posix/Jamfile +++ b/src/kernel/libroot/posix/Jamfile @@ -1,5 +1,7 @@ SubDir OBOS_TOP src kernel libroot posix ; +UsePrivateHeaders [ FDirName syslog_daemon ] ; + KernelMergeObject posix_main.o : <$(SOURCE_GRIST)>dlfcn.c <$(SOURCE_GRIST)>errno.c @@ -8,6 +10,7 @@ KernelMergeObject posix_main.o : <$(SOURCE_GRIST)>poll.c <$(SOURCE_GRIST)>pwd.c <$(SOURCE_GRIST)>rlimit.c + <$(SOURCE_GRIST)>syslog.cpp <$(SOURCE_GRIST)>utime.c : -fPIC -DPIC @@ -34,4 +37,6 @@ SubInclude OBOS_TOP src kernel libroot posix string ; SubInclude OBOS_TOP src kernel libroot posix sys ; SubInclude OBOS_TOP src kernel libroot posix termios ; SubInclude OBOS_TOP src kernel libroot posix time ; -SubInclude OBOS_TOP src kernel libroot posix unistd ; \ No newline at end of file +SubInclude OBOS_TOP src kernel libroot posix unistd ; + +#SubInclude OBOS_TOP src kernel libroot posix glibc ; diff --git a/src/kernel/libroot/posix/syslog.cpp b/src/kernel/libroot/posix/syslog.cpp new file mode 100644 index 0000000000..3ccbcf44a3 --- /dev/null +++ b/src/kernel/libroot/posix/syslog.cpp @@ -0,0 +1,246 @@ +/* +** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + + +#include +#include + +#include +#include +#include +#include +#include + + +struct syslog_context { + char ident[B_OS_NAME_LENGTH]; + int32 mask; + int32 options; +}; + +static syslog_context sTeamContext; +static int32 sThreadContextSlot = -1; + + +static syslog_context * +allocate_context() +{ + syslog_context *context = (syslog_context *)malloc(sizeof(syslog_context)); + if (context == NULL) + return NULL; + + // inherit the attributes of the team context + memcpy(context, &sTeamContext, sizeof(syslog_context)); + return context; +} + + +/** This function returns the current syslog context structure. + * If there is none for the current thread, it will create one + * that inherits the context attributes from the team and put it + * into TLS. + * If it could not allocate a thread context, it will return the + * team context; this function is guaranteed to return a valid + * syslog context. + */ + +static syslog_context * +get_context() +{ + if (sThreadContextSlot == B_NO_MEMORY) + return &sTeamContext; + + if (sThreadContextSlot < 0) { + static int32 lock = 0; + if (atomic_add(&lock, 1) == 0) { + int32 slot = tls_allocate(); + + if (slot < 0) { + sThreadContextSlot = B_NO_MEMORY; + return &sTeamContext; + } + + *tls_address(slot) = allocate_context(); + sThreadContextSlot = slot; + return (syslog_context *)tls_get(slot); + } else { + while (sThreadContextSlot == -1) + snooze(10000); + } + } + + syslog_context *context = (syslog_context *)tls_get(sThreadContextSlot); + if (context == NULL) { + // try to allocate the context again; it might have + // been deleted, or there was not enough memory last + // time + context = allocate_context(); + } + if (context != NULL) + return context; + + return &sTeamContext; +} + + +/** Creates the message from the given context and sends it to the syslog + * daemon, if the priority mask matches. + * If the message couldn't be delivered, and LOG_CONS was set, it will + * redirect the message to stderr. + */ + +static void +send_syslog_message(syslog_context *context, int priority, const char *text, va_list args) +{ + // do we have to do anything? + if ((context->mask & LOG_MASK(priority)) == 0) + return; + + port_id port = find_port("syslog_daemon"); + if (port < B_OK) { + // apparently, there is no syslog daemon running; if asked + // for, print out the (simplified) message on stderr + if (context->options & LOG_CONS) { + if (context->ident[0]) + fprintf(stderr, "'%s' ", context->ident); + if (context->options & LOG_PID) + fprintf(stderr, "[%ld] ", find_thread(NULL)); + vfprintf(stderr, text, args); + } + return; + } + + char buffer[2048]; + syslog_message &message = *(syslog_message *)&buffer[0]; + + message.from = find_thread(NULL); + message.when = real_time_clock(); + message.options = context->options | priority; + strcpy(message.ident, context->ident); + + int length = vsnprintf(message.message, sizeof(buffer) - sizeof(syslog_message), text, args); + + while (write_port(port, SYSLOG_MESSAGE, &message, sizeof(syslog_message) + length) == B_INTERRUPTED); + // make sure the message gets send (if there is a valid port) +} + + +// #pragma mark - +// public API + + +void +closelog_team(void) +{ + // nothing to do here... +} + + +void +openlog_team(const char *ident, int options, int facility) +{ + if (ident != NULL) + strcpy(sTeamContext.ident, ident); + + sTeamContext.options = facility | options; +} + + +int +setlogmask_team(int priorityMask) +{ + sTeamContext.mask = priorityMask; +} + + +void +log_team(int priority, const char *message, ...) +{ + va_list args; + + va_start(args, message); + send_syslog_message(&sTeamContext, priority, message, args); + va_end(args); +} + + +void +closelog_thread(void) +{ + if (sThreadContextSlot < 0) + return; + + free(tls_get(sThreadContextSlot)); + *tls_address(sThreadContextSlot) = NULL; +} + + +void +openlog_thread(const char *ident, int options, int facility) +{ + syslog_context *context = get_context(); + + if (ident) + strcpy(context->ident, ident); + + context->options = options | facility; +} + + +int +setlogmask_thread(int priorityMask) +{ + syslog_context *context = get_context(); + context->mask = priorityMask; +} + + +void +log_thread(int priority, const char *message, ...) +{ + va_list args; + + va_start(args, message); + send_syslog_message(get_context(), priority, message, args); + va_end(args); +} + + +// #pragma mark - +// POSIX API - just uses the thread syslog functions + + +void +closelog(void) +{ + closelog_thread(); +} + + +void +openlog(const char *ident, int options, int facility) +{ + openlog_thread(ident, options, facility); +} + + +int +setlogmask(int priorityMask) +{ + setlogmask_thread(priorityMask); +} + + +void +syslog(int priority, const char *message, ...) +{ + va_list args; + + va_start(args, message); + send_syslog_message(get_context(), priority, message, args); + va_end(args); +} + +