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