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