The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: d1a9cc9f8832964aa894b4cb85ac8198f718f63a $")
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] fmt with printf style substitution tokens.
378 * @param[in] ap Substitution arguments.
379 */
380void fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, va_list ap)
381{
382 int colourise = log->colourise;
383 char *buffer;
384 TALLOC_CTX *pool, *thread_log_pool;
385 char const *fmt_colour = "";
386 char const *fmt_location = "";
387 char fmt_time[50];
388 char const *fmt_type = "";
389 char *fmt_msg;
390
391 static char const *spaces = " "; /* 40 */
392
393 fmt_time[0] = '\0';
394
395 /*
396 * If we don't want any messages, then
397 * throw them away.
398 */
399 if (log->dst == L_DST_NULL) return;
400
401 thread_log_pool = fr_log_pool_init();
402 pool = talloc_new(thread_log_pool); /* Track our local allocations */
403
404 /*
405 * Set colourisation
406 */
407 if (colourise) {
408 fmt_colour = fr_table_str_by_value(colours, type, NULL);
409 if (!fmt_colour) colourise = false;
410 }
411
412 /*
413 * Print src file/line
414 */
415 if (log->line_number) {
416 size_t len;
417 int pad = 0;
418 char *str;
419
420 str = talloc_asprintf(pool, "%s:%i", file, line);
421 len = talloc_strlen(str);
422
423 /*
424 * Only increase the indent
425 */
426 if (len > location_indent) {
427 location_indent = len;
428 } else {
429 pad = location_indent - len;
430 }
431
432 fmt_location = talloc_asprintf_append_buffer(str, "%.*s : ", pad, spaces);
433 }
434 /*
435 * Determine if we need to add a timestamp to the start of the message
436 */
437 switch (log->timestamp) {
438 case L_TIMESTAMP_OFF:
439 break;
440
441 /*
442 * If we're not logging to syslog, and the debug level is -xxx
443 * then log timestamps by default.
444 */
445 case L_TIMESTAMP_AUTO:
446 if (log->dst == L_DST_SYSLOG) break;
447 if ((log->dst != L_DST_FILES) && (fr_debug_lvl <= L_DBG_LVL_2)) break;
449
450 case L_TIMESTAMP_ON:
451 {
453 fr_sbuff_t time_sbuff = FR_SBUFF_OUT(fmt_time, sizeof(fmt_time));
454 fr_unix_time_to_str(&time_sbuff, now, FR_TIME_RES_USEC, log->dates_utc);
455 break;
456 }
457 }
458
459 /*
460 * Add ERROR or WARNING prefixes to messages not going to
461 * syslog. It's redundant for syslog because of syslog
462 * facilities.
463 */
464 if (log->dst != L_DST_SYSLOG) {
465 /*
466 * We always print "WARN" and "ERROR" prefixes.
467 */
468 switch (type) {
469 case L_DBG_WARN:
470 case L_DBG_ERR:
471 fmt_type = fr_table_str_by_value(fr_log_levels, type, NULL);
472 break;
473
474 default:
475 /*
476 * Otherwise, print the other info levels only if we're asked to print the level,
477 * and we're not colourizing the output. If we're colourizing the output, then
478 * the colors indicate the debug level (info, warning, error), and we don't need
479 * any prefix.
480 */
481 if (log->print_level && !log->colourise) fmt_type = fr_table_str_by_value(fr_log_levels, type, ": ");
482 break;
483 }
484 }
485
486 /*
487 * Sanitize output.
488 *
489 * Most strings should be escaped before they get here.
490 */
491 {
492 char *p, *end;
493
494 p = fmt_msg = fr_vasprintf(pool, fmt, ap);
495 end = p + talloc_strlen(fmt_msg);
496
497 /*
498 * Filter out control chars and non UTF8 chars
499 */
500 for (p = fmt_msg; p < end; p++) {
501 int clen;
502
503 switch (*p) {
504 case '\r':
505 case '\n':
506 *p = ' ';
507 break;
508
509 case '\t':
510 continue;
511
512 default:
513 clen = fr_utf8_char((uint8_t *)p, -1);
514 if (!clen) {
515 *p = '?';
516 continue;
517 }
518 p += (clen - 1);
519 break;
520 }
521 }
522 }
523
524 switch (log->dst) {
525
526#ifdef HAVE_SYSLOG_H
527 case L_DST_SYSLOG:
528 {
529 int syslog_priority = L_DBG;
530
531 switch (type) {
532 case L_DBG:
533 case L_DBG_INFO:
534 case L_DBG_WARN:
535 case L_DBG_ERR:
536 case L_DBG_ERR_REQ:
537 case L_DBG_WARN_REQ:
538 syslog_priority= LOG_DEBUG;
539 break;
540
541 case L_INFO:
542 syslog_priority = LOG_INFO;
543 break;
544
545 case L_WARN:
546 syslog_priority = LOG_WARNING;
547 break;
548
549 case L_ERR:
550 syslog_priority = LOG_ERR;
551 break;
552
553 case L_AUTH:
554 syslog_priority = LOG_AUTH | LOG_INFO;
555 break;
556 }
557 syslog(syslog_priority,
558 "%s" /* time */
559 "%s" /* time sep */
560 "%s", /* message */
561 fmt_time,
562 fmt_time[0] ? ": " : "",
563 fmt_msg);
564 }
565 break;
566#endif
567
568 case L_DST_FILES:
569 case L_DST_STDOUT:
570 case L_DST_STDERR:
571 {
572 size_t len, wrote;
573
574 buffer = talloc_asprintf(pool,
575 "%s" /* colourise */
576 "%s" /* location */
577 "%s" /* time */
578 "%s" /* time sep */
579 "%s" /* message type */
580 "%s" /* message */
581 "%s" /* colourise reset */
582 "\n",
583 colourise ? fmt_colour : "",
584 fmt_location,
585 fmt_time,
586 fmt_time[0] ? ": " : "",
587 fmt_type,
588 fmt_msg,
589 colourise ? VTC_RESET : "");
590
591 len = talloc_strlen(buffer);
592 wrote = write(log->fd, buffer, len);
593 if (wrote < len) return;
594 }
595 break;
596
597 default:
598 case L_DST_NULL: /* should have been caught above */
599 break;
600 }
601
602 talloc_free(pool); /* clears all temporary allocations */
603
604 return;
605}
606
607/** Send a server log message to its destination
608 *
609 * @param log destination.
610 * @param type of log message.
611 * @param file where the log message originated
612 * @param line where the log message originated
613 * @param fmt with printf style substitution tokens.
614 * @param ... Substitution arguments.
615 */
616void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, ...)
617{
618 va_list ap;
619
620 /*
621 * Non-debug message, or debugging is enabled. Log it.
622 */
623 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
624
625 va_start(ap, fmt);
626 fr_vlog(log, type, file, line, fmt, ap);
627 va_end(ap);
628}
629
630/** Drain any outstanding messages from the fr_strerror buffers
631 *
632 * This function drains any messages from fr_strerror buffer prefixing
633 * the first message with fmt + args.
634 *
635 * If a prefix is specified in rules, this is prepended to all lines
636 * logged. The prefix is useful for adding context, i.e. configuration
637 * file and line number information.
638 *
639 * @param[in] log destination.
640 * @param[in] type of log message.
641 * @param[in] file src file the log message was generated in.
642 * @param[in] line number the log message was generated on.
643 * @param[in] f_rules for printing multiline errors.
644 * @param[in] fmt with printf style substitution tokens.
645 * @param[in] ap Substitution arguments.
646 */
647void fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
648 fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
649{
650 char const *error;
651 static fr_log_perror_format_t default_f_rules;
652
653 TALLOC_CTX *thread_log_pool;
654 fr_sbuff_marker_t prefix_m;
655
656 fr_sbuff_t sbuff;
658
659 /*
660 * Non-debug message, or debugging is enabled. Log it.
661 */
662 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
663
664 if (!f_rules) f_rules = &default_f_rules;
665
666 thread_log_pool = fr_log_pool_init();
667
668 /*
669 * Setup the aggregation buffer
670 */
671 fr_sbuff_init_talloc(thread_log_pool, &sbuff, &tctx, 1024, 16384);
672
673 /*
674 * Add the prefix for the first line
675 */
676 if (f_rules->first_prefix) (void) fr_sbuff_in_strcpy(&sbuff, f_rules->first_prefix);
677
678 /*
679 * Add the (optional) message, and/or (optional) error
680 * with the error_sep.
681 * i.e. <msg>: <error>
682 */
683 error = fr_strerror_pop();
684
685 if (!error && !fmt) return; /* NOOP */
686
687 if (fmt) {
688 va_list aq;
689
690 va_copy(aq, ap);
691 fr_sbuff_in_vsprintf(&sbuff, fmt, aq);
692 va_end(aq);
693 }
694
695 if (error && (fmt || f_rules->first_prefix)) {
696 if (fmt) (void) fr_sbuff_in_strcpy(&sbuff, ": ");
697 (void) fr_sbuff_in_strcpy(&sbuff, error);
698 }
699
700 error = fr_sbuff_start(&sbuff); /* may not be talloced with const */
701
702 /*
703 * Log the first line
704 */
705 fr_log(log, type, file, line, "%s", error);
706
707 fr_sbuff_set_to_start(&sbuff);
708 if (f_rules->subsq_prefix) {
709 (void) fr_sbuff_in_strcpy(&sbuff, f_rules->subsq_prefix);
710 fr_sbuff_marker(&prefix_m, &sbuff);
711 }
712
713 /*
714 * Print out additional error lines
715 */
716 while ((error = fr_strerror_pop())) {
717 if (f_rules->subsq_prefix) {
718 fr_sbuff_set(&sbuff, &prefix_m);
719 (void) fr_sbuff_in_strcpy(&sbuff, error); /* may not be talloced with const */
720 error = fr_sbuff_start(&sbuff);
721 }
722
723 fr_log(log, type, file, line, "%s", error);
724 }
725
726 talloc_free(sbuff.buff);
727}
728
729/** Drain any outstanding messages from the fr_strerror buffers
730 *
731 * This function drains any messages from fr_strerror buffer adding a prefix (fmt)
732 * to the first message.
733 *
734 * @param[in] log destination.
735 * @param[in] type of log message.
736 * @param[in] file src file the log message was generated in.
737 * @param[in] line number the log message was generated on.
738 * @param[in] rules for printing multiline errors.
739 * @param[in] fmt with printf style substitution tokens.
740 * @param[in] ... Substitution arguments.
741 */
742void fr_log_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
743 fr_log_perror_format_t const *rules, char const *fmt, ...)
744{
745 va_list ap;
746
747 va_start(ap, fmt);
748 fr_vlog_perror(log, type, file, line, rules, fmt, ap);
749 va_end(ap);
750}
751
752DIAG_OFF(format-nonliteral)
753/** Print out an error marker
754 *
755 * @param[in] log destination.
756 * @param[in] type of log message.
757 * @param[in] file src file the log message was generated in.
758 * @param[in] line number the log message was generated on.
759 * @param[in] str Subject string we're printing a marker for.
760 * @param[in] str_len Subject string length. Use SIZE_MAX for the
761 * length of the string.
762 * @param[in] marker_idx Where to place the marker. May be negative.
763 * @param[in] marker text to print at marker_idx.
764 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
765 * @param[in] ... Arguments for line_prefix_fmt.
766 */
767void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
768 char const *str, size_t str_len,
769 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
770{
771 char const *ellipses = "";
772 va_list ap;
773 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
774 char *line_prefix = NULL;
775 static char const marker_spaces[] = " "; /* 60 */
776
777 if (str_len == SIZE_MAX) str_len = strlen(str);
778
779 if (marker_idx < 0) marker_idx = marker_idx * -1;
780
781 if ((size_t)marker_idx >= sizeof(marker_spaces)) {
782 size_t offset = (marker_idx - (sizeof(marker_spaces) - 1)) + (sizeof(marker_spaces) * 0.75);
783 marker_idx -= offset;
784
785 if (offset > str_len) offset = str_len;
786 str += offset;
787 str_len -= offset;
788
789 ellipses = "... ";
790 }
791
792 if (line_prefix_fmt) {
793 va_start(ap, line_prefix_fmt);
794 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
795 va_end(ap);
796 }
797
798 fr_log(log, type, file, line, "%s%s%.*s",
799 line_prefix ? line_prefix : "", ellipses, (int)str_len, str);
800 fr_log(log, type, file, line, "%s%s%.*s^ %s",
801 line_prefix ? line_prefix : "", ellipses, (int)marker_idx, marker_spaces, marker);
802
803 if (line_prefix_fmt) talloc_free(line_prefix);
804}
805
806/** Print out hex block
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] data to print.
813 * @param[in] data_len length of data.
814 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
815 * @param[in] ... Arguments for line_prefix_fmt.
816 */
817void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
818 uint8_t const *data, size_t data_len, char const *line_prefix_fmt, ...)
819{
820 size_t i, j, len;
821 char buffer[(0x10 * 3) + 1];
822 char *p, *end = buffer + sizeof(buffer);
823 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
824 char *line_prefix = NULL;
825
826 if (line_prefix_fmt) {
827 va_list ap;
828
829 va_start(ap, line_prefix_fmt);
830 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
831 va_end(ap);
832 }
833
834 for (i = 0; i < data_len; i += 0x10) {
835 len = 0x10;
836 if ((i + len) > data_len) len = data_len - i;
837
838 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
839
840 if (line_prefix_fmt) {
841 fr_log(log, type, file, line, "%s%04x: %s",
842 line_prefix, (unsigned int) i, buffer);
843 } else {
844 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
845 }
846 }
847
848 if (line_prefix_fmt) talloc_free(line_prefix);
849}
850
851/** Print out hex block
852 *
853 * @param[in] log destination.
854 * @param[in] type of log message.
855 * @param[in] file src file the log message was generated in.
856 * @param[in] line number the log message was generated on.
857 * @param[in] data to print.
858 * @param[in] data_len length of data.
859 * @param[in] marker_idx Where to place the marker. May be negative.
860 * @param[in] marker text to print at marker_idx.
861 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
862 * @param[in] ... Arguments for line_prefix_fmt.
863 */
864void fr_log_hex_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
865 uint8_t const *data, size_t data_len,
866 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
867{
868 size_t i, j, len;
869 char buffer[(0x10 * 3) + 1];
870 char *p, *end = buffer + sizeof(buffer);
871 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
872
873 char *line_prefix = NULL;
874 static char spaces[3 * 0x10]; /* Bytes per line */
875
876 if (!*spaces) memset(spaces, ' ', sizeof(spaces) - 1); /* Leave a \0 */
877
878 if (marker_idx < 0) marker_idx = marker_idx * -1;
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 * Marker is on this line
902 */
903 if (((size_t)marker_idx >= i) && ((size_t)marker_idx < (i + 0x10))) {
904 if (line_prefix_fmt) {
905 fr_log(log, type, file, line, "%s %.*s^ %s", line_prefix,
906 (int)((marker_idx - i) * 3), spaces, marker);
907 } else {
908 fr_log(log, type, file, line, " %.*s^ %s",
909 (int)((marker_idx - i) * 3), spaces, marker);
910 }
911 }
912 }
913
914 if (line_prefix_fmt) talloc_free(line_prefix);
915}
916DIAG_ON(format-nonliteral)
917/** On fault, reset STDOUT and STDERR to something useful
918 *
919 * @return 0
920 */
921static int _restore_std_legacy(UNUSED int sig)
922{
923 if ((stderr_fd > 0) && (stdout_fd > 0)) {
924 dup2(stderr_fd, STDOUT_FILENO);
925 dup2(stdout_fd, STDERR_FILENO);
926 return 0;
927 }
928
929 return 0;
930}
931
932/** Initialise file descriptors based on logging destination
933 *
934 * @param log Logger to manipulate.
935 * @param daemonize Whether the server is starting as a daemon.
936 * @return
937 * - 0 on success.
938 * - -1 on failure.
939 */
940int fr_log_init_legacy(fr_log_t *log, bool daemonize)
941{
942 int devnull_legacy;
943
944 fr_log_rate_limit = daemonize;
945
946 /*
947 * If we're running in foreground mode, save STDIN /
948 * STDERR as higher FDs, which won't get used by anyone
949 * else. When we fork/exec a program, its STD FDs will
950 * get set to pipes. We later set STDOUT / STDERR to
951 * /dev/null, so that any library trying to write to them
952 * doesn't screw anything up.
953 *
954 * Then, when something goes wrong, restore them so that
955 * any debugger called from the panic action has access
956 * to STDOUT / STDERR.
957 */
958 if (!daemonize) {
960
961 stdout_fd = dup(STDOUT_FILENO);
962 stderr_fd = dup(STDERR_FILENO);
963 }
964
965 devnull_legacy = open("/dev/null", O_RDWR);
966 if (devnull_legacy < 0) {
967 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
968 return -1;
969 }
970
971 /*
972 * STDOUT & STDERR go to /dev/null, unless we have "-x",
973 * then STDOUT & STDERR go to the "-l log" destination.
974 *
975 * The complexity here is because "-l log" can go to
976 * STDOUT or STDERR, too.
977 */
978 if (log->dst == L_DST_STDOUT) {
979 setlinebuf(stdout);
980 log->fd = STDOUT_FILENO;
981
982 /*
983 * If we're debugging, allow STDERR to go to
984 * STDOUT too, for executed programs.
985 *
986 * Allow stdout when running in foreground mode
987 * as it's useful for some profiling tools,
988 * like mutrace.
989 */
990 if (fr_debug_lvl || !daemonize) {
991 dup2(STDOUT_FILENO, STDERR_FILENO);
992 } else {
993 dup2(devnull_legacy, STDERR_FILENO);
994 }
995
996 } else if (log->dst == L_DST_STDERR) {
997 setlinebuf(stderr);
998 log->fd = STDERR_FILENO;
999
1000 /*
1001 * If we're debugging, allow STDOUT to go to
1002 * STDERR too, for executed programs.
1003 *
1004 * Allow stdout when running in foreground mode
1005 * as it's useful for some profiling tools,
1006 * like mutrace.
1007 */
1008 if (fr_debug_lvl || !daemonize) {
1009 dup2(STDERR_FILENO, STDOUT_FILENO);
1010 } else {
1011 dup2(devnull_legacy, STDOUT_FILENO);
1012 }
1013
1014 } else if (log->dst == L_DST_SYSLOG) {
1015 /*
1016 * Discard STDOUT and STDERR no matter what the
1017 * status of debugging. Syslog isn't a file
1018 * descriptor, so we can't use it.
1019 */
1020 dup2(devnull_legacy, STDOUT_FILENO);
1021 dup2(devnull_legacy, STDERR_FILENO);
1022 log->print_level = false;
1023
1024 } else if (fr_debug_lvl) {
1025 /*
1026 * If we're debugging, allow STDOUT and STDERR to
1027 * go to the log file.
1028 */
1029 dup2(log->fd, STDOUT_FILENO);
1030 dup2(log->fd, STDERR_FILENO);
1031
1032 } else {
1033 /*
1034 * Not debugging, and the log isn't STDOUT or
1035 * STDERR. Ensure that we move both of them to
1036 * /dev/null, so that the calling terminal can
1037 * exit, and the output from executed programs
1038 * doesn't pollute STDOUT / STDERR.
1039 */
1040 dup2(devnull_legacy, STDOUT_FILENO);
1041 dup2(devnull_legacy, STDERR_FILENO);
1042 }
1043
1044 close(devnull_legacy);
1045
1046 fr_fault_set_log_fd(log->fd);
1047
1048 return 0;
1049}
1050
1051DIAG_ON(format-nonliteral)
1052
1053/** Initialise log dst for stdout, stderr or /dev/null
1054 *
1055 * @param[out] log Destination to initialise.
1056 * @param[in] dst_type The specific type of log destination to initialise.
1057 * @return
1058 * - 0 on success.
1059 * - -1 on failure.
1060 */
1062{
1063 memset(log, 0, sizeof(*log));
1064
1065 log->dst = dst_type;
1066 switch (log->dst) {
1067 case L_DST_STDOUT:
1068 log->handle = stdout;
1069 break;
1070
1071 case L_DST_STDERR:
1072 log->handle = stderr;
1073 break;
1074
1075 case L_DST_NULL:
1076 log->handle = devnull;
1077 break;
1078
1079 default:
1080 fr_strerror_const("Invalid dst type for FD log destination");
1081 return -1;
1082 }
1083
1084 return 0;
1085}
1086
1087/** Initialise a file logging destination to a FILE*
1088 *
1089 * @param[out] log Destination to initialise.
1090 * @param[in] fp pre-existing handle
1091 * @return
1092 * - 0 on success.
1093 * - -1 on failure.
1094 */
1095int fr_log_init_fp(fr_log_t *log, FILE *fp)
1096{
1097 memset(log, 0, sizeof(*log));
1098
1099 log->dst = L_DST_FILES;
1100 log->handle = fp;
1101
1102 setlinebuf(log->handle);
1103 log->fd = fileno(log->handle);
1104
1105 return 0;
1106}
1107
1108/** Initialise a file logging destination
1109 *
1110 * @param[out] log Destination to initialise.
1111 * @param[in] file to open handle for.
1112 * @return
1113 * - 0 on success.
1114 * - -1 on failure.
1115 */
1116int fr_log_init_file(fr_log_t *log, char const *file)
1117{
1118 FILE *fp;
1119
1120 if (unlikely((fp = fopen(file, "a")) == NULL)) {
1121 fr_strerror_printf("Failed opening log file \"%s\": %s", file, fr_syserror(errno));
1122 return -1;
1123 }
1124
1125 if (fr_log_init_fp(log, fp) < 0) return -1;
1126
1127 /*
1128 * The init over-rode any filename, so we reset it here.
1129 */
1130 log->file = file;
1131 return 0;
1132}
1133
1134/** Write complete lines to syslog
1135 *
1136 */
1137static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
1138{
1139 static int syslog_priority_table[] = {
1140 [L_DBG] = LOG_DEBUG,
1141
1142 [L_INFO] = LOG_INFO,
1143 [L_DBG_INFO] = LOG_INFO,
1144
1145 [L_ERR] = LOG_ERR,
1146 [L_DBG_ERR] = LOG_ERR,
1147 [L_DBG_ERR_REQ] = LOG_ERR,
1148
1149 [L_WARN] = LOG_WARNING,
1150 [L_DBG_WARN] = LOG_WARNING,
1151 [L_DBG_WARN_REQ] = LOG_WARNING,
1152
1153 [L_AUTH] = LOG_AUTH | LOG_INFO
1154 };
1155
1156 syslog(syslog_priority_table[log_msg_type], "%.*s", (int)size, buf);
1157
1158 return size;
1159}
1160
1161/** Initialise a syslog logging destination
1162 *
1163 * @param[out] log Destination to initialise.
1164 * @return
1165 * - 0 on success.
1166 * - -1 on failure.
1167 */
1169{
1170 memset(log, 0, sizeof(*log));
1171
1172 log->dst = L_DST_SYSLOG;
1173 if (unlikely((log->handle = fopencookie(log, "w",
1175 .write = _syslog_write,
1176 })) == NULL)) {
1177 fr_strerror_printf("Failed opening syslog transpor: %s", fr_syserror(errno));
1178 return -1;
1179 }
1180
1181 setlinebuf(log->handle);
1182
1183 return 0;
1184}
1185
1186/** Initialise a function based logging destination
1187 *
1188 * @note Cookie functions receive the fr_log_t which contains the uctx, not the uctx directly.
1189 *
1190 * @param[out] log Destination to initialise.
1191 * @param[in] write Called when a complete log line is ready for writing.
1192 * @param[in] close May be NULL. Called when the logging destination has been closed.
1193 * @param[in] uctx for the write and close functions.
1194 * @return
1195 * - 0 on success.
1196 * - -1 on failure.
1197 */
1199{
1200 memset(log, 0, sizeof(*log));
1201
1202 log->dst = L_DST_FUNC;
1203
1204 if (unlikely((log->handle = fopencookie(log, "w",
1206 .write = write,
1207 .close = close
1208 })) == NULL)) {
1209 fr_strerror_printf("Failed opening func transport: %s", fr_syserror(errno));
1210 return -1;
1211 }
1212
1213 setlinebuf(log->handle);
1214 log->uctx = uctx;
1215
1216 return 0;
1217}
1218
1219/** Universal close function for all logging destinations
1220 *
1221 */
1223{
1224 switch (log->dst) {
1225 case L_DST_STDOUT:
1226 case L_DST_STDERR:
1227 case L_DST_NULL:
1228 return 0;
1229
1230 /*
1231 * Other log dsts
1232 */
1233 case L_DST_FILES:
1234 case L_DST_FUNC:
1235 case L_DST_SYSLOG:
1236 if (log->handle && (fclose(log->handle) < 0)) {
1237 fr_strerror_printf("Failed closing file handle: %s", fr_syserror(errno));
1238 return -1;
1239 }
1240 return 0;
1241
1242 case L_DST_NUM_DEST:
1243 break;
1244 }
1245
1246 fr_strerror_printf("Failed closing invalid log dst %u", log->dst);
1247 return -1;
1248}
1249
1250/** Manipulate stderr and stdout so that was capture all data send to it from libraries
1251 *
1252 * @param[in] el The event list we use to process logging data.
1253 * @param[in] daemonize Whether the server is starting as a daemon.
1254 * @return
1255 * - 0 on success.
1256 * - -1 on failure.
1257 */
1259{
1260 log_el = el;
1261
1262 fr_log_rate_limit = daemonize;
1263
1264 /*
1265 * dup the current stdout/stderr FDs and close
1266 * the FDs in the STDOUT/STDERR slots to get
1267 * the reference count back to one.
1268 */
1269 stdout_fd = dup(STDOUT_FILENO);
1270 if (unlikely(stdout_fd < 0)) {
1271 fr_strerror_printf("Failed cloning stdout FD: %s", fr_syserror(errno));
1272 return -1;
1273 }
1274
1275 /*
1276 * Create two unidirection pipes, duping one end
1277 * to the stdout/stderr slots and inserting the
1278 * other into our event loop
1279 */
1280 if (unlikely(pipe(stdout_pipe) < 0)) {
1281 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1282 error_0:
1283 log_el = NULL;
1284 close(stdout_fd);
1285 return -1;
1286 }
1287
1288 /*
1289 * This closes the other ref to the stdout FD.
1290 */
1291 if (unlikely(dup2(stdout_pipe[0], STDOUT_FILENO) < 0)) {
1292 fr_strerror_printf("Failed copying pipe end over stdout: %s", fr_syserror(errno));
1293 error_1:
1294 close(stdout_pipe[0]);
1295 stdout_pipe[0] = -1;
1296 close(stdout_pipe[1]);
1297 stdout_pipe[1] = -1;
1298 goto error_0;
1299 }
1300
1302 stdout_ctx.prefix = "(stdout)";
1305
1306 /*
1307 * Now do stderr...
1308 */
1309 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stdout_pipe[1], fr_log_fd_event, NULL, NULL, &stdout_ctx) < 0)) {
1310 fr_strerror_const_push("Failed adding stdout handler to event loop");
1311 error_2:
1312 dup2(STDOUT_FILENO, stdout_fd); /* Copy back the stdout FD */
1313 goto error_1;
1314 }
1315
1316 stderr_fd = dup(STDERR_FILENO);
1317 if (unlikely(stderr_fd < 0)) {
1318 fr_strerror_printf("Failed cloning stderr FD: %s", fr_syserror(errno));
1319
1320 error_3:
1322 goto error_2;
1323 }
1324
1325 if (unlikely(pipe(stderr_pipe) < 0)) {
1326 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1327 error_4:
1328 close(stderr_fd);
1329 goto error_3;
1330 }
1331
1332 if (unlikely(dup2(stderr_pipe[0], STDOUT_FILENO) < 0)) {
1333 fr_strerror_printf("Failed copying pipe end over stderr: %s", fr_syserror(errno));
1334 error_5:
1335 close(stderr_pipe[0]);
1336 stderr_pipe[0] = -1;
1337 close(stderr_pipe[1]);
1338 stderr_pipe[1] = -1;
1339 goto error_4;
1340 }
1341
1343 stdout_ctx.prefix = "(stderr)";
1345 stdout_ctx.lvl = L_DBG_LVL_OFF; /* Log at all debug levels */
1346
1347 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stderr_pipe[1], fr_log_fd_event, NULL, NULL, &stderr_ctx) < 0)) {
1348 fr_strerror_const_push("Failed adding stdout handler to event loop");
1349 error_6:
1350 dup2(STDERR_FILENO, stderr_fd); /* Copy back the stderr FD */
1351 goto error_5;
1352 }
1353
1354 fr_fault_set_log_fd(STDERR_FILENO);
1355 fr_fault_set_cb(_restore_std_legacy); /* Restore the original file descriptors if we experience a fault */
1356
1357 /*
1358 * Setup our standard file *s
1359 */
1360 setlinebuf(stdout);
1361 setlinebuf(stderr);
1362
1363 devnull = fopen("/dev/null", "w");
1364 if (unlikely(!devnull)) {
1365 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
1366 goto error_6;
1367 }
1368
1370
1371 return 0;
1372}
1373
1374/** Restores the original stdout and stderr FDs, closes the pipes and removes them from the event loop
1375 *
1376 */
1378{
1379 if (!log_el) return;
1380
1382 close(stdout_pipe[1]);
1383 stdout_pipe[1] = -1;
1385 close(stderr_pipe[1]);
1386 stderr_pipe[1] = -1;
1387
1388 _restore_std_legacy(0); /* Will close stdout_pipe[0] and stderr_pipe[0] with dup2 */
1389
1390 stdout_pipe[0] = -1;
1391 stderr_pipe[0] = -1;
1392
1393 fclose(devnull);
1394}
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:442
bool fr_atexit_is_exiting(void)
Return whether we're currently in the teardown phase.
Definition atexit.c:452
#define fr_atexit_thread_local(_name, _free, _uctx)
Definition atexit.h:224
#define RCSID(id)
Definition build.h:512
#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:343
#define DIAG_ON(_x)
Definition build.h:487
#define unlikely(_x)
Definition build.h:407
#define UNUSED
Definition build.h:336
#define NUM_ELEMENTS(_t)
Definition build.h:358
#define DIAG_OFF(_x)
Definition build.h:486
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:1247
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition debug.c:1199
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:940
#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:1137
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:1168
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:1258
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:817
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:864
#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:1377
static int _restore_std_legacy(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Definition log.c:921
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:1061
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:1198
#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:767
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:1116
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
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 *fmt,...)
Drain any outstanding messages from the fr_strerror buffers.
Definition log.c:742
int fr_log_init_fp(fr_log_t *log, FILE *fp)
Initialise a file logging destination to a FILE*.
Definition log.c:1095
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, char const *fmt, va_list ap)
Drain any outstanding messages from the fr_strerror buffers.
Definition log.c:647
void fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, va_list ap)
Send a server log message to its destination.
Definition log.c:380
static _Thread_local TALLOC_CTX * fr_log_pool
Definition log.c:43
bool log_dates_utc
Definition log.c:304
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
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
Definition log.c:616
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:1222
#define VTC_BOLD
Embolden following text.
Definition log.c:286
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:1472
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:2200
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:1900
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:1581
#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:772
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:1143
@ 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