mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:07:45 +00:00
LibC: syslog and lots of compat stuff for it
This is an implementation of syslog with some OpenBSD extensions. There is no syslogd support (so it only logs to dbgprintf/stderr), but otherwise is functional. Many weird defines are always present, because some syslog users in the wild check for their existence.
This commit is contained in:
parent
45fa3b7454
commit
bbee1c5b98
3 changed files with 285 additions and 1 deletions
|
@ -53,7 +53,8 @@ LIBC_OBJS = \
|
||||||
sched.o \
|
sched.o \
|
||||||
dlfcn.o \
|
dlfcn.o \
|
||||||
libgen.o \
|
libgen.o \
|
||||||
wchar.o
|
wchar.o \
|
||||||
|
syslog.o
|
||||||
|
|
||||||
ASM_OBJS = setjmp.ao crti.ao crtn.ao
|
ASM_OBJS = setjmp.ao crti.ao crtn.ao
|
||||||
|
|
||||||
|
|
132
Libraries/LibC/syslog.cpp
Normal file
132
Libraries/LibC/syslog.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Has to be defined before including due to legacy Unices
|
||||||
|
#define SYSLOG_NAMES 1
|
||||||
|
|
||||||
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// This implementation doesn't talk to a syslog server. Any options related to
|
||||||
|
// that are no-ops.
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// For implementation simplicity, we actually only use the re-entrant version
|
||||||
|
// of each function, and the version that isn't just redirects with a static
|
||||||
|
// struct to share.
|
||||||
|
static struct syslog_data global_log_data = {
|
||||||
|
.ident = nullptr,
|
||||||
|
.logopt = 0,
|
||||||
|
.facility = LOG_USER,
|
||||||
|
.maskpri = LOG_UPTO(LOG_DEBUG)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used when ident is null, since syslog traditionally prints the program's
|
||||||
|
// own name; the process name will always be the same unless we exec.
|
||||||
|
static char program_name_buffer[256];
|
||||||
|
static bool program_name_set = false;
|
||||||
|
|
||||||
|
// Convenience function for initialization and checking what string to use
|
||||||
|
// for the program name.
|
||||||
|
static const char* get_syslog_ident(struct syslog_data* data)
|
||||||
|
{
|
||||||
|
if (!program_name_set && data->ident == nullptr)
|
||||||
|
program_name_set = get_process_name(program_name_buffer, sizeof(program_name_buffer)) >= 0;
|
||||||
|
|
||||||
|
if (data->ident != nullptr)
|
||||||
|
return data->ident;
|
||||||
|
else if (program_name_set)
|
||||||
|
return program_name_buffer;
|
||||||
|
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void openlog_r(const char* ident, int logopt, int facility, struct syslog_data* data)
|
||||||
|
{
|
||||||
|
data->ident = ident;
|
||||||
|
data->logopt = logopt;
|
||||||
|
data->facility = facility;
|
||||||
|
// default value
|
||||||
|
data->maskpri = LOG_UPTO(LOG_DEBUG);
|
||||||
|
// would be where we connect to a daemon
|
||||||
|
}
|
||||||
|
|
||||||
|
void openlog(const char* ident, int logopt, int facility)
|
||||||
|
{
|
||||||
|
openlog_r(ident, logopt, facility, &global_log_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void closelog_r(struct syslog_data* data)
|
||||||
|
{
|
||||||
|
// would be where we disconnect from a daemon
|
||||||
|
// restore defaults
|
||||||
|
data->ident = nullptr;
|
||||||
|
data->logopt = 0;
|
||||||
|
data->facility = LOG_USER;
|
||||||
|
data->maskpri = LOG_UPTO(LOG_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void closelog(void)
|
||||||
|
{
|
||||||
|
closelog_r(&global_log_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setlogmask_r(int maskpri, struct syslog_data* data)
|
||||||
|
{
|
||||||
|
// Remember, this takes the input of LOG_MASK/LOG_UPTO
|
||||||
|
int old_maskpri = data->maskpri;
|
||||||
|
data->maskpri = maskpri;
|
||||||
|
return old_maskpri;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setlogmask(int maskpri)
|
||||||
|
{
|
||||||
|
return setlogmask_r(maskpri, &global_log_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syslog_r(int priority, struct syslog_data* data, const char* message, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, message);
|
||||||
|
vsyslog_r(priority, data, message, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syslog(int priority, const char* message, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, message);
|
||||||
|
vsyslog_r(priority, &global_log_data, message, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vsyslog_r(int priority, struct syslog_data* data, const char* message, va_list args)
|
||||||
|
{
|
||||||
|
StringBuilder combined;
|
||||||
|
|
||||||
|
int real_priority = LOG_PRI(priority);
|
||||||
|
// Lots of parens, but it just extracts the priority from combo and masks.
|
||||||
|
if (!(data->maskpri & LOG_MASK(real_priority)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Some metadata would be consumed by a syslog daemon, if we had one.
|
||||||
|
if (data->logopt & LOG_PID)
|
||||||
|
combined.appendf("%s[%d]: ", get_syslog_ident(data), getpid());
|
||||||
|
else
|
||||||
|
combined.appendf("%s: ", get_syslog_ident(data));
|
||||||
|
|
||||||
|
combined.appendvf(message, args);
|
||||||
|
String combined_string = combined.build();
|
||||||
|
|
||||||
|
if (data->logopt & LOG_CONS)
|
||||||
|
dbgputstr(combined_string.characters(), combined_string.length());
|
||||||
|
if (data->logopt & LOG_PERROR)
|
||||||
|
fputs(combined_string.characters(), stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vsyslog(int priority, const char* message, va_list args)
|
||||||
|
{
|
||||||
|
vsyslog_r(priority, &global_log_data, message, args);
|
||||||
|
}
|
||||||
|
}
|
151
Libraries/LibC/syslog.h
Normal file
151
Libraries/LibC/syslog.h
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
struct syslog_data {
|
||||||
|
const char* ident;
|
||||||
|
int logopt;
|
||||||
|
int facility;
|
||||||
|
int maskpri;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The severity of the message. This is ordered. */
|
||||||
|
#define LOG_EMERG 0
|
||||||
|
#define LOG_ALERT 1
|
||||||
|
#define LOG_CRIT 2
|
||||||
|
#define LOG_ERR 3
|
||||||
|
#define LOG_WARNING 4
|
||||||
|
#define LOG_NOTICE 5
|
||||||
|
#define LOG_INFO 6
|
||||||
|
#define LOG_DEBUG 7
|
||||||
|
|
||||||
|
/* Macros for masking out the priority of a combined priority */
|
||||||
|
#define LOG_PRIMASK (7)
|
||||||
|
#define LOG_PRI(priority) ((priority) & LOG_PRIMASK)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Many of these facilities don't really make sense anymore, but we keep them
|
||||||
|
* for compatability purposes.
|
||||||
|
*/
|
||||||
|
#define LOG_KERN ( 0 << 3)
|
||||||
|
#define LOG_USER ( 1 << 3)
|
||||||
|
#define LOG_MAIL ( 2 << 3)
|
||||||
|
#define LOG_DAEMON ( 3 << 3)
|
||||||
|
#define LOG_AUTH ( 4 << 3)
|
||||||
|
#define LOG_SYSLOG ( 5 << 3)
|
||||||
|
#define LOG_LPR ( 6 << 3)
|
||||||
|
#define LOG_NEWS ( 7 << 3)
|
||||||
|
#define LOG_UUCP ( 8 << 3)
|
||||||
|
#define LOG_CRON ( 9 << 3)
|
||||||
|
#define LOG_AUTHPRIV (10 << 3)
|
||||||
|
#define LOG_FTP (11 << 3)
|
||||||
|
/* glibc and OpenBSD reserve 12..15 for future system usage, we will too */
|
||||||
|
#define LOG_LOCAL0 (16 << 3)
|
||||||
|
#define LOG_LOCAL1 (17 << 3)
|
||||||
|
#define LOG_LOCAL2 (18 << 3)
|
||||||
|
#define LOG_LOCAL3 (19 << 3)
|
||||||
|
#define LOG_LOCAL4 (20 << 3)
|
||||||
|
#define LOG_LOCAL5 (21 << 3)
|
||||||
|
#define LOG_LOCAL6 (22 << 3)
|
||||||
|
#define LOG_LOCAL7 (23 << 3)
|
||||||
|
|
||||||
|
#define LOG_NFACILITIES 24
|
||||||
|
|
||||||
|
/* Macros to get the facility from a combined priority. */
|
||||||
|
#define LOG_FACMASK (~7)
|
||||||
|
#define LOG_FAC(priority) (((priority) & LOG_FACMASK) >> 3)
|
||||||
|
|
||||||
|
/* For masking logs, we use these macros with just the priority. */
|
||||||
|
#define LOG_MASK(priority) (1 << (priority))
|
||||||
|
#define LOG_UPTO(priority) (LOG_MASK(priority) + (LOG_MASK(priority) - 1))
|
||||||
|
|
||||||
|
/* Macro to make a combined priority. */
|
||||||
|
#define LOG_MAKEPRI(facility, priority) ((facility) | (priority))
|
||||||
|
|
||||||
|
/* Include a PID with the message. */
|
||||||
|
#define LOG_PID (1 << 0)
|
||||||
|
/* Log on the console. */
|
||||||
|
#define LOG_CONS (1 << 1)
|
||||||
|
/* Open the syslogd connection at the first call. (not implemented, default) */
|
||||||
|
#define LOG_ODELAY (1 << 2)
|
||||||
|
/* Open the syslogd connection immediately. (not implemented) */
|
||||||
|
#define LOG_NDELAY (1 << 3)
|
||||||
|
/* Log to stderr as well. */
|
||||||
|
#define LOG_PERROR (1 << 4)
|
||||||
|
|
||||||
|
/* This is useful to have, but has to be stored weirdly for compatibility. */
|
||||||
|
#ifdef SYSLOG_NAMES
|
||||||
|
/* Used for marking the fallback; some applications check for these defines. */
|
||||||
|
# define INTERNAL_NOPRI 0x10
|
||||||
|
# define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES << 3, 0)
|
||||||
|
|
||||||
|
typedef struct _code {
|
||||||
|
/*
|
||||||
|
* Most Unices define this as char*, but in C++, we have to define it as a
|
||||||
|
* const char* if we want to use string constants.
|
||||||
|
*/
|
||||||
|
const char* c_name;
|
||||||
|
int c_val;
|
||||||
|
} CODE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The names we use are the same as what glibc and OpenBSD use. We omit
|
||||||
|
* deprecated values in the hope that no one uses them. Sorted, as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CODE prioritynames[] = {
|
||||||
|
{ "alert", LOG_ALERT },
|
||||||
|
{ "crit", LOG_CRIT },
|
||||||
|
{ "debug", LOG_DEBUG },
|
||||||
|
{ "emerg", LOG_EMERG },
|
||||||
|
{ "err", LOG_ERR },
|
||||||
|
{ "info", LOG_INFO },
|
||||||
|
/* Fallback */
|
||||||
|
{ "none", INTERNAL_NOPRI },
|
||||||
|
{ "notice", LOG_NOTICE },
|
||||||
|
{ "warning", LOG_WARNING },
|
||||||
|
{ NULL, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
CODE facilitynames[] = {
|
||||||
|
{ "auth", LOG_AUTH },
|
||||||
|
{ "authpriv", LOG_AUTHPRIV },
|
||||||
|
{ "cron", LOG_CRON },
|
||||||
|
{ "daemon", LOG_DAEMON },
|
||||||
|
{ "ftp", LOG_FTP },
|
||||||
|
{ "kern", LOG_KERN },
|
||||||
|
{ "local0", LOG_LOCAL0 },
|
||||||
|
{ "local1", LOG_LOCAL1 },
|
||||||
|
{ "local2", LOG_LOCAL2 },
|
||||||
|
{ "local3", LOG_LOCAL3 },
|
||||||
|
{ "local4", LOG_LOCAL4 },
|
||||||
|
{ "local5", LOG_LOCAL5 },
|
||||||
|
{ "local6", LOG_LOCAL6 },
|
||||||
|
{ "local7", LOG_LOCAL7 },
|
||||||
|
{ "lpr", LOG_LPR },
|
||||||
|
{ "mail", LOG_MAIL },
|
||||||
|
/* Fallback */
|
||||||
|
{ "mark", INTERNAL_MARK },
|
||||||
|
{ "news", LOG_NEWS },
|
||||||
|
{ "syslog", LOG_SYSLOG },
|
||||||
|
{ "user", LOG_USER },
|
||||||
|
{ "uucp", LOG_UUCP },
|
||||||
|
{ NULL, -1 },
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The re-entrant versions are an OpenBSD extension we also implement. */
|
||||||
|
void syslog(int, const char*, ...);
|
||||||
|
void syslog_r(int, struct syslog_data*, const char*, ...);
|
||||||
|
void vsyslog(int, const char* message, va_list);
|
||||||
|
void vsyslog_r(int, struct syslog_data* data, const char* message, va_list);
|
||||||
|
void openlog(const char*, int, int);
|
||||||
|
void openlog_r(const char*, int, int, struct syslog_data*);
|
||||||
|
void closelog(void);
|
||||||
|
void closelog_r(struct syslog_data*);
|
||||||
|
int setlogmask(int);
|
||||||
|
int setlogmask_r(int, struct syslog_data*);
|
||||||
|
|
||||||
|
__END_DECLS
|
Loading…
Add table
Add a link
Reference in a new issue