28 RCSID(
"$Id: a4a1d89fff3d499509b384c7986132f06759dc0b $")
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/rad_assert.h>
33 #ifdef HAVE_SYS_STAT_H
34 # include <sys/stat.h>
55 {
": Debug: ",
L_DBG },
61 {
": Error: ",
L_ERR },
79 #define VTC_RED "\x1b[31m"
80 #define VTC_YELLOW "\x1b[33m"
81 #define VTC_BOLD "\x1b[1m"
82 #define VTC_RESET "\x1b[0m"
112 {
"kern", LOG_KERN },
115 {
"user", LOG_USER },
118 {
"mail", LOG_MAIL },
121 {
"daemon", LOG_DAEMON },
124 {
"auth", LOG_AUTH },
130 {
"news", LOG_NEWS },
133 {
"uucp", LOG_UUCP },
136 {
"cron", LOG_CRON },
139 {
"authpriv", LOG_AUTHPRIV },
145 {
"local0", LOG_LOCAL0 },
148 {
"local1", LOG_LOCAL1 },
151 {
"local2", LOG_LOCAL2 },
154 {
"local3", LOG_LOCAL3 },
157 {
"local4", LOG_LOCAL4 },
160 {
"local5", LOG_LOCAL5 },
163 {
"local6", LOG_LOCAL6 },
166 {
"local7", LOG_LOCAL7 },
179 {
"emergency", LOG_EMERG },
182 {
"alert", LOG_ALERT },
185 {
"critical", LOG_CRIT },
188 {
"error", LOG_ERR },
191 {
"warning", LOG_WARNING },
194 {
"notice", LOG_NOTICE },
197 {
"info", LOG_INFO },
200 {
"debug", LOG_DEBUG },
234 if ((stderr_fd > 0) && (stdout_fd > 0)) {
235 dup2(stderr_fd, STDOUT_FILENO);
236 dup2(stdout_fd, STDERR_FILENO);
240 if (default_log.
fd > 0) {
241 dup2(default_log.
fd, STDOUT_FILENO);
242 dup2(default_log.
fd, STDERR_FILENO);
261 rate_limit = daemonize;
278 stdout_fd = dup(STDOUT_FILENO);
279 stderr_fd = dup(STDERR_FILENO);
282 devnull = open(
"/dev/null", O_RDWR);
297 log->
fd = STDOUT_FILENO;
307 if (rad_debug_lvl || !daemonize) {
308 dup2(STDOUT_FILENO, STDERR_FILENO);
310 dup2(devnull, STDERR_FILENO);
315 log->
fd = STDERR_FILENO;
325 if (rad_debug_lvl || !daemonize) {
326 dup2(STDERR_FILENO, STDOUT_FILENO);
328 dup2(devnull, STDOUT_FILENO);
337 dup2(devnull, STDOUT_FILENO);
338 dup2(devnull, STDERR_FILENO);
340 }
else if (rad_debug_lvl) {
345 dup2(log->
fd, STDOUT_FILENO);
346 dup2(log->
fd, STDERR_FILENO);
356 dup2(devnull, STDOUT_FILENO);
357 dup2(devnull, STDERR_FILENO);
393 len +=
strlcpy(buffer + len,
fr_int2str(colours, type,
""),
sizeof(buffer) - len) ;
402 unsan = buffer + len;
413 if ((rad_debug_lvl != 1) && (rad_debug_lvl != 2)) {
416 timeval = time(NULL);
417 CTIME_R(&timeval, buffer + len,
sizeof(buffer) - len - 1);
419 len = strlen(buffer);
420 len +=
strlcpy(buffer + len,
fr_int2str(levels, type,
": "),
sizeof(buffer) - len);
421 }
else goto add_prefix;
424 if (len <
sizeof(buffer))
switch (type) {
426 len +=
strlcpy(buffer + len,
"WARNING: ",
sizeof(buffer) - len);
430 len +=
strlcpy(buffer + len,
"ERROR: ",
sizeof(buffer) - len);
438 if (len <
sizeof(buffer)) {
439 len +=
vsnprintf(buffer + len,
sizeof(buffer) - len - 1, msg, ap);
445 for (p = (
unsigned char *)unsan; *p !=
'\0'; p++) {
468 if (colourise && (len <
sizeof(buffer))) {
472 if (len < (
sizeof(buffer) - 2)) {
474 buffer[len + 1] =
'\0';
476 buffer[
sizeof(buffer) - 2] =
'\n';
477 buffer[
sizeof(buffer) - 1] =
'\0';
480 switch (default_log.
dst) {
511 syslog(type,
"%s", buffer);
518 return write(default_log.
fd, buffer, strlen(buffer));
544 if (((type &
L_DBG) == 0) || (rad_debug_lvl > 0)) {
581 if ((type &
L_DBG) && (lvl <= rad_debug_lvl))
return true;
590 if (rate_limit || (rad_debug_lvl < 1))
return true;
616 if ((type &
L_DBG) &&
617 ((request->
log.func && (lvl <= request->log.lvl)) ||
618 ((rad_debug_lvl != 0) && (lvl <= rad_debug_lvl)))) {
636 char const *filename = default_log.
file;
642 char const *extra =
"";
651 if ((type &
L_DBG) != 0) {
656 #ifdef WITH_COMMAND_SOCKET
665 if (request->
log.output) {
667 fp = fopen(request->
log.output->file,
"a");
669 #if defined(HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
671 # ifdef HAVE_FOPENCOOKIE
672 cookie_io_functions_t io;
680 io.write = request->
log.output->cookie_write;
682 fp = fopencookie(request->
log.output->cookie,
"w", io);
684 fp = funopen(request->
log.output->cookie,
685 NULL, request->
log.output->cookie_write, NULL, NULL);
699 request->
log.func = NULL;
706 request->
log.func = rl;
712 p = strrchr(buffer, FR_DIR_SEP);
715 if (
rad_mkdir(buffer, S_IRWXU, -1, -1) < 0) {
722 fp = fopen(buffer,
"a");
736 vsnprintf(buffer + len,
sizeof(buffer) - len, msg, aq);
742 indent = request->
log.indent >
sizeof(
spaces) ?
753 timeval = time(NULL);
759 ASCTIME_R(&utc, time_buff,
sizeof(time_buff));
763 CTIME_R(&timeval, time_buff,
sizeof(time_buff));
769 p = strrchr(time_buff,
'\n');
773 fprintf(fp,
"(%u) %s%s%s: %.*s%s\n",
775 request->
module, indent, spaces, buffer);
777 fprintf(fp,
"(%u) %s%s%.*s%s\n",
779 indent, spaces, buffer);
804 request->
module, indent, spaces, extra, buffer);
807 indent, spaces, extra, buffer);
827 if (!request->
log.func && !(type &
L_DBG))
return;
830 if (request->
log.func) request->
log.func(type, lvl, request, msg, ap);
831 else if (!(type & L_DBG))
vradlog_request(type, lvl, request, msg, ap);
858 if (request->
log.func) request->
log.func(type, lvl, request, msg, ap);
874 char const *msg,
size_t idx,
char const *error)
881 if (idx >=
sizeof(spaces)) {
882 size_t offset = (idx - (
sizeof(
spaces) - 1)) + (
sizeof(spaces) * 0.75);
892 indent = request->
log.indent;
893 request->
log.indent = 0;
896 radlog_request(type, lvl, request,
"%s%.*s^ %s", prefix, (
int) idx, spaces, error);
898 request->
log.indent = indent;
PUBLIC int vsnprintf(char *string, size_t length, char *format, va_list args)
Only displayed when debugging is enabled.
static const FR_NAME_NUMBER levels[]
Maps log categories to message prefixes.
Send log messages to a FILE*, via fopencookie()
void(* radlog_func_t)(log_type_t lvl, log_lvl_t priority, REQUEST *, char const *, va_list ap)
struct rad_request::@7 log
Less severe warning only displayed when debugging is enabled.
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
bool debug_enabled(log_type_t type, log_lvl_t lvl)
Whether a server debug message should be logged.
static int stderr_fd
The original unmolested stderr file descriptor.
Less severe error only displayed when debugging is enabled.
size_t rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes the raw string such that it should be safe to use as part of a file path. ...
static bool rate_limit
Whether repeated log entries should be rate limited.
#define VTC_BOLD
Embolden following text.
void fr_strerror_printf(char const *fmt,...)
Log to thread local error buffer.
unsigned int number
Monotonically increasing request number. Reset on server restart.
static int stdout_fd
The original unmolested stdout file descriptor.
int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid)
Create possibly many directories.
bool radlog_debug_enabled(log_type_t type, log_lvl_t lvl, REQUEST *request)
Whether a request specific debug message should be logged.
void radlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg,...)
Martial variadic log arguments into a va_list and pass to normal logging functions.
#define VTC_RED
Colour following text red.
int vradlog(log_type_t type, char const *msg, va_list ap)
Send a server log message to its destination.
const FR_NAME_NUMBER syslog_facility_table[]
Syslog facility table.
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
int radlog(log_type_t type, char const *msg,...)
Send a server log message to its destination.
void radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg,...)
Martial variadic log arguments into a va_list and pass to error logging functions.
bool rate_limit_enabled(void)
Whether rate limiting is enabled.
log_lvl_t rad_debug_lvl
Global debugging level.
static char const spaces[]
void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap)
Send a log message to its destination, possibly including fields from the request.
void void vmodule_failure_msg(REQUEST *request, char const *fmt, va_list ap) CC_HINT(format(printf
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
char const * file
Path to log file.
static char const * prefix
#define VTC_RESET
Reset terminal text to default style/colour.
#define VTC_YELLOW
Colour following text yellow.
int radlog_init(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
static int _restore_std(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Error only displayed when debugging is enabled.
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
bool colourise
Prefix log messages with VT100 escape codes to change text colour.
int fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Warning only displayed when debugging is enabled.
log_dst_t dst
Log destination.
static const FR_NAME_NUMBER colours[]
Maps log categories to VT100 style/colour escape sequences.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
const FR_NAME_NUMBER syslog_severity_table[]
Syslog severity table.
const FR_NAME_NUMBER log_str2dst[]
char const * module
Module the request is currently being processed by.
static int radlog_always(log_type_t type, char const *msg,...) CC_HINT(format(printf
Send a server log message to its destination without evaluating its debug level.
int fd
File descriptor to write messages to.
void radlog_request_marker(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, size_t idx, char const *error)
Write the string being parsed, and a marker showing where the parse error occurred.
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)