1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:37:35 +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:
Calvin Buckley 2019-10-14 16:25:57 -03:00 committed by Andreas Kling
parent 45fa3b7454
commit bbee1c5b98
3 changed files with 285 additions and 1 deletions

View file

@ -53,7 +53,8 @@ LIBC_OBJS = \
sched.o \
dlfcn.o \
libgen.o \
wchar.o
wchar.o \
syslog.o
ASM_OBJS = setjmp.ao crti.ao crtn.ao

132
Libraries/LibC/syslog.cpp Normal file
View 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
View 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