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: 56de09aa9d127a8a51c7ca3a471cc04a571588b7 $")
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 /*
120 * Catch bad callers.
121 */
122 if (offset > inlen) {
123 *sp = talloc_strdup(ctx, "");
124 *text = talloc_strdup(ctx, "");
125 return;
126 }
127
128 /*
129 * Too many characters before the inflection point. Skip
130 * leading text until we have only 45 characters before it.
131 */
132 if (offset > 30) {
133 size_t skip = offset - 30;
134
135 start += skip;
136 inlen -= skip;
137 offset -= skip;
138 prefix = 4;
139 }
140
141 /*
142 * Too many characters after the inflection point,
143 * truncate it to 30 characters after the inflection
144 * point.
145 */
146 if (inlen > (offset + 30)) {
147 inlen = offset + 30;
148 suffix = 4;
149 }
150
151 /*
152 * Allocate an array to hold just the text we need.
153 */
154 value = talloc_array(ctx, char, prefix + inlen + 1 + suffix);
155 if (prefix) {
156 memcpy(value, "... ", 4);
157 }
158 memcpy(value + prefix, start, inlen);
159 if (suffix) {
160 memcpy(value + prefix + inlen, "...", 3);
161 value[prefix + inlen + 3] = '\0';
162 }
163 value[prefix + inlen + suffix] = '\0';
164
165 /*
166 * Smash tabs to spaces for the input string.
167 */
168 for (p = value; *p != '\0'; p++) {
169 if (*p == '\t') *p = ' ';
170 }
171
172 /*
173 * Allocate the spaces array
174 */
175 spaces = talloc_array(ctx, char, prefix + offset + 1);
176 memset(spaces, ' ', prefix + offset);
177 spaces[prefix + offset] = '\0';
178
179 *sp = spaces;
180 *text = value;
181}
182
183/** Function to provide as the readable callback to the event loop
184 *
185 * Writes any data read from a file descriptor to the request log,
186 * tries very hard not to chop lines in the middle, but will split
187 * at 1024 byte boundaries if forced to.
188 *
189 * @param[in] el UNUSED
190 * @param[in] fd UNUSED
191 * @param[in] flags UNUSED
192 * @param[in] uctx Pointer to a log_fd_event_ctx_t
193 */
194void fr_log_fd_event(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
195{
196 char buffer[1024] = "";
197 fr_log_fd_event_ctx_t *log_info = uctx;
198 fr_sbuff_t sbuff;
199 fr_sbuff_marker_t m_start, m_end;
200
201 fr_sbuff_term_t const line_endings = FR_SBUFF_TERMS(L("\n"), L("\r"));
202
203 if (log_info->lvl < fr_debug_lvl) {
204 while (read(fd, buffer, sizeof(buffer)) > 0);
205 return;
206 }
207
208#ifndef NDEBUG
209 memset(buffer, 0x42, sizeof(buffer));
210#endif
211
212 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
213 fr_sbuff_marker(&m_start, &sbuff);
214 fr_sbuff_marker(&m_end, &sbuff);
215
216 for (;;) {
217 ssize_t slen;
218
219 slen = read(fd, fr_sbuff_current(&m_end), fr_sbuff_remaining(&m_end));
220 if ((slen < 0) && (errno == EINTR)) continue;
221
222 if (slen > 0) fr_sbuff_advance(&m_end, slen);
223
224 while (fr_sbuff_ahead(&m_end) > 0) {
225 fr_sbuff_adv_until(&sbuff, fr_sbuff_ahead(&m_end), &line_endings, '\0');
226
227 /*
228 * Incomplete line, try and read the rest.
229 */
230 if ((slen > 0) && (fr_sbuff_used(&m_start) > 0) &&
231 !fr_sbuff_is_terminal(&sbuff, &line_endings)) {
232 break;
233 }
234
235 fr_log(log_info->dst, log_info->type,
236 __FILE__, __LINE__,
237 "%s%s%pV",
238 log_info->prefix ? log_info->prefix : "",
239 log_info->prefix ? " - " : "",
241
242 fr_sbuff_advance(&sbuff, 1); /* Skip the whitespace */
243 fr_sbuff_set(&m_start, &sbuff);
244 }
245
246 /*
247 * Error or done
248 */
249 if (slen <= 0) break;
250
251 /*
252 * Clear out the existing data
253 */
254 fr_sbuff_shift(&sbuff, fr_sbuff_used(&m_start), false);
255 }
256}
257
258/** Maps log categories to message prefixes
259 */
261 { L("Debug : "), L_DBG },
262 { L("Info : "), L_INFO },
263 { L("Warn : "), L_WARN },
264 { L("Error : "), L_ERR },
265 { L("Auth : "), L_AUTH },
266 { L("INFO : "), L_DBG_INFO },
267 { L("WARN : "), L_DBG_WARN },
268 { L("ERROR : "), L_DBG_ERR },
269 { L("WARN : "), L_DBG_WARN_REQ },
270 { L("ERROR : "), L_DBG_ERR_REQ }
271};
273
274/** @name VT100 escape sequences
275 *
276 * These sequences may be written to VT100 terminals to change the
277 * colour and style of the text.
278 *
279 @code{.c}
280 fprintf(stdout, VTC_RED "This text will be coloured red" VTC_RESET);
281 @endcode
282 * @{
283 */
284#define VTC_RED "\x1b[31m" //!< Colour following text red.
285#define VTC_YELLOW "\x1b[33m" //!< Colour following text yellow.
286#define VTC_BOLD "\x1b[1m" //!< Embolden following text.
287#define VTC_RESET "\x1b[0m" //!< Reset terminal text to default style/colour.
288/** @} */
289
290/** Maps log categories to VT100 style/colour escape sequences
291 */
302
303
304bool log_dates_utc = false;
305
307 .colourise = false, //!< Will be set later. Should be off before we do terminal detection.
308 .fd = STDOUT_FILENO,
309 .dst = L_DST_STDOUT,
310 .file = NULL,
311 .timestamp = L_TIMESTAMP_AUTO
312};
313
314/** Cleanup the memory pool used by vlog_request
315 *
316 */
317static int _fr_log_pool_free(void *arg)
318{
319 if (talloc_free(arg) < 0) return -1;
320 fr_log_pool = NULL;
321 return 0;
322}
323
324/** Disable per-thread log pools for the rest of the process lifetime
325 *
326 * Call this from the main thread immediately after
327 * `fr_atexit_thread_trigger_all()`, which frees every other thread's log
328 * pool but can't reset their `_Thread_local` slot. After this returns,
329 * subsequent `fr_log` calls fall back to `talloc_new(NULL)` instead of
330 * touching the (now dangling) TLS pool pointer.
331 */
336
337/** talloc ctx to use when composing log messages
338 *
339 * Functions must ensure that they allocate a new ctx from the one returned
340 * here, and that this ctx is freed before the function returns.
341 *
342 * @return talloc pool to use for scratch space, or NULL if pools have been
343 * disabled - callers must tolerate a NULL return.
344 */
345TALLOC_CTX *fr_log_pool_init(void)
346{
347 TALLOC_CTX *pool;
348
349 /*
350 * Once main has signalled shutdown the TLS slot may be a
351 * dangling pointer for any thread we don't own (librdkafka's
352 * bg threads etc.) - skip the pool entirely.
353 */
355
356 pool = fr_log_pool;
357 if (unlikely(!pool)) {
358 if (fr_atexit_is_exiting()) return NULL; /* No new pools if we're exiting */
359
360 pool = talloc_pool(NULL, 16384);
361 if (!pool) {
362 fr_perror("Failed allocating memory for vlog_request_pool");
363 return NULL;
364 }
366 }
367
368 return pool;
369}
370
371/** Send a server log message to its destination
372 *
373 * @param[in] log destination.
374 * @param[in] type of log message.
375 * @param[in] file src file the log message was generated in.
376 * @param[in] line number the log message was generated on.
377 * @param[in] arg_names source text of each substitution argument, or NULL.
378 * @param[in] fmt with printf style substitution tokens.
379 * @param[in] ap Substitution arguments.
380 */
381void _fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
382 UNUSED char const * const arg_names[], char const *fmt, va_list ap)
383{
384 int colourise = log->colourise;
385 char *buffer;
386 TALLOC_CTX *pool, *thread_log_pool;
387 char const *fmt_colour = "";
388 char const *fmt_location = "";
389 char fmt_time[50];
390 char const *fmt_type = "";
391 char *fmt_msg;
392
393 static char const *spaces = " "; /* 40 */
394
395 fmt_time[0] = '\0';
396
397 /*
398 * If we don't want any messages, then
399 * throw them away.
400 */
401 if (log->dst == L_DST_NULL) return;
402
403 thread_log_pool = fr_log_pool_init();
404 pool = talloc_new(thread_log_pool); /* Track our local allocations */
405
406 /*
407 * Set colourisation
408 */
409 if (colourise) {
410 fmt_colour = fr_table_str_by_value(colours, type, NULL);
411 if (!fmt_colour) colourise = false;
412 }
413
414 /*
415 * Print src file/line
416 */
417 if (log->line_number) {
418 size_t len;
419 int pad = 0;
420 char *str;
421
422 str = talloc_asprintf(pool, "%s:%i", file, line);
423 len = talloc_strlen(str);
424
425 /*
426 * Only increase the indent
427 */
428 if (len > location_indent) {
429 location_indent = len;
430 } else {
431 pad = location_indent - len;
432 }
433
434 fmt_location = talloc_asprintf_append_buffer(str, "%.*s : ", pad, spaces);
435 }
436 /*
437 * Determine if we need to add a timestamp to the start of the message
438 */
439 switch (log->timestamp) {
440 case L_TIMESTAMP_OFF:
441 break;
442
443 /*
444 * If we're not logging to syslog, and the debug level is -xxx
445 * then log timestamps by default.
446 */
447 case L_TIMESTAMP_AUTO:
448 if (log->dst == L_DST_SYSLOG) break;
449 if ((log->dst != L_DST_FILES) && (fr_debug_lvl <= L_DBG_LVL_2)) break;
451
452 case L_TIMESTAMP_ON:
453 {
455 fr_sbuff_t time_sbuff = FR_SBUFF_OUT(fmt_time, sizeof(fmt_time));
456 fr_unix_time_to_str(&time_sbuff, now, FR_TIME_RES_USEC, log->dates_utc);
457 break;
458 }
459 }
460
461 /*
462 * Add ERROR or WARNING prefixes to messages not going to
463 * syslog. It's redundant for syslog because of syslog
464 * facilities.
465 */
466 if (log->dst != L_DST_SYSLOG) {
467 /*
468 * We always print "WARN" and "ERROR" prefixes.
469 */
470 switch (type) {
471 case L_DBG_WARN:
472 case L_DBG_ERR:
473 fmt_type = fr_table_str_by_value(fr_log_levels, type, NULL);
474 break;
475
476 default:
477 /*
478 * Otherwise, print the other info levels only if we're asked to print the level,
479 * and we're not colourizing the output. If we're colourizing the output, then
480 * the colors indicate the debug level (info, warning, error), and we don't need
481 * any prefix.
482 */
483 if (log->print_level && !log->colourise) fmt_type = fr_table_str_by_value(fr_log_levels, type, ": ");
484 break;
485 }
486 }
487
488 /*
489 * Sanitize output.
490 *
491 * Most strings should be escaped before they get here.
492 */
493 {
494 char *p, *end;
495
496 p = fmt_msg = fr_vasprintf(pool, fmt, ap);
497 end = p + talloc_strlen(fmt_msg);
498
499 /*
500 * Filter out control chars and non UTF8 chars
501 */
502 for (p = fmt_msg; p < end; p++) {
503 int clen;
504
505 switch (*p) {
506 case '\r':
507 case '\n':
508 *p = ' ';
509 break;
510
511 case '\t':
512 continue;
513
514 default:
515 clen = fr_utf8_char((uint8_t *)p, -1);
516 if (!clen) {
517 *p = '?';
518 continue;
519 }
520 p += (clen - 1);
521 break;
522 }
523 }
524 }
525
526 switch (log->dst) {
527
528#ifdef HAVE_SYSLOG_H
529 case L_DST_SYSLOG:
530 {
531 int syslog_priority = L_DBG;
532
533 switch (type) {
534 case L_DBG:
535 case L_DBG_INFO:
536 case L_DBG_WARN:
537 case L_DBG_ERR:
538 case L_DBG_ERR_REQ:
539 case L_DBG_WARN_REQ:
540 syslog_priority= LOG_DEBUG;
541 break;
542
543 case L_INFO:
544 syslog_priority = LOG_INFO;
545 break;
546
547 case L_WARN:
548 syslog_priority = LOG_WARNING;
549 break;
550
551 case L_ERR:
552 syslog_priority = LOG_ERR;
553 break;
554
555 case L_AUTH:
556 syslog_priority = LOG_AUTH | LOG_INFO;
557 break;
558 }
559 syslog(syslog_priority,
560 "%s" /* time */
561 "%s" /* time sep */
562 "%s", /* message */
563 fmt_time,
564 fmt_time[0] ? ": " : "",
565 fmt_msg);
566 }
567 break;
568#endif
569
570 case L_DST_FILES:
571 case L_DST_STDOUT:
572 case L_DST_STDERR:
573 {
574 size_t len, wrote;
575
576 buffer = talloc_asprintf(pool,
577 "%s" /* colourise */
578 "%s" /* location */
579 "%s" /* time */
580 "%s" /* time sep */
581 "%s" /* message type */
582 "%s" /* message */
583 "%s" /* colourise reset */
584 "\n",
585 colourise ? fmt_colour : "",
586 fmt_location,
587 fmt_time,
588 fmt_time[0] ? ": " : "",
589 fmt_type,
590 fmt_msg,
591 colourise ? VTC_RESET : "");
592
593 len = talloc_strlen(buffer);
594 wrote = write(log->fd, buffer, len);
595 if (wrote < len) return;
596 }
597 break;
598
599 default:
600 case L_DST_NULL: /* should have been caught above */
601 break;
602 }
603
604 talloc_free(pool); /* clears all temporary allocations */
605
606 return;
607}
608
609/** Send a server log message to its destination
610 *
611 * @param log destination.
612 * @param type of log message.
613 * @param file where the log message originated
614 * @param line where the log message originated
615 * @param arg_names source text of each substitution argument, or NULL.
616 * @param fmt with printf style substitution tokens.
617 * @param ... Substitution arguments.
618 */
619void _fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
620 char const * const arg_names[], char const *fmt, ...)
621{
622 va_list ap;
623
624 /*
625 * Non-debug message, or debugging is enabled. Log it.
626 */
627 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
628
629 va_start(ap, fmt);
630 _fr_vlog(log, type, file, line, arg_names, fmt, ap);
631 va_end(ap);
632}
633
634/** Drain any outstanding messages from the fr_strerror buffers
635 *
636 * This function drains any messages from fr_strerror buffer prefixing
637 * the first message with fmt + args.
638 *
639 * If a prefix is specified in rules, this is prepended to all lines
640 * logged. The prefix is useful for adding context, i.e. configuration
641 * file and line number information.
642 *
643 * @param[in] log destination.
644 * @param[in] type of log message.
645 * @param[in] file src file the log message was generated in.
646 * @param[in] line number the log message was generated on.
647 * @param[in] f_rules for printing multiline errors.
648 * @param[in] arg_names source text of each substitution argument, or NULL.
649 * @param[in] fmt with printf style substitution tokens.
650 * @param[in] ap Substitution arguments.
651 */
652void _fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
653 fr_log_perror_format_t const *f_rules,
654 UNUSED char const * const arg_names[], char const *fmt, va_list ap)
655{
656 char const *error;
657 static fr_log_perror_format_t default_f_rules;
658
659 TALLOC_CTX *thread_log_pool;
660 fr_sbuff_marker_t prefix_m;
661
662 fr_sbuff_t sbuff;
664
665 /*
666 * Non-debug message, or debugging is enabled. Log it.
667 */
668 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
669
670 if (!f_rules) f_rules = &default_f_rules;
671
672 thread_log_pool = fr_log_pool_init();
673
674 /*
675 * Setup the aggregation buffer
676 */
677 fr_sbuff_init_talloc(thread_log_pool, &sbuff, &tctx, 1024, 16384);
678
679 /*
680 * Add the prefix for the first line
681 */
682 if (f_rules->first_prefix) (void) fr_sbuff_in_strcpy(&sbuff, f_rules->first_prefix);
683
684 /*
685 * Add the (optional) message, and/or (optional) error
686 * with the error_sep.
687 * i.e. <msg>: <error>
688 */
689 error = fr_strerror_pop();
690
691 if (!error && !fmt) return; /* NOOP */
692
693 if (fmt) {
694 va_list aq;
695
696 va_copy(aq, ap);
697 fr_sbuff_in_vsprintf(&sbuff, fmt, aq);
698 va_end(aq);
699 }
700
701 if (error && (fmt || f_rules->first_prefix)) {
702 if (fmt) (void) fr_sbuff_in_strcpy(&sbuff, ": ");
703 (void) fr_sbuff_in_strcpy(&sbuff, error);
704 }
705
706 error = fr_sbuff_start(&sbuff); /* may not be talloced with const */
707
708 /*
709 * Log the first line
710 */
711 fr_log(log, type, file, line, "%s", error);
712
713 fr_sbuff_set_to_start(&sbuff);
714 if (f_rules->subsq_prefix) {
715 (void) fr_sbuff_in_strcpy(&sbuff, f_rules->subsq_prefix);
716 fr_sbuff_marker(&prefix_m, &sbuff);
717 }
718
719 /*
720 * Print out additional error lines
721 */
722 while ((error = fr_strerror_pop())) {
723 if (f_rules->subsq_prefix) {
724 fr_sbuff_set(&sbuff, &prefix_m);
725 (void) fr_sbuff_in_strcpy(&sbuff, error); /* may not be talloced with const */
726 error = fr_sbuff_start(&sbuff);
727 }
728
729 fr_log(log, type, file, line, "%s", error);
730 }
731
732 talloc_free(sbuff.buff);
733}
734
735/** Drain any outstanding messages from the fr_strerror buffers
736 *
737 * This function drains any messages from fr_strerror buffer adding a prefix (fmt)
738 * to the first message.
739 *
740 * @param[in] log destination.
741 * @param[in] type of log message.
742 * @param[in] file src file the log message was generated in.
743 * @param[in] line number the log message was generated on.
744 * @param[in] rules for printing multiline errors.
745 * @param[in] arg_names source text of each substitution argument, or NULL.
746 * @param[in] fmt with printf style substitution tokens.
747 * @param[in] ... Substitution arguments.
748 */
749void _fr_log_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
750 fr_log_perror_format_t const *rules,
751 char const * const arg_names[], char const *fmt, ...)
752{
753 va_list ap;
754
755 va_start(ap, fmt);
756 _fr_vlog_perror(log, type, file, line, rules, arg_names, fmt, ap);
757 va_end(ap);
758}
759
760DIAG_OFF(format-nonliteral)
761/** Print out an error marker
762 *
763 * @param[in] log destination.
764 * @param[in] type of log message.
765 * @param[in] file src file the log message was generated in.
766 * @param[in] line number the log message was generated on.
767 * @param[in] str Subject string we're printing a marker for.
768 * @param[in] str_len Subject string length. Use SIZE_MAX for the
769 * length of the string.
770 * @param[in] marker_idx Where to place the marker. May be negative.
771 * @param[in] marker text to print at marker_idx.
772 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
773 * @param[in] ... Arguments for line_prefix_fmt.
774 */
775void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
776 char const *str, size_t str_len,
777 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
778{
779 char const *ellipses = "";
780 va_list ap;
781 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
782 char *line_prefix = NULL;
783 static char const marker_spaces[] = " "; /* 60 */
784
785 if (str_len == SIZE_MAX) str_len = strlen(str);
786
787 if (marker_idx < 0) marker_idx = marker_idx * -1;
788
789 if ((size_t)marker_idx >= sizeof(marker_spaces)) {
790 size_t offset = (marker_idx - (sizeof(marker_spaces) - 1)) + (sizeof(marker_spaces) * 0.75);
791 marker_idx -= offset;
792
793 if (offset > str_len) offset = str_len;
794 str += offset;
795 str_len -= offset;
796
797 ellipses = "... ";
798 }
799
800 if (line_prefix_fmt) {
801 va_start(ap, line_prefix_fmt);
802 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
803 va_end(ap);
804 }
805
806 fr_log(log, type, file, line, "%s%s%.*s",
807 line_prefix ? line_prefix : "", ellipses, (int)str_len, str);
808 fr_log(log, type, file, line, "%s%s%.*s^ %s",
809 line_prefix ? line_prefix : "", ellipses, (int)marker_idx, marker_spaces, marker);
810
811 if (line_prefix_fmt) talloc_free(line_prefix);
812}
813
814/** Print out hex block
815 *
816 * @param[in] log destination.
817 * @param[in] type of log message.
818 * @param[in] file src file the log message was generated in.
819 * @param[in] line number the log message was generated on.
820 * @param[in] data to print.
821 * @param[in] data_len length of data.
822 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
823 * @param[in] ... Arguments for line_prefix_fmt.
824 */
825void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
826 uint8_t const *data, size_t data_len, char const *line_prefix_fmt, ...)
827{
828 size_t i, j, len;
829 char buffer[(0x10 * 3) + 1];
830 char *p, *end = buffer + sizeof(buffer);
831 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
832 char *line_prefix = NULL;
833
834 if (line_prefix_fmt) {
835 va_list ap;
836
837 va_start(ap, line_prefix_fmt);
838 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
839 va_end(ap);
840 }
841
842 for (i = 0; i < data_len; i += 0x10) {
843 len = 0x10;
844 if ((i + len) > data_len) len = data_len - i;
845
846 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
847
848 if (line_prefix_fmt) {
849 fr_log(log, type, file, line, "%s%04x: %s",
850 line_prefix, (unsigned int) i, buffer);
851 } else {
852 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
853 }
854 }
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] marker_idx Where to place the marker. May be negative.
868 * @param[in] marker text to print at marker_idx.
869 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
870 * @param[in] ... Arguments for line_prefix_fmt.
871 */
872void fr_log_hex_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
873 uint8_t const *data, size_t data_len,
874 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
875{
876 size_t i, j, len;
877 char buffer[(0x10 * 3) + 1];
878 char *p, *end = buffer + sizeof(buffer);
879 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
880
881 char *line_prefix = NULL;
882 static char spaces[3 * 0x10]; /* Bytes per line */
883
884 if (!*spaces) memset(spaces, ' ', sizeof(spaces) - 1); /* Leave a \0 */
885
886 if (marker_idx < 0) marker_idx = marker_idx * -1;
887 if (line_prefix_fmt) {
888 va_list ap;
889
890 va_start(ap, line_prefix_fmt);
891 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
892 va_end(ap);
893 }
894
895 for (i = 0; i < data_len; i += 0x10) {
896 len = 0x10;
897 if ((i + len) > data_len) len = data_len - i;
898
899 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
900
901 if (line_prefix_fmt) {
902 fr_log(log, type, file, line, "%s%04x: %s",
903 line_prefix, (unsigned int) i, buffer);
904 } else {
905 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
906 }
907
908 /*
909 * Marker is on this line
910 */
911 if (((size_t)marker_idx >= i) && ((size_t)marker_idx < (i + 0x10))) {
912 if (line_prefix_fmt) {
913 fr_log(log, type, file, line, "%s %.*s^ %s", line_prefix,
914 (int)((marker_idx - i) * 3), spaces, marker);
915 } else {
916 fr_log(log, type, file, line, " %.*s^ %s",
917 (int)((marker_idx - i) * 3), spaces, marker);
918 }
919 }
920 }
921
922 if (line_prefix_fmt) talloc_free(line_prefix);
923}
924DIAG_ON(format-nonliteral)
925/** On fault, reset STDOUT and STDERR to something useful
926 *
927 * @return 0
928 */
929static int _restore_std_legacy(UNUSED int sig)
930{
931 if ((stderr_fd > 0) && (stdout_fd > 0)) {
932 dup2(stdout_fd, STDOUT_FILENO);
933 dup2(stderr_fd, STDERR_FILENO);
934 return 0;
935 }
936
937 return 0;
938}
939
940/** Initialise file descriptors based on logging destination
941 *
942 * @param log Logger to manipulate.
943 * @param daemonize Whether the server is starting as a daemon.
944 * @return
945 * - 0 on success.
946 * - -1 on failure.
947 */
948int fr_log_init_legacy(fr_log_t *log, bool daemonize)
949{
950 int devnull_legacy;
951
952 fr_log_rate_limit = daemonize;
953
954 /*
955 * If we're running in foreground mode, save STDIN /
956 * STDERR as higher FDs, which won't get used by anyone
957 * else. When we fork/exec a program, its STD FDs will
958 * get set to pipes. We later set STDOUT / STDERR to
959 * /dev/null, so that any library trying to write to them
960 * doesn't screw anything up.
961 *
962 * Then, when something goes wrong, restore them so that
963 * any debugger called from the panic action has access
964 * to STDOUT / STDERR.
965 */
966 if (!daemonize) {
968
969 stdout_fd = dup(STDOUT_FILENO);
970 stderr_fd = dup(STDERR_FILENO);
971 }
972
973 devnull_legacy = open("/dev/null", O_RDWR);
974 if (devnull_legacy < 0) {
975 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
976 return -1;
977 }
978
979 /*
980 * STDOUT & STDERR go to /dev/null, unless we have "-x",
981 * then STDOUT & STDERR go to the "-l log" destination.
982 *
983 * The complexity here is because "-l log" can go to
984 * STDOUT or STDERR, too.
985 */
986 if (log->dst == L_DST_STDOUT) {
987 setlinebuf(stdout);
988 log->fd = STDOUT_FILENO;
989
990 /*
991 * If we're debugging, allow STDERR to go to
992 * STDOUT too, for executed programs.
993 *
994 * Allow stdout when running in foreground mode
995 * as it's useful for some profiling tools,
996 * like mutrace.
997 */
998 if (fr_debug_lvl || !daemonize) {
999 dup2(STDOUT_FILENO, STDERR_FILENO);
1000 } else {
1001 dup2(devnull_legacy, STDERR_FILENO);
1002 }
1003
1004 } else if (log->dst == L_DST_STDERR) {
1005 setlinebuf(stderr);
1006 log->fd = STDERR_FILENO;
1007
1008 /*
1009 * If we're debugging, allow STDOUT to go to
1010 * STDERR too, for executed programs.
1011 *
1012 * Allow stdout when running in foreground mode
1013 * as it's useful for some profiling tools,
1014 * like mutrace.
1015 */
1016 if (fr_debug_lvl || !daemonize) {
1017 dup2(STDERR_FILENO, STDOUT_FILENO);
1018 } else {
1019 dup2(devnull_legacy, STDOUT_FILENO);
1020 }
1021
1022 } else if (log->dst == L_DST_SYSLOG) {
1023 /*
1024 * Discard STDOUT and STDERR no matter what the
1025 * status of debugging. Syslog isn't a file
1026 * descriptor, so we can't use it.
1027 */
1028 dup2(devnull_legacy, STDOUT_FILENO);
1029 dup2(devnull_legacy, STDERR_FILENO);
1030 log->print_level = false;
1031
1032 } else if (fr_debug_lvl) {
1033 /*
1034 * If we're debugging, allow STDOUT and STDERR to
1035 * go to the log file.
1036 */
1037 dup2(log->fd, STDOUT_FILENO);
1038 dup2(log->fd, STDERR_FILENO);
1039
1040 } else {
1041 /*
1042 * Not debugging, and the log isn't STDOUT or
1043 * STDERR. Ensure that we move both of them to
1044 * /dev/null, so that the calling terminal can
1045 * exit, and the output from executed programs
1046 * doesn't pollute STDOUT / STDERR.
1047 */
1048 dup2(devnull_legacy, STDOUT_FILENO);
1049 dup2(devnull_legacy, STDERR_FILENO);
1050 }
1051
1052 close(devnull_legacy);
1053
1054 fr_fault_set_log_fd(log->fd);
1055
1056 return 0;
1057}
1058
1059DIAG_ON(format-nonliteral)
1060
1061/** Initialise log dst for stdout, stderr or /dev/null
1062 *
1063 * @param[out] log Destination to initialise.
1064 * @param[in] dst_type The specific type of log destination to initialise.
1065 * @return
1066 * - 0 on success.
1067 * - -1 on failure.
1068 */
1070{
1071 memset(log, 0, sizeof(*log));
1072
1073 log->dst = dst_type;
1074 switch (log->dst) {
1075 case L_DST_STDOUT:
1076 log->handle = stdout;
1077 break;
1078
1079 case L_DST_STDERR:
1080 log->handle = stderr;
1081 break;
1082
1083 case L_DST_NULL:
1084 log->handle = devnull;
1085 break;
1086
1087 default:
1088 fr_strerror_const("Invalid dst type for FD log destination");
1089 return -1;
1090 }
1091
1092 return 0;
1093}
1094
1095/** Initialise a file logging destination to a FILE*
1096 *
1097 * @param[out] log Destination to initialise.
1098 * @param[in] fp pre-existing handle
1099 * @return
1100 * - 0 on success.
1101 * - -1 on failure.
1102 */
1103int fr_log_init_fp(fr_log_t *log, FILE *fp)
1104{
1105 memset(log, 0, sizeof(*log));
1106
1107 log->dst = L_DST_FILES;
1108 log->handle = fp;
1109
1110 setlinebuf(log->handle);
1111 log->fd = fileno(log->handle);
1112
1113 return 0;
1114}
1115
1116/** Initialise a file logging destination
1117 *
1118 * @param[out] log Destination to initialise.
1119 * @param[in] file to open handle for.
1120 * @return
1121 * - 0 on success.
1122 * - -1 on failure.
1123 */
1124int fr_log_init_file(fr_log_t *log, char const *file)
1125{
1126 FILE *fp;
1127
1128 if (unlikely((fp = fopen(file, "a")) == NULL)) {
1129 fr_strerror_printf("Failed opening log file \"%s\": %s", file, fr_syserror(errno));
1130 return -1;
1131 }
1132
1133 if (fr_log_init_fp(log, fp) < 0) return -1;
1134
1135 /*
1136 * The init over-rode any filename, so we reset it here.
1137 */
1138 log->file = file;
1139 return 0;
1140}
1141
1142/** Write complete lines to syslog
1143 *
1144 */
1145static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
1146{
1147 static int syslog_priority_table[] = {
1148 [L_DBG] = LOG_DEBUG,
1149
1150 [L_INFO] = LOG_INFO,
1151 [L_DBG_INFO] = LOG_INFO,
1152
1153 [L_ERR] = LOG_ERR,
1154 [L_DBG_ERR] = LOG_ERR,
1155 [L_DBG_ERR_REQ] = LOG_ERR,
1156
1157 [L_WARN] = LOG_WARNING,
1158 [L_DBG_WARN] = LOG_WARNING,
1159 [L_DBG_WARN_REQ] = LOG_WARNING,
1160
1161 [L_AUTH] = LOG_AUTH | LOG_INFO
1162 };
1163
1164 syslog(syslog_priority_table[log_msg_type], "%.*s", (int)size, buf);
1165
1166 return size;
1167}
1168
1169/** Initialise a syslog logging destination
1170 *
1171 * @param[out] log Destination to initialise.
1172 * @return
1173 * - 0 on success.
1174 * - -1 on failure.
1175 */
1177{
1178 memset(log, 0, sizeof(*log));
1179
1180 log->dst = L_DST_SYSLOG;
1181 if (unlikely((log->handle = fopencookie(log, "w",
1183 .write = _syslog_write,
1184 })) == NULL)) {
1185 fr_strerror_printf("Failed opening syslog transpor: %s", fr_syserror(errno));
1186 return -1;
1187 }
1188
1189 setlinebuf(log->handle);
1190
1191 return 0;
1192}
1193
1194/** Initialise a function based logging destination
1195 *
1196 * @note Cookie functions receive the fr_log_t which contains the uctx, not the uctx directly.
1197 *
1198 * @param[out] log Destination to initialise.
1199 * @param[in] write Called when a complete log line is ready for writing.
1200 * @param[in] close May be NULL. Called when the logging destination has been closed.
1201 * @param[in] uctx for the write and close functions.
1202 * @return
1203 * - 0 on success.
1204 * - -1 on failure.
1205 */
1207{
1208 memset(log, 0, sizeof(*log));
1209
1210 log->dst = L_DST_FUNC;
1211
1212 if (unlikely((log->handle = fopencookie(log, "w",
1214 .write = write,
1215 .close = close
1216 })) == NULL)) {
1217 fr_strerror_printf("Failed opening func transport: %s", fr_syserror(errno));
1218 return -1;
1219 }
1220
1221 setlinebuf(log->handle);
1222 log->uctx = uctx;
1223
1224 return 0;
1225}
1226
1227/** Universal close function for all logging destinations
1228 *
1229 */
1231{
1232 switch (log->dst) {
1233 case L_DST_STDOUT:
1234 case L_DST_STDERR:
1235 case L_DST_NULL:
1236 return 0;
1237
1238 /*
1239 * Other log dsts
1240 */
1241 case L_DST_FILES:
1242 case L_DST_FUNC:
1243 case L_DST_SYSLOG:
1244 if (log->handle && (fclose(log->handle) < 0)) {
1245 fr_strerror_printf("Failed closing file handle: %s", fr_syserror(errno));
1246 return -1;
1247 }
1248 return 0;
1249
1250 case L_DST_NUM_DEST:
1251 break;
1252 }
1253
1254 fr_strerror_printf("Failed closing invalid log dst %u", log->dst);
1255 return -1;
1256}
1257
1258/** Manipulate stderr and stdout so that was capture all data send to it from libraries
1259 *
1260 * @param[in] el The event list we use to process logging data.
1261 * @param[in] daemonize Whether the server is starting as a daemon.
1262 * @return
1263 * - 0 on success.
1264 * - -1 on failure.
1265 */
1267{
1268 log_el = el;
1269
1270 fr_log_rate_limit = daemonize;
1271
1272 /*
1273 * dup the current stdout/stderr FDs and close
1274 * the FDs in the STDOUT/STDERR slots to get
1275 * the reference count back to one.
1276 */
1277 stdout_fd = dup(STDOUT_FILENO);
1278 if (unlikely(stdout_fd < 0)) {
1279 fr_strerror_printf("Failed cloning stdout FD: %s", fr_syserror(errno));
1280 return -1;
1281 }
1282
1283 /*
1284 * Create two unidirection pipes, duping one end
1285 * to the stdout/stderr slots and inserting the
1286 * other into our event loop
1287 */
1288 if (unlikely(pipe(stdout_pipe) < 0)) {
1289 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1290 error_0:
1291 log_el = NULL;
1292 close(stdout_fd);
1293 return -1;
1294 }
1295
1296 /*
1297 * This closes the other ref to the stdout FD.
1298 */
1299 if (unlikely(dup2(stdout_pipe[0], STDOUT_FILENO) < 0)) {
1300 fr_strerror_printf("Failed copying pipe end over stdout: %s", fr_syserror(errno));
1301 error_1:
1302 close(stdout_pipe[0]);
1303 stdout_pipe[0] = -1;
1304 close(stdout_pipe[1]);
1305 stdout_pipe[1] = -1;
1306 goto error_0;
1307 }
1308
1310 stdout_ctx.prefix = "(stdout)";
1313
1314 /*
1315 * Now do stderr...
1316 */
1317 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stdout_pipe[1], fr_log_fd_event, NULL, NULL, &stdout_ctx) < 0)) {
1318 fr_strerror_const_push("Failed adding stdout handler to event loop");
1319 error_2:
1320 dup2(STDOUT_FILENO, stdout_fd); /* Copy back the stdout FD */
1321 goto error_1;
1322 }
1323
1324 stderr_fd = dup(STDERR_FILENO);
1325 if (unlikely(stderr_fd < 0)) {
1326 fr_strerror_printf("Failed cloning stderr FD: %s", fr_syserror(errno));
1327
1328 error_3:
1330 goto error_2;
1331 }
1332
1333 if (unlikely(pipe(stderr_pipe) < 0)) {
1334 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1335 error_4:
1336 close(stderr_fd);
1337 goto error_3;
1338 }
1339
1340 if (unlikely(dup2(stderr_pipe[0], STDERR_FILENO) < 0)) {
1341 fr_strerror_printf("Failed copying pipe end over stderr: %s", fr_syserror(errno));
1342 error_5:
1343 close(stderr_pipe[0]);
1344 stderr_pipe[0] = -1;
1345 close(stderr_pipe[1]);
1346 stderr_pipe[1] = -1;
1347 goto error_4;
1348 }
1349
1351 stderr_ctx.prefix = "(stderr)";
1353 stderr_ctx.lvl = L_DBG_LVL_OFF; /* Log at all debug levels */
1354
1355 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stderr_pipe[1], fr_log_fd_event, NULL, NULL, &stderr_ctx) < 0)) {
1356 fr_strerror_const_push("Failed adding stdout handler to event loop");
1357 error_6:
1358 dup2(STDERR_FILENO, stderr_fd); /* Copy back the stderr FD */
1359 goto error_5;
1360 }
1361
1362 fr_fault_set_log_fd(STDERR_FILENO);
1363 fr_fault_set_cb(_restore_std_legacy); /* Restore the original file descriptors if we experience a fault */
1364
1365 /*
1366 * Setup our standard file *s
1367 */
1368 setlinebuf(stdout);
1369 setlinebuf(stderr);
1370
1371 devnull = fopen("/dev/null", "w");
1372 if (unlikely(!devnull)) {
1373 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
1374 goto error_6;
1375 }
1376
1378
1379 return 0;
1380}
1381
1382/** Restores the original stdout and stderr FDs, closes the pipes and removes them from the event loop
1383 *
1384 */
1386{
1387 if (!log_el) return;
1388
1390 close(stdout_pipe[1]);
1391 stdout_pipe[1] = -1;
1393 close(stderr_pipe[1]);
1394 stderr_pipe[1] = -1;
1395
1396 _restore_std_legacy(0); /* Will close stdout_pipe[0] and stderr_pipe[0] with dup2 */
1397
1398 stdout_pipe[0] = -1;
1399 stderr_pipe[0] = -1;
1400
1401 fclose(devnull);
1402}
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:1246
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition debug.c:1198
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:260
int fr_log_init_legacy(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
Definition log.c:948
#define VTC_RED
Colour following text red.
Definition log.c:284
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:332
static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
Write complete lines to syslog.
Definition log.c:1145
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition log.c:345
int fr_log_init_syslog(fr_log_t *log)
Initialise a syslog logging destination.
Definition log.c:1176
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:1266
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:749
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:825
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:872
#define VTC_YELLOW
Colour following text yellow.
Definition log.c:285
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:1385
static int _restore_std_legacy(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Definition log.c:929
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:1069
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:1206
#define VTC_RESET
Reset terminal text to default style/colour.
Definition log.c:287
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:292
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:775
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:194
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:306
int fr_log_init_file(fr_log_t *log, char const *file)
Initialise a file logging destination.
Definition log.c:1124
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:1103
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:652
static _Thread_local TALLOC_CTX * fr_log_pool
Definition log.c:43
bool log_dates_utc
Definition log.c:304
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:381
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:619
size_t fr_log_levels_len
Definition log.c:272
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:317
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:301
int fr_log_close(fr_log_t *log)
Universal close function for all logging destinations.
Definition log.c:1230
#define VTC_BOLD
Embolden following text.
Definition log.c:286
#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:1471
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:201
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
Definition sbuff.c:2242
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:1942
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:1580
#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:1152
@ 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:1340
#define fr_box_strvalue_len(_val, _len)
Definition value.h:309
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1030