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