The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
log.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Support functions for logging in FreeRADIUS libraries
18 *
19 * @file src/lib/util/log.c
20 *
21 * @copyright 2003,2006 The FreeRADIUS server project
22 */
23RCSID("$Id: 797aa76d8c9081b17fce2afac0078e102bad9379 $")
24
25#include <freeradius-devel/util/debug.h>
26#include <freeradius-devel/util/log.h>
27#include <freeradius-devel/util/print.h>
28#include <freeradius-devel/util/syserror.h>
29#include <freeradius-devel/util/value.h>
30
31#include <fcntl.h>
32#include <stdatomic.h>
33#ifdef HAVE_FEATURES_H
34# include <features.h>
35#endif
36#ifdef HAVE_SYSLOG_H
37# include <syslog.h>
38#endif
39
40FILE *fr_log_fp = NULL;
42
43static _Thread_local TALLOC_CTX *fr_log_pool;
44
45/** Latched once shutdown has freed every thread's log pool
46 *
47 * `fr_atexit_thread_trigger_all()` runs every registered thread destructor
48 * on the calling (main) thread, so it frees the log pool memory for threads
49 * whose TLS slot it can't reach (librdkafka's bg threads, anything spawned
50 * by a third-party library that bypasses our schedule). Those threads
51 * still hold the now-dangling pointer in their `_Thread_local fr_log_pool`,
52 * and will hand it to `talloc_new` on the next log call - "Bad talloc magic
53 * value" abort.
54 *
55 * Once set, `fr_log_pool_init()` ignores the TLS slot entirely and returns
56 * NULL; downstream `talloc_new(NULL)` / `talloc_asprintf(NULL, ...)` calls
57 * just allocate top-level chunks for the duration of the log line. No
58 * pooling, no TLS, safe from any thread.
59 */
60static atomic_bool log_pools_disabled;
61
63static fr_event_list_t *log_el; //!< Event loop we use for process logging data.
64
65static int stderr_fd = -1; //!< The original unmolested stderr file descriptor
66static int stdout_fd = -1; //!< The original unmolested stdout file descriptor
67
68static fr_log_fd_event_ctx_t stdout_ctx; //!< Logging ctx for stdout.
69static fr_log_fd_event_ctx_t stderr_ctx; //!< Logging ctx for stderr.
70
71static int stdout_pipe[2]; //!< Pipe we use to transport stdout data.
72static int stderr_pipe[2]; //!< Pipe we use to transport stderr data.
73
74static FILE *devnull; //!< File handle for /dev/null
75
76bool fr_log_rate_limit = true; //!< Whether repeated log entries should be rate limited
77
78static _Thread_local fr_log_type_t log_msg_type;//!< The type of the last message logged.
79 ///< Mainly uses for syslog.
80
81/** Canonicalize error strings, removing tabs, and generate spaces for error marker
82 *
83 * @note talloc_free must be called on the buffer returned in spaces and text
84 *
85 * Used to produce error messages such as this:
86 @verbatim
87 I'm a string with a parser # error
88 ^ Unexpected character in string
89 @endverbatim
90 *
91 * With code resembling this:
92 @code{.c}
93 ERROR("%s", parsed_str);
94 ERROR("%s^ %s", space, text);
95 @endcode
96 *
97 * @todo merge with above function (log_request_marker)
98 *
99 * @param sp Where to write a dynamically allocated buffer of spaces used to indent the error text.
100 * @param text Where to write the canonicalized version of fmt (the error text).
101 * @param ctx to allocate the spaces and text buffers in.
102 * @param slen of error marker. Expects negative integer value, as returned by parse functions.
103 * @param fmt to canonicalize.
104 */
105void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
106{
107 size_t offset, prefix, suffix;
108 char *spaces, *p;
109 char const *start;
110 char *value;
111 size_t inlen;
112
113 offset = -slen;
114
115 inlen = strlen(fmt);
116 start = fmt;
117 prefix = suffix = 0;
118
119 if (offset == inlen + 1) offset = inlen;
120
121 /*
122 * Catch bad callers.
123 */
124 if (offset > inlen) {
125 *sp = talloc_asprintf(ctx, "Invalid offset %zu > %zu", offset, inlen);
126 *text = talloc_strdup(ctx, fmt);
127 return;
128 }
129
130 /*
131 * Too many characters before the inflection point. Skip
132 * leading text until we have only 45 characters before it.
133 */
134 if (offset > 30) {
135 size_t skip = offset - 30;
136
137 start += skip;
138 inlen -= skip;
139 offset -= skip;
140 prefix = 4;
141 }
142
143 /*
144 * Too many characters after the inflection point,
145 * truncate it to 30 characters after the inflection
146 * point.
147 */
148 if (inlen > (offset + 30)) {
149 inlen = offset + 30;
150 suffix = 4;
151 }
152
153 /*
154 * Allocate an array to hold just the text we need.
155 */
156 value = talloc_array(ctx, char, prefix + inlen + 1 + suffix);
157 if (prefix) {
158 memcpy(value, "... ", 4);
159 }
160 memcpy(value + prefix, start, inlen);
161 if (suffix) {
162 memcpy(value + prefix + inlen, "...", 3);
163 value[prefix + inlen + 3] = '\0';
164 }
165 value[prefix + inlen + suffix] = '\0';
166
167 /*
168 * Smash tabs to spaces for the input string.
169 */
170 for (p = value; *p != '\0'; p++) {
171 if (*p == '\t') *p = ' ';
172 }
173
174 /*
175 * Allocate the spaces array
176 */
177 spaces = talloc_array(ctx, char, prefix + offset + 1);
178 memset(spaces, ' ', prefix + offset);
179 spaces[prefix + offset] = '\0';
180
181 *sp = spaces;
182 *text = value;
183}
184
185/** Function to provide as the readable callback to the event loop
186 *
187 * Writes any data read from a file descriptor to the request log,
188 * tries very hard not to chop lines in the middle, but will split
189 * at 1024 byte boundaries if forced to.
190 *
191 * @param[in] el UNUSED
192 * @param[in] fd UNUSED
193 * @param[in] flags UNUSED
194 * @param[in] uctx Pointer to a log_fd_event_ctx_t
195 */
196void fr_log_fd_event(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
197{
198 char buffer[1024] = "";
199 fr_log_fd_event_ctx_t *log_info = uctx;
200 fr_sbuff_t sbuff;
201 fr_sbuff_marker_t m_start, m_end;
202
203 fr_sbuff_term_t const line_endings = FR_SBUFF_TERMS(L("\n"), L("\r"));
204
205 if (log_info->lvl < fr_debug_lvl) {
206 while (read(fd, buffer, sizeof(buffer)) > 0);
207 return;
208 }
209
210#ifndef NDEBUG
211 memset(buffer, 0x42, sizeof(buffer));
212#endif
213
214 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
215 fr_sbuff_marker(&m_start, &sbuff);
216 fr_sbuff_marker(&m_end, &sbuff);
217
218 for (;;) {
219 ssize_t slen;
220
221 slen = read(fd, fr_sbuff_current(&m_end), fr_sbuff_remaining(&m_end));
222 if ((slen < 0) && (errno == EINTR)) continue;
223
224 if (slen > 0) fr_sbuff_advance(&m_end, slen);
225
226 while (fr_sbuff_ahead(&m_end) > 0) {
227 fr_sbuff_adv_until(&sbuff, fr_sbuff_ahead(&m_end), &line_endings, '\0');
228
229 /*
230 * Incomplete line, try and read the rest.
231 */
232 if ((slen > 0) && (fr_sbuff_used(&m_start) > 0) &&
233 !fr_sbuff_is_terminal(&sbuff, &line_endings)) {
234 break;
235 }
236
237 fr_log(log_info->dst, log_info->type,
238 __FILE__, __LINE__,
239 "%s%s%pV",
240 log_info->prefix ? log_info->prefix : "",
241 log_info->prefix ? " - " : "",
243
244 fr_sbuff_advance(&sbuff, 1); /* Skip the whitespace */
245 fr_sbuff_set(&m_start, &sbuff);
246 }
247
248 /*
249 * Error or done
250 */
251 if (slen <= 0) break;
252
253 /*
254 * Clear out the existing data
255 */
256 fr_sbuff_shift(&sbuff, fr_sbuff_used(&m_start), false);
257 }
258}
259
260/** Maps log categories to message prefixes
261 */
263 { L("Debug : "), L_DBG },
264 { L("Info : "), L_INFO },
265 { L("Warn : "), L_WARN },
266 { L("Error : "), L_ERR },
267 { L("Auth : "), L_AUTH },
268 { L("INFO : "), L_DBG_INFO },
269 { L("WARN : "), L_DBG_WARN },
270 { L("ERROR : "), L_DBG_ERR },
271 { L("WARN : "), L_DBG_WARN_REQ },
272 { L("ERROR : "), L_DBG_ERR_REQ }
273};
275
276/** @name VT100 escape sequences
277 *
278 * These sequences may be written to VT100 terminals to change the
279 * colour and style of the text.
280 *
281 @code{.c}
282 fprintf(stdout, VTC_RED "This text will be coloured red" VTC_RESET);
283 @endcode
284 * @{
285 */
286#define VTC_RED "\x1b[31m" //!< Colour following text red.
287#define VTC_YELLOW "\x1b[33m" //!< Colour following text yellow.
288#define VTC_BOLD "\x1b[1m" //!< Embolden following text.
289#define VTC_RESET "\x1b[0m" //!< Reset terminal text to default style/colour.
290/** @} */
291
292/** Maps log categories to VT100 style/colour escape sequences
293 */
304
305
306bool log_dates_utc = false;
307
309 .colourise = false, //!< Will be set later. Should be off before we do terminal detection.
310 .fd = STDOUT_FILENO,
311 .dst = L_DST_STDOUT,
312 .file = NULL,
313 .timestamp = L_TIMESTAMP_AUTO
314};
315
316/** Cleanup the memory pool used by vlog_request
317 *
318 */
319static int _fr_log_pool_free(void *arg)
320{
321 if (talloc_free(arg) < 0) return -1;
322 fr_log_pool = NULL;
323 return 0;
324}
325
326/** Disable per-thread log pools for the rest of the process lifetime
327 *
328 * Call this from the main thread immediately after
329 * `fr_atexit_thread_trigger_all()`, which frees every other thread's log
330 * pool but can't reset their `_Thread_local` slot. After this returns,
331 * subsequent `fr_log` calls fall back to `talloc_new(NULL)` instead of
332 * touching the (now dangling) TLS pool pointer.
333 */
338
339/** talloc ctx to use when composing log messages
340 *
341 * Functions must ensure that they allocate a new ctx from the one returned
342 * here, and that this ctx is freed before the function returns.
343 *
344 * @return talloc pool to use for scratch space, or NULL if pools have been
345 * disabled - callers must tolerate a NULL return.
346 */
347TALLOC_CTX *fr_log_pool_init(void)
348{
349 TALLOC_CTX *pool;
350
351 /*
352 * Once main has signalled shutdown the TLS slot may be a
353 * dangling pointer for any thread we don't own (librdkafka's
354 * bg threads etc.) - skip the pool entirely.
355 */
357
358 pool = fr_log_pool;
359 if (unlikely(!pool)) {
360 if (fr_atexit_is_exiting()) return NULL; /* No new pools if we're exiting */
361
362 pool = talloc_pool(NULL, 16384);
363 if (!pool) {
364 fr_perror("Failed allocating memory for vlog_request_pool");
365 return NULL;
366 }
368 }
369
370 return pool;
371}
372
373/** Send a server log message to its destination
374 *
375 * @param[in] log destination.
376 * @param[in] type of log message.
377 * @param[in] file src file the log message was generated in.
378 * @param[in] line number the log message was generated on.
379 * @param[in] arg_names source text of each substitution argument, or NULL.
380 * @param[in] fmt with printf style substitution tokens.
381 * @param[in] ap Substitution arguments.
382 */
383void _fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
384 UNUSED char const * const arg_names[], char const *fmt, va_list ap)
385{
386 int colourise = log->colourise;
387 char *buffer;
388 TALLOC_CTX *pool, *thread_log_pool;
389 char const *fmt_colour = "";
390 char const *fmt_location = "";
391 char fmt_time[50];
392 char const *fmt_type = "";
393 char *fmt_msg;
394
395 static char const *spaces = " "; /* 40 */
396
397 fmt_time[0] = '\0';
398
399 /*
400 * If we don't want any messages, then
401 * throw them away.
402 */
403 if (log->dst == L_DST_NULL) return;
404
405 thread_log_pool = fr_log_pool_init();
406 pool = talloc_new(thread_log_pool); /* Track our local allocations */
407
408 /*
409 * Set colourisation
410 */
411 if (colourise) {
412 fmt_colour = fr_table_str_by_value(colours, type, NULL);
413 if (!fmt_colour) colourise = false;
414 }
415
416 /*
417 * Print src file/line
418 */
419 if (log->line_number) {
420 size_t len;
421 int pad = 0;
422 char *str;
423
424 str = talloc_asprintf(pool, "%s:%i", file, line);
425 len = talloc_strlen(str);
426
427 /*
428 * Only increase the indent
429 */
430 if (len > location_indent) {
432 } else {
433 pad = location_indent - len;
434 }
435
436 fmt_location = talloc_asprintf_append_buffer(str, "%.*s : ", pad, spaces);
437 }
438 /*
439 * Determine if we need to add a timestamp to the start of the message
440 */
441 switch (log->timestamp) {
442 case L_TIMESTAMP_OFF:
443 break;
444
445 /*
446 * If we're not logging to syslog, and the debug level is -xxx
447 * then log timestamps by default.
448 */
449 case L_TIMESTAMP_AUTO:
450 if (log->dst == L_DST_SYSLOG) break;
451 if ((log->dst != L_DST_FILES) && (fr_debug_lvl <= L_DBG_LVL_2)) break;
453
454 case L_TIMESTAMP_ON:
455 {
457 fr_sbuff_t time_sbuff = FR_SBUFF_OUT(fmt_time, sizeof(fmt_time));
458 fr_unix_time_to_str(&time_sbuff, now, FR_TIME_RES_USEC, log->dates_utc);
459 break;
460 }
461 }
462
463 /*
464 * Add ERROR or WARNING prefixes to messages not going to
465 * syslog. It's redundant for syslog because of syslog
466 * facilities.
467 */
468 if (log->dst != L_DST_SYSLOG) {
469 /*
470 * We always print "WARN" and "ERROR" prefixes.
471 */
472 switch (type) {
473 case L_DBG_WARN:
474 case L_DBG_ERR:
475 fmt_type = fr_table_str_by_value(fr_log_levels, type, NULL);
476 break;
477
478 default:
479 /*
480 * Otherwise, print the other info levels only if we're asked to print the level,
481 * and we're not colourizing the output. If we're colourizing the output, then
482 * the colors indicate the debug level (info, warning, error), and we don't need
483 * any prefix.
484 */
485 if (!log->print_level || log->colourise) break;
486
487 if (fmt_time[0] != '\0') {
488 fmt_type = fr_table_str_by_value(fr_log_levels, type, ": ");
489 break;
490 }
491
492 /*
493 * The mixed-case "Debug", "Info", "Warn", and "Error" prefixes are
494 * only useful when the messages are timestamped, i.e. when the server
495 * runs as a daemon, or at high debug levels. A "radiusd -X" session
496 * has no timestamps, so print no prefix at all for "Debug" and
497 * "Info", and use the all-caps prefixes of the equivalent debug
498 * levels for warnings and errors.
499 */
500 switch (type) {
501 case L_DBG:
502 case L_INFO:
503 break;
504
505 case L_WARN:
507 break;
508
509 case L_ERR:
511 break;
512
513 default:
514 fmt_type = fr_table_str_by_value(fr_log_levels, type, ": ");
515 break;
516 }
517 break;
518 }
519 }
520
521 /*
522 * Sanitize output.
523 *
524 * Most strings should be escaped before they get here.
525 */
526 {
527 char *p, *end;
528
529 p = fmt_msg = fr_vasprintf(pool, fmt, ap);
530 end = p + talloc_strlen(fmt_msg);
531
532 /*
533 * Filter out control chars and non UTF8 chars
534 */
535 for (p = fmt_msg; p < end; p++) {
536 int clen;
537
538 switch (*p) {
539 case '\r':
540 case '\n':
541 *p = ' ';
542 break;
543
544 case '\t':
545 continue;
546
547 default:
548 clen = fr_utf8_char((uint8_t *)p, -1);
549 if (!clen) {
550 *p = '?';
551 continue;
552 }
553 p += (clen - 1);
554 break;
555 }
556 }
557 }
558
559 switch (log->dst) {
560
561#ifdef HAVE_SYSLOG_H
562 case L_DST_SYSLOG:
563 {
564 int syslog_priority = L_DBG;
565
566 switch (type) {
567 case L_DBG:
568 case L_DBG_INFO:
569 case L_DBG_WARN:
570 case L_DBG_ERR:
571 case L_DBG_ERR_REQ:
572 case L_DBG_WARN_REQ:
573 syslog_priority= LOG_DEBUG;
574 break;
575
576 case L_INFO:
577 syslog_priority = LOG_INFO;
578 break;
579
580 case L_WARN:
581 syslog_priority = LOG_WARNING;
582 break;
583
584 case L_ERR:
585 syslog_priority = LOG_ERR;
586 break;
587
588 case L_AUTH:
589 syslog_priority = LOG_AUTH | LOG_INFO;
590 break;
591 }
592 syslog(syslog_priority,
593 "%s" /* time */
594 "%s" /* time sep */
595 "%s", /* message */
596 fmt_time,
597 fmt_time[0] ? ": " : "",
598 fmt_msg);
599 }
600 break;
601#endif
602
603 case L_DST_FILES:
604 case L_DST_STDOUT:
605 case L_DST_STDERR:
606 {
607 buffer = talloc_asprintf(pool,
608 "%s" /* colourise */
609 "%s" /* location */
610 "%s" /* time */
611 "%s" /* time sep */
612 "%s" /* message type */
613 "%s" /* message */
614 "%s" /* colourise reset */
615 "\n",
616 colourise ? fmt_colour : "",
617 fmt_location,
618 fmt_time,
619 fmt_time[0] ? ": " : "",
620 fmt_type,
621 fmt_msg,
622 colourise ? VTC_RESET : "");
623
624 /*
625 * This function is in a utility library, and can't do anything about write errors,
626 * except for writes to stdout(). We can't recover from those, so we might as well exit
627 * rather than continue to write to a place which doesn't exist.
628 */
629 if (write(log->fd, buffer, talloc_strlen(buffer)) < 0) {
630 if (log->dst == L_DST_STDOUT) {
631 switch (errno) {
632 case EPIPE:
633 case EBADF:
634 fr_exit_now(EXIT_FAILURE);
635
636 default:
637 break;
638 }
639 }
640 }
641 }
642 break;
643
644 default:
645 case L_DST_NULL: /* should have been caught above */
646 break;
647 }
648
649 talloc_free(pool); /* clears all temporary allocations */
650
651 return;
652}
653
654/** Send a server log message to its destination
655 *
656 * @param log destination.
657 * @param type of log message.
658 * @param file where the log message originated
659 * @param line where the log message originated
660 * @param arg_names source text of each substitution argument, or NULL.
661 * @param fmt with printf style substitution tokens.
662 * @param ... Substitution arguments.
663 */
664void _fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
665 char const * const arg_names[], char const *fmt, ...)
666{
667 va_list ap;
668
669 /*
670 * Non-debug message, or debugging is enabled. Log it.
671 */
672 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
673
674 va_start(ap, fmt);
675 _fr_vlog(log, type, file, line, arg_names, fmt, ap);
676 va_end(ap);
677}
678
679/** Drain any outstanding messages from the fr_strerror buffers
680 *
681 * This function drains any messages from fr_strerror buffer prefixing
682 * the first message with fmt + args.
683 *
684 * If a prefix is specified in rules, this is prepended to all lines
685 * logged. The prefix is useful for adding context, i.e. configuration
686 * file and line number information.
687 *
688 * @param[in] log destination.
689 * @param[in] type of log message.
690 * @param[in] file src file the log message was generated in.
691 * @param[in] line number the log message was generated on.
692 * @param[in] f_rules for printing multiline errors.
693 * @param[in] arg_names source text of each substitution argument, or NULL.
694 * @param[in] fmt with printf style substitution tokens.
695 * @param[in] ap Substitution arguments.
696 */
697void _fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
698 fr_log_perror_format_t const *f_rules,
699 UNUSED char const * const arg_names[], char const *fmt, va_list ap)
700{
701 char const *error;
702 static fr_log_perror_format_t default_f_rules;
703
704 TALLOC_CTX *thread_log_pool;
705 fr_sbuff_marker_t prefix_m;
706
707 fr_sbuff_t sbuff;
709
710 /*
711 * Non-debug message, or debugging is enabled. Log it.
712 */
713 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
714
715 if (!f_rules) f_rules = &default_f_rules;
716
717 thread_log_pool = fr_log_pool_init();
718
719 /*
720 * Setup the aggregation buffer
721 */
722 fr_sbuff_init_talloc(thread_log_pool, &sbuff, &tctx, 1024, 16384);
723
724 /*
725 * Add the prefix for the first line
726 */
727 if (f_rules->first_prefix) (void) fr_sbuff_in_strcpy(&sbuff, f_rules->first_prefix);
728
729 /*
730 * Add the (optional) message, and/or (optional) error
731 * with the error_sep.
732 * i.e. <msg>: <error>
733 */
734 error = fr_strerror_pop();
735
736 if (!error && !fmt) return; /* NOOP */
737
738 if (fmt) {
739 va_list aq;
740
741 va_copy(aq, ap);
742 fr_sbuff_in_vsprintf(&sbuff, fmt, aq);
743 va_end(aq);
744 }
745
746 if (error && (fmt || f_rules->first_prefix)) {
747 if (fmt) (void) fr_sbuff_in_strcpy(&sbuff, ": ");
748 (void) fr_sbuff_in_strcpy(&sbuff, error);
749 }
750
751 error = fr_sbuff_start(&sbuff); /* may not be talloced with const */
752
753 /*
754 * Log the first line
755 */
756 fr_log(log, type, file, line, "%s", error);
757
758 fr_sbuff_set_to_start(&sbuff);
759 if (f_rules->subsq_prefix) {
760 (void) fr_sbuff_in_strcpy(&sbuff, f_rules->subsq_prefix);
761 fr_sbuff_marker(&prefix_m, &sbuff);
762 }
763
764 /*
765 * Print out additional error lines
766 */
767 while ((error = fr_strerror_pop())) {
768 if (f_rules->subsq_prefix) {
769 fr_sbuff_set(&sbuff, &prefix_m);
770 (void) fr_sbuff_in_strcpy(&sbuff, error); /* may not be talloced with const */
771 error = fr_sbuff_start(&sbuff);
772 }
773
774 fr_log(log, type, file, line, "%s", error);
775 }
776
777 talloc_free(sbuff.buff);
778}
779
780/** Drain any outstanding messages from the fr_strerror buffers
781 *
782 * This function drains any messages from fr_strerror buffer adding a prefix (fmt)
783 * to the first message.
784 *
785 * @param[in] log destination.
786 * @param[in] type of log message.
787 * @param[in] file src file the log message was generated in.
788 * @param[in] line number the log message was generated on.
789 * @param[in] rules for printing multiline errors.
790 * @param[in] arg_names source text of each substitution argument, or NULL.
791 * @param[in] fmt with printf style substitution tokens.
792 * @param[in] ... Substitution arguments.
793 */
794void _fr_log_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
795 fr_log_perror_format_t const *rules,
796 char const * const arg_names[], char const *fmt, ...)
797{
798 va_list ap;
799
800 va_start(ap, fmt);
801 _fr_vlog_perror(log, type, file, line, rules, arg_names, fmt, ap);
802 va_end(ap);
803}
804
805DIAG_OFF(format-nonliteral)
806/** Print out an error marker
807 *
808 * @param[in] log destination.
809 * @param[in] type of log message.
810 * @param[in] file src file the log message was generated in.
811 * @param[in] line number the log message was generated on.
812 * @param[in] str Subject string we're printing a marker for.
813 * @param[in] str_len Subject string length. Use SIZE_MAX for the
814 * length of the string.
815 * @param[in] marker_idx Where to place the marker. May be negative.
816 * @param[in] marker text to print at marker_idx.
817 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
818 * @param[in] ... Arguments for line_prefix_fmt.
819 */
820void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
821 char const *str, size_t str_len,
822 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
823{
824 char const *ellipses = "";
825 va_list ap;
826 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
827 char *line_prefix = NULL;
828 static char const marker_spaces[] = " "; /* 60 */
829
830 if (str_len == SIZE_MAX) str_len = strlen(str);
831
832 if (marker_idx < 0) marker_idx = marker_idx * -1;
833
834 if ((size_t)marker_idx >= sizeof(marker_spaces)) {
835 size_t offset = (marker_idx - (sizeof(marker_spaces) - 1)) + (sizeof(marker_spaces) * 0.75);
836 marker_idx -= offset;
837
838 if (offset > str_len) offset = str_len;
839 str += offset;
840 str_len -= offset;
841
842 ellipses = "... ";
843 }
844
845 if (line_prefix_fmt) {
846 va_start(ap, line_prefix_fmt);
847 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
848 va_end(ap);
849 }
850
851 fr_log(log, type, file, line, "%s%s%.*s",
852 line_prefix ? line_prefix : "", ellipses, (int)str_len, str);
853 fr_log(log, type, file, line, "%s%s%.*s^ %s",
854 line_prefix ? line_prefix : "", ellipses, (int)marker_idx, marker_spaces, marker);
855
856 if (line_prefix_fmt) talloc_free(line_prefix);
857}
858
859/** Print out hex block
860 *
861 * @param[in] log destination.
862 * @param[in] type of log message.
863 * @param[in] file src file the log message was generated in.
864 * @param[in] line number the log message was generated on.
865 * @param[in] data to print.
866 * @param[in] data_len length of data.
867 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
868 * @param[in] ... Arguments for line_prefix_fmt.
869 */
870void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
871 uint8_t const *data, size_t data_len, char const *line_prefix_fmt, ...)
872{
873 size_t i, j, len;
874 char buffer[(0x10 * 3) + 1];
875 char *p, *end = buffer + sizeof(buffer);
876 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
877 char *line_prefix = NULL;
878
879 if (line_prefix_fmt) {
880 va_list ap;
881
882 va_start(ap, line_prefix_fmt);
883 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
884 va_end(ap);
885 }
886
887 for (i = 0; i < data_len; i += 0x10) {
888 len = 0x10;
889 if ((i + len) > data_len) len = data_len - i;
890
891 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
892
893 if (line_prefix_fmt) {
894 fr_log(log, type, file, line, "%s%04x: %s",
895 line_prefix, (unsigned int) i, buffer);
896 } else {
897 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
898 }
899 }
900
901 if (line_prefix_fmt) talloc_free(line_prefix);
902}
903
904/** Print out hex block
905 *
906 * @param[in] log destination.
907 * @param[in] type of log message.
908 * @param[in] file src file the log message was generated in.
909 * @param[in] line number the log message was generated on.
910 * @param[in] data to print.
911 * @param[in] data_len length of data.
912 * @param[in] marker_idx Where to place the marker. May be negative.
913 * @param[in] marker text to print at marker_idx.
914 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
915 * @param[in] ... Arguments for line_prefix_fmt.
916 */
917void fr_log_hex_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
918 uint8_t const *data, size_t data_len,
919 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
920{
921 size_t i, j, len;
922 char buffer[(0x10 * 3) + 1];
923 char *p, *end = buffer + sizeof(buffer);
924 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
925
926 char *line_prefix = NULL;
927 static char spaces[3 * 0x10]; /* Bytes per line */
928
929 if (!*spaces) memset(spaces, ' ', sizeof(spaces) - 1); /* Leave a \0 */
930
931 if (marker_idx < 0) marker_idx = marker_idx * -1;
932 if (line_prefix_fmt) {
933 va_list ap;
934
935 va_start(ap, line_prefix_fmt);
936 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
937 va_end(ap);
938 }
939
940 for (i = 0; i < data_len; i += 0x10) {
941 len = 0x10;
942 if ((i + len) > data_len) len = data_len - i;
943
944 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
945
946 if (line_prefix_fmt) {
947 fr_log(log, type, file, line, "%s%04x: %s",
948 line_prefix, (unsigned int) i, buffer);
949 } else {
950 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
951 }
952
953 /*
954 * Marker is on this line
955 */
956 if (((size_t)marker_idx >= i) && ((size_t)marker_idx < (i + 0x10))) {
957 if (line_prefix_fmt) {
958 fr_log(log, type, file, line, "%s %.*s^ %s", line_prefix,
959 (int)((marker_idx - i) * 3), spaces, marker);
960 } else {
961 fr_log(log, type, file, line, " %.*s^ %s",
962 (int)((marker_idx - i) * 3), spaces, marker);
963 }
964 }
965 }
966
967 if (line_prefix_fmt) talloc_free(line_prefix);
968}
969DIAG_ON(format-nonliteral)
970/** On fault, reset STDOUT and STDERR to something useful
971 *
972 * @return 0
973 */
974static int _restore_std_legacy(UNUSED int sig)
975{
976 if ((stderr_fd > 0) && (stdout_fd > 0)) {
977 dup2(stdout_fd, STDOUT_FILENO);
978 dup2(stderr_fd, STDERR_FILENO);
979 return 0;
980 }
981
982 return 0;
983}
984
985/** Initialise file descriptors based on logging destination
986 *
987 * @param log Logger to manipulate.
988 * @param daemonize Whether the server is starting as a daemon.
989 * @return
990 * - 0 on success.
991 * - -1 on failure.
992 */
993int fr_log_init_legacy(fr_log_t *log, bool daemonize)
994{
995 int devnull_legacy;
996
997 fr_log_rate_limit = daemonize;
998
999 /*
1000 * If we're running in foreground mode, save STDIN /
1001 * STDERR as higher FDs, which won't get used by anyone
1002 * else. When we fork/exec a program, its STD FDs will
1003 * get set to pipes. We later set STDOUT / STDERR to
1004 * /dev/null, so that any library trying to write to them
1005 * doesn't screw anything up.
1006 *
1007 * Then, when something goes wrong, restore them so that
1008 * any debugger called from the panic action has access
1009 * to STDOUT / STDERR.
1010 */
1011 if (!daemonize) {
1013
1014 stdout_fd = dup(STDOUT_FILENO);
1015 stderr_fd = dup(STDERR_FILENO);
1016 }
1017
1018 devnull_legacy = open("/dev/null", O_RDWR);
1019 if (devnull_legacy < 0) {
1020 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
1021 return -1;
1022 }
1023
1024 /*
1025 * STDOUT & STDERR go to /dev/null, unless we have "-x",
1026 * then STDOUT & STDERR go to the "-l log" destination.
1027 *
1028 * The complexity here is because "-l log" can go to
1029 * STDOUT or STDERR, too.
1030 */
1031 if (log->dst == L_DST_STDOUT) {
1032 setlinebuf(stdout);
1033 log->fd = STDOUT_FILENO;
1034
1035 /*
1036 * If we're debugging, allow STDERR to go to
1037 * STDOUT too, for executed programs.
1038 *
1039 * Allow stdout when running in foreground mode
1040 * as it's useful for some profiling tools,
1041 * like mutrace.
1042 */
1043 if (fr_debug_lvl || !daemonize) {
1044 dup2(STDOUT_FILENO, STDERR_FILENO);
1045 } else {
1046 dup2(devnull_legacy, STDERR_FILENO);
1047 }
1048
1049 } else if (log->dst == L_DST_STDERR) {
1050 setlinebuf(stderr);
1051 log->fd = STDERR_FILENO;
1052
1053 /*
1054 * If we're debugging, allow STDOUT to go to
1055 * STDERR too, for executed programs.
1056 *
1057 * Allow stdout when running in foreground mode
1058 * as it's useful for some profiling tools,
1059 * like mutrace.
1060 */
1061 if (fr_debug_lvl || !daemonize) {
1062 dup2(STDERR_FILENO, STDOUT_FILENO);
1063 } else {
1064 dup2(devnull_legacy, STDOUT_FILENO);
1065 }
1066
1067 } else if (log->dst == L_DST_SYSLOG) {
1068 /*
1069 * Discard STDOUT and STDERR no matter what the
1070 * status of debugging. Syslog isn't a file
1071 * descriptor, so we can't use it.
1072 */
1073 dup2(devnull_legacy, STDOUT_FILENO);
1074 dup2(devnull_legacy, STDERR_FILENO);
1075 log->print_level = false;
1076
1077 } else if (fr_debug_lvl) {
1078 /*
1079 * If we're debugging, allow STDOUT and STDERR to
1080 * go to the log file.
1081 */
1082 dup2(log->fd, STDOUT_FILENO);
1083 dup2(log->fd, STDERR_FILENO);
1084
1085 } else {
1086 /*
1087 * Not debugging, and the log isn't STDOUT or
1088 * STDERR. Ensure that we move both of them to
1089 * /dev/null, so that the calling terminal can
1090 * exit, and the output from executed programs
1091 * doesn't pollute STDOUT / STDERR.
1092 */
1093 dup2(devnull_legacy, STDOUT_FILENO);
1094 dup2(devnull_legacy, STDERR_FILENO);
1095 }
1096
1097 close(devnull_legacy);
1098
1099 fr_fault_set_log_fd(log->fd);
1100
1101 return 0;
1102}
1103
1104DIAG_ON(format-nonliteral)
1105
1106/** Initialise log dst for stdout, stderr or /dev/null
1107 *
1108 * @param[out] log Destination to initialise.
1109 * @param[in] dst_type The specific type of log destination to initialise.
1110 * @return
1111 * - 0 on success.
1112 * - -1 on failure.
1113 */
1115{
1116 memset(log, 0, sizeof(*log));
1117
1118 log->dst = dst_type;
1119 switch (log->dst) {
1120 case L_DST_STDOUT:
1121 log->handle = stdout;
1122 break;
1123
1124 case L_DST_STDERR:
1125 log->handle = stderr;
1126 break;
1127
1128 case L_DST_NULL:
1129 log->handle = devnull;
1130 break;
1131
1132 default:
1133 fr_strerror_const("Invalid dst type for FD log destination");
1134 return -1;
1135 }
1136
1137 return 0;
1138}
1139
1140/** Initialise a file logging destination to a FILE*
1141 *
1142 * @param[out] log Destination to initialise.
1143 * @param[in] fp pre-existing handle
1144 * @return
1145 * - 0 on success.
1146 * - -1 on failure.
1147 */
1148int fr_log_init_fp(fr_log_t *log, FILE *fp)
1149{
1150 memset(log, 0, sizeof(*log));
1151
1152 log->dst = L_DST_FILES;
1153 log->handle = fp;
1154
1155 setlinebuf(log->handle);
1156 log->fd = fileno(log->handle);
1157
1158 return 0;
1159}
1160
1161/** Initialise a file logging destination
1162 *
1163 * @param[out] log Destination to initialise.
1164 * @param[in] file to open handle for.
1165 * @return
1166 * - 0 on success.
1167 * - -1 on failure.
1168 */
1169int fr_log_init_file(fr_log_t *log, char const *file)
1170{
1171 FILE *fp;
1172
1173 if (unlikely((fp = fopen(file, "a")) == NULL)) {
1174 fr_strerror_printf("Failed opening log file \"%s\": %s", file, fr_syserror(errno));
1175 return -1;
1176 }
1177
1178 if (fr_log_init_fp(log, fp) < 0) return -1;
1179
1180 /*
1181 * The init over-rode any filename, so we reset it here.
1182 */
1183 log->file = file;
1184 return 0;
1185}
1186
1187/** Write complete lines to syslog
1188 *
1189 */
1190static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
1191{
1192 static int syslog_priority_table[] = {
1193 [L_DBG] = LOG_DEBUG,
1194
1195 [L_INFO] = LOG_INFO,
1196 [L_DBG_INFO] = LOG_INFO,
1197
1198 [L_ERR] = LOG_ERR,
1199 [L_DBG_ERR] = LOG_ERR,
1200 [L_DBG_ERR_REQ] = LOG_ERR,
1201
1202 [L_WARN] = LOG_WARNING,
1203 [L_DBG_WARN] = LOG_WARNING,
1204 [L_DBG_WARN_REQ] = LOG_WARNING,
1205
1206 [L_AUTH] = LOG_AUTH | LOG_INFO
1207 };
1208
1209 syslog(syslog_priority_table[log_msg_type], "%.*s", (int)size, buf);
1210
1211 return size;
1212}
1213
1214/** Initialise a syslog logging destination
1215 *
1216 * @param[out] log Destination to initialise.
1217 * @return
1218 * - 0 on success.
1219 * - -1 on failure.
1220 */
1222{
1223 memset(log, 0, sizeof(*log));
1224
1225 log->dst = L_DST_SYSLOG;
1226 if (unlikely((log->handle = fopencookie(log, "w",
1228 .write = _syslog_write,
1229 })) == NULL)) {
1230 fr_strerror_printf("Failed opening syslog transpor: %s", fr_syserror(errno));
1231 return -1;
1232 }
1233
1234 setlinebuf(log->handle);
1235
1236 return 0;
1237}
1238
1239/** Initialise a function based logging destination
1240 *
1241 * @note Cookie functions receive the fr_log_t which contains the uctx, not the uctx directly.
1242 *
1243 * @param[out] log Destination to initialise.
1244 * @param[in] write Called when a complete log line is ready for writing.
1245 * @param[in] close May be NULL. Called when the logging destination has been closed.
1246 * @param[in] uctx for the write and close functions.
1247 * @return
1248 * - 0 on success.
1249 * - -1 on failure.
1250 */
1252{
1253 memset(log, 0, sizeof(*log));
1254
1255 log->dst = L_DST_FUNC;
1256
1257 if (unlikely((log->handle = fopencookie(log, "w",
1259 .write = write,
1260 .close = close
1261 })) == NULL)) {
1262 fr_strerror_printf("Failed opening func transport: %s", fr_syserror(errno));
1263 return -1;
1264 }
1265
1266 setlinebuf(log->handle);
1267 log->uctx = uctx;
1268
1269 return 0;
1270}
1271
1272/** Universal close function for all logging destinations
1273 *
1274 */
1276{
1277 switch (log->dst) {
1278 case L_DST_STDOUT:
1279 case L_DST_STDERR:
1280 case L_DST_NULL:
1281 return 0;
1282
1283 /*
1284 * Other log dsts
1285 */
1286 case L_DST_FILES:
1287 case L_DST_FUNC:
1288 case L_DST_SYSLOG:
1289 if (log->handle && (fclose(log->handle) < 0)) {
1290 fr_strerror_printf("Failed closing file handle: %s", fr_syserror(errno));
1291 return -1;
1292 }
1293 return 0;
1294
1295 case L_DST_NUM_DEST:
1296 break;
1297 }
1298
1299 fr_strerror_printf("Failed closing invalid log dst %u", log->dst);
1300 return -1;
1301}
1302
1303/** Manipulate stderr and stdout so that was capture all data send to it from libraries
1304 *
1305 * @param[in] el The event list we use to process logging data.
1306 * @param[in] daemonize Whether the server is starting as a daemon.
1307 * @return
1308 * - 0 on success.
1309 * - -1 on failure.
1310 */
1312{
1313 log_el = el;
1314
1315 fr_log_rate_limit = daemonize;
1316
1317 /*
1318 * dup the current stdout/stderr FDs and close
1319 * the FDs in the STDOUT/STDERR slots to get
1320 * the reference count back to one.
1321 */
1322 stdout_fd = dup(STDOUT_FILENO);
1323 if (unlikely(stdout_fd < 0)) {
1324 fr_strerror_printf("Failed cloning stdout FD: %s", fr_syserror(errno));
1325 return -1;
1326 }
1327
1328 /*
1329 * Create two unidirection pipes, duping one end
1330 * to the stdout/stderr slots and inserting the
1331 * other into our event loop
1332 */
1333 if (unlikely(pipe(stdout_pipe) < 0)) {
1334 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1335 error_0:
1336 log_el = NULL;
1337 close(stdout_fd);
1338 return -1;
1339 }
1340
1341 /*
1342 * This closes the other ref to the stdout FD.
1343 */
1344 if (unlikely(dup2(stdout_pipe[0], STDOUT_FILENO) < 0)) {
1345 fr_strerror_printf("Failed copying pipe end over stdout: %s", fr_syserror(errno));
1346 error_1:
1347 close(stdout_pipe[0]);
1348 stdout_pipe[0] = -1;
1349 close(stdout_pipe[1]);
1350 stdout_pipe[1] = -1;
1351 goto error_0;
1352 }
1353
1355 stdout_ctx.prefix = "(stdout)";
1358
1359 /*
1360 * Now do stderr...
1361 */
1362 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stdout_pipe[1], fr_log_fd_event, NULL, NULL, &stdout_ctx) < 0)) {
1363 fr_strerror_const_push("Failed adding stdout handler to event loop");
1364 error_2:
1365 dup2(STDOUT_FILENO, stdout_fd); /* Copy back the stdout FD */
1366 goto error_1;
1367 }
1368
1369 stderr_fd = dup(STDERR_FILENO);
1370 if (unlikely(stderr_fd < 0)) {
1371 fr_strerror_printf("Failed cloning stderr FD: %s", fr_syserror(errno));
1372
1373 error_3:
1375 goto error_2;
1376 }
1377
1378 if (unlikely(pipe(stderr_pipe) < 0)) {
1379 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1380 error_4:
1381 close(stderr_fd);
1382 goto error_3;
1383 }
1384
1385 if (unlikely(dup2(stderr_pipe[0], STDERR_FILENO) < 0)) {
1386 fr_strerror_printf("Failed copying pipe end over stderr: %s", fr_syserror(errno));
1387 error_5:
1388 close(stderr_pipe[0]);
1389 stderr_pipe[0] = -1;
1390 close(stderr_pipe[1]);
1391 stderr_pipe[1] = -1;
1392 goto error_4;
1393 }
1394
1396 stderr_ctx.prefix = "(stderr)";
1398 stderr_ctx.lvl = L_DBG_LVL_OFF; /* Log at all debug levels */
1399
1400 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stderr_pipe[1], fr_log_fd_event, NULL, NULL, &stderr_ctx) < 0)) {
1401 fr_strerror_const_push("Failed adding stdout handler to event loop");
1402 error_6:
1403 dup2(STDERR_FILENO, stderr_fd); /* Copy back the stderr FD */
1404 goto error_5;
1405 }
1406
1407 fr_fault_set_log_fd(STDERR_FILENO);
1408 fr_fault_set_cb(_restore_std_legacy); /* Restore the original file descriptors if we experience a fault */
1409
1410 /*
1411 * Setup our standard file *s
1412 */
1413 setlinebuf(stdout);
1414 setlinebuf(stderr);
1415
1416 devnull = fopen("/dev/null", "w");
1417 if (unlikely(!devnull)) {
1418 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
1419 goto error_6;
1420 }
1421
1423
1424 return 0;
1425}
1426
1427/** Restores the original stdout and stderr FDs, closes the pipes and removes them from the event loop
1428 *
1429 */
1431{
1432 if (!log_el) return;
1433
1435 close(stdout_pipe[1]);
1436 stdout_pipe[1] = -1;
1438 close(stderr_pipe[1]);
1439 stderr_pipe[1] = -1;
1440
1441 _restore_std_legacy(0); /* Will close stdout_pipe[0] and stderr_pipe[0] with dup2 */
1442
1443 stdout_pipe[0] = -1;
1444 stderr_pipe[0] = -1;
1445
1446 fclose(devnull);
1447}
static int const char char buffer[256]
Definition acutest.h:576
int const char * file
Definition acutest.h:702
va_end(args)
static int const char * fmt
Definition acutest.h:573
int const char int line
Definition acutest.h:702
va_start(args, fmt)
bool fr_atexit_thread_local_alloc_disabled(void)
Has fr_atexit_thread_local_disable_alloc been called yet.
Definition atexit.c:447
bool fr_atexit_is_exiting(void)
Return whether we're currently in the teardown phase.
Definition atexit.c:457
#define _Thread_local
Definition atexit.h:213
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:224
#define RCSID(id)
Definition build.h:560
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:391
#define DIAG_ON(_x)
Definition build.h:535
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define NUM_ELEMENTS(_t)
Definition build.h:406
#define DIAG_OFF(_x)
Definition build.h:534
static fr_atomic_queue_t ** aq
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
Definition debug.c:1262
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition debug.c:1214
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:272
Test enumeration values.
Definition dict_test.h:92
#define fr_event_fd_insert(...)
Definition event.h:247
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
FILE * fopencookie(void *cookie, const char *mode, cookie_io_functions_t io_funcs)
Definition fopencookie.c:99
int(* cookie_close_function_t)(void *cookie)
Definition fopencookie.h:49
ssize_t(* cookie_write_function_t)(void *cookie, const char *buf, size_t size)
Definition fopencookie.h:45
talloc_free(hp)
static char const spaces[]
Definition log.c:196
#define fr_time()
Definition event.c:60
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition event.c:1203
Stores all information relating to an event list.
Definition event.c:377
fr_table_num_ordered_t const fr_log_levels[]
Maps log categories to message prefixes.
Definition log.c:262
int fr_log_init_legacy(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
Definition log.c:993
#define VTC_RED
Colour following text red.
Definition log.c:286
int fr_debug_lvl
Definition log.c:41
void fr_log_disable_pools(void)
Disable per-thread log pools for the rest of the process lifetime.
Definition log.c:334
static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
Write complete lines to syslog.
Definition log.c:1190
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition log.c:347
int fr_log_init_syslog(fr_log_t *log)
Initialise a syslog logging destination.
Definition log.c:1221
int fr_log_global_init(fr_event_list_t *el, bool daemonize)
Manipulate stderr and stdout so that was capture all data send to it from libraries.
Definition log.c:1311
void _fr_log_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line, fr_log_perror_format_t const *rules, char const *const arg_names[], char const *fmt,...)
Drain any outstanding messages from the fr_strerror buffers.
Definition log.c:794
void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line, uint8_t const *data, size_t data_len, char const *line_prefix_fmt,...)
Print out hex block.
Definition log.c:870
static FILE * devnull
File handle for /dev/null.
Definition log.c:74
static atomic_bool log_pools_disabled
Latched once shutdown has freed every thread's log pool.
Definition log.c:60
void fr_log_hex_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line, uint8_t const *data, size_t data_len, ssize_t marker_idx, char const *marker, char const *line_prefix_fmt,...)
Print out hex block.
Definition log.c:917
#define VTC_YELLOW
Colour following text yellow.
Definition log.c:287
void fr_log_global_free(void)
Restores the original stdout and stderr FDs, closes the pipes and removes them from the event loop.
Definition log.c:1430
static int _restore_std_legacy(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Definition log.c:974
static int stdout_fd
The original unmolested stdout file descriptor.
Definition log.c:66
int fr_log_init_std(fr_log_t *log, fr_log_dst_t dst_type)
Initialise log dst for stdout, stderr or /dev/null.
Definition log.c:1114
int fr_log_init_func(fr_log_t *log, cookie_write_function_t write, cookie_close_function_t close, void *uctx)
Initialise a function based logging destination.
Definition log.c:1251
#define VTC_RESET
Reset terminal text to default style/colour.
Definition log.c:289
static fr_log_fd_event_ctx_t stderr_ctx
Logging ctx for stderr.
Definition log.c:69
static uint32_t location_indent
Definition log.c:62
static fr_table_num_ordered_t const colours[]
Maps log categories to VT100 style/colour escape sequences.
Definition log.c:294
void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *str, size_t str_len, ssize_t marker_idx, char const *marker, char const *line_prefix_fmt,...)
Print out an error marker.
Definition log.c:820
void fr_log_fd_event(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Function to provide as the readable callback to the event loop.
Definition log.c:196
static fr_event_list_t * log_el
Event loop we use for process logging data.
Definition log.c:63
FILE * fr_log_fp
Definition log.c:40
fr_log_t default_log
Definition log.c:308
int fr_log_init_file(fr_log_t *log, char const *file)
Initialise a file logging destination.
Definition log.c:1169
static _Thread_local fr_log_type_t log_msg_type
The type of the last message logged.
Definition log.c:78
static int stdout_pipe[2]
Pipe we use to transport stdout data.
Definition log.c:71
static int stderr_pipe[2]
Pipe we use to transport stderr data.
Definition log.c:72
bool fr_log_rate_limit
Whether repeated log entries should be rate limited.
Definition log.c:76
int fr_log_init_fp(fr_log_t *log, FILE *fp)
Initialise a file logging destination to a FILE*.
Definition log.c:1148
void _fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line, fr_log_perror_format_t const *f_rules, UNUSED char const *const arg_names[], char const *fmt, va_list ap)
Drain any outstanding messages from the fr_strerror buffers.
Definition log.c:697
static _Thread_local TALLOC_CTX * fr_log_pool
Definition log.c:43
bool log_dates_utc
Definition log.c:306
void _fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, UNUSED char const *const arg_names[], char const *fmt, va_list ap)
Send a server log message to its destination.
Definition log.c:383
void _fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *const arg_names[], char const *fmt,...)
Send a server log message to its destination.
Definition log.c:664
size_t fr_log_levels_len
Definition log.c:274
static fr_log_fd_event_ctx_t stdout_ctx
Logging ctx for stdout.
Definition log.c:68
static int _fr_log_pool_free(void *arg)
Cleanup the memory pool used by vlog_request.
Definition log.c:319
void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen, char const *fmt)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
Definition log.c:105
static int stderr_fd
The original unmolested stderr file descriptor.
Definition log.c:65
static size_t colours_len
Definition log.c:303
int fr_log_close(fr_log_t *log)
Universal close function for all logging destinations.
Definition log.c:1275
#define VTC_BOLD
Embolden following text.
Definition log.c:288
#define fr_log(_log, _lvl, _file, _line, _fmt,...)
Definition log.h:172
fr_log_dst_t
Definition log.h:74
@ L_DST_NULL
Discard log messages.
Definition log.h:80
@ L_DST_STDERR
Log to stderr.
Definition log.h:78
@ L_DST_FILES
Log to a file on disk.
Definition log.h:76
@ L_DST_FUNC
Send log messages to a FILE*, via fopencookie()
Definition log.h:79
@ L_DST_NUM_DEST
Definition log.h:81
@ L_DST_STDOUT
Log to stdout.
Definition log.h:75
@ L_DST_SYSLOG
Log to syslog.
Definition log.h:77
@ L_TIMESTAMP_ON
Always log timestamps.
Definition log.h:87
@ L_TIMESTAMP_OFF
Never log timestamps.
Definition log.h:88
@ L_TIMESTAMP_AUTO
Timestamp logging preference not specified.
Definition log.h:85
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
Definition log.h:68
@ L_DBG_LVL_OFF
No debug messages.
Definition log.h:66
char const * prefix
To add to log messages.
Definition log.h:136
char const * first_prefix
Prefix for the first line printed.
Definition log.h:122
char const * subsq_prefix
Prefix for subsequent lines.
Definition log.h:123
fr_log_lvl_t lvl
Priority of the message.
Definition log.h:135
fr_log_type_t type
What type of log message it is.
Definition log.h:134
fr_log_t const * dst
Where to log to.
Definition log.h:133
fr_log_type_t
Definition log.h:51
@ L_DBG_INFO
Info only displayed when debugging is enabled.
Definition log.h:57
@ L_DBG_WARN_REQ
Less severe warning only displayed when debugging is enabled.
Definition log.h:60
@ L_WARN
Warning.
Definition log.h:54
@ L_ERR
Error message.
Definition log.h:53
@ L_DBG_ERR
Error only displayed when debugging is enabled.
Definition log.h:59
@ L_DBG_ERR_REQ
Less severe error only displayed when debugging is enabled.
Definition log.h:61
@ L_DBG_WARN
Warning only displayed when debugging is enabled.
Definition log.h:58
@ L_AUTH
Authentication logs.
Definition log.h:55
@ L_INFO
Informational message.
Definition log.h:52
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
Context structure for the log fd event function.
Definition log.h:132
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
size_t 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.
Definition print.c:39
char * fr_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Definition print.c:860
ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str)
Copy bytes into the sbuff up to the first \0.
Definition sbuff.c:1529
size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift, bool move_end)
Shift the contents of the sbuff, returning the number of bytes we managed to shift.
Definition sbuff.c:212
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
Definition sbuff.c:2311
size_t fr_sbuff_adv_until(fr_sbuff_t *sbuff, size_t len, fr_sbuff_term_t const *tt, char escape_chr)
Wind position until we hit a character in the terminal set.
Definition sbuff.c:2011
ssize_t fr_sbuff_in_vsprintf(fr_sbuff_t *sbuff, char const *fmt, va_list ap)
Print using a fmt string to an sbuff.
Definition sbuff.c:1646
#define fr_sbuff_start(_sbuff_or_marker)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_current(_sbuff_or_marker)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
Definition sbuff.h:190
#define fr_sbuff_init_out(_out, _start, _len_or_end)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_remaining(_sbuff_or_marker)
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_used(_sbuff_or_marker)
#define fr_sbuff_behind(_sbuff_or_marker)
#define fr_sbuff_ahead(_sbuff_or_marker)
Set of terminal elements.
Talloc sbuff extension structure.
Definition sbuff.h:137
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
fr_aka_sim_id_type_t type
@ memory_order_relaxed
Definition stdatomic.h:127
#define atomic_store_explicit(object, desired, order)
Definition stdatomic.h:314
Definition log.h:93
bool dates_utc
Whether timestamps should be UTC or local timezone.
Definition log.h:101
void * uctx
User data associated with the fr_log_t.
Definition log.h:116
bool colourise
Prefix log messages with VT100 escape codes to change text colour.
Definition log.h:98
fr_log_dst_t dst
Log destination.
Definition log.h:94
bool line_number
Log src file and line number.
Definition log.h:96
int fd
File descriptor to write messages to.
Definition log.h:109
fr_log_timestamp_t timestamp
Prefix log messages with timestamps.
Definition log.h:107
char const * file
Path to log file.
Definition log.h:110
bool print_level
sometimes we don't want log levels printed
Definition log.h:103
FILE * handle
Path to log file.
Definition log.h:113
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
#define talloc_asprintf
Definition talloc.h:151
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
fr_slen_t fr_unix_time_to_str(fr_sbuff_t *out, fr_unix_time_t time, fr_time_res_t res, bool utc)
Convert unix time to string.
Definition time.c:1159
@ FR_TIME_RES_USEC
Definition time.h:59
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition time.h:688
"Unix" time.
Definition time.h:95
static fr_event_list_t * el
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:737
char const * fr_strerror_pop(void)
Pop the last library error.
Definition strerror.c:685
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1367
#define fr_box_strvalue_len(_val, _len)
Definition value.h:334
static fr_sbuff_err_t char size_t * len
Definition value.h:1062