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: 2bb0580bef20aaa8800325b677a92bcb779d811f $")
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#ifdef STATIC_ANALYZER
191 buffer[0] = '\0';
192#endif
193
194 fr_sbuff_init_out(&sbuff, buffer, sizeof(buffer));
195 fr_sbuff_marker(&m_start, &sbuff);
196 fr_sbuff_marker(&m_end, &sbuff);
197
198#ifndef NDEBUG
199 memset(buffer, 0x42, sizeof(buffer));
200#endif
201
202 for (;;) {
203 ssize_t slen;
204
205 slen = read(fd, fr_sbuff_current(&m_end), fr_sbuff_remaining(&m_end));
206 if ((slen < 0) && (errno == EINTR)) continue;
207
208 if (slen > 0) fr_sbuff_advance(&m_end, slen);
209
210 while (fr_sbuff_ahead(&m_end) > 0) {
211 fr_sbuff_adv_until(&sbuff, fr_sbuff_ahead(&m_end), &line_endings, '\0');
212
213 /*
214 * Incomplete line, try and read the rest.
215 */
216 if ((slen > 0) && (fr_sbuff_used(&m_start) > 0) &&
217 !fr_sbuff_is_terminal(&sbuff, &line_endings)) {
218 break;
219 }
220
221 fr_log(log_info->dst, log_info->type,
222 __FILE__, __LINE__,
223 "%s%s%pV",
224 log_info->prefix ? log_info->prefix : "",
225 log_info->prefix ? " - " : "",
227
228 fr_sbuff_advance(&sbuff, 1); /* Skip the whitespace */
229 fr_sbuff_set(&m_start, &sbuff);
230 }
231
232 /*
233 * Error or done
234 */
235 if (slen <= 0) break;
236
237 /*
238 * Clear out the existing data
239 */
240 fr_sbuff_shift(&sbuff, fr_sbuff_used(&m_start), false);
241 }
242}
243
244/** Maps log categories to message prefixes
245 */
247 { L("Debug : "), L_DBG },
248 { L("Info : "), L_INFO },
249 { L("Warn : "), L_WARN },
250 { L("Error : "), L_ERR },
251 { L("Auth : "), L_AUTH },
252 { L("INFO : "), L_DBG_INFO },
253 { L("WARN : "), L_DBG_WARN },
254 { L("ERROR : "), L_DBG_ERR },
255 { L("WARN : "), L_DBG_WARN_REQ },
256 { L("ERROR : "), L_DBG_ERR_REQ }
257};
259
260/** @name VT100 escape sequences
261 *
262 * These sequences may be written to VT100 terminals to change the
263 * colour and style of the text.
264 *
265 @code{.c}
266 fprintf(stdout, VTC_RED "This text will be coloured red" VTC_RESET);
267 @endcode
268 * @{
269 */
270#define VTC_RED "\x1b[31m" //!< Colour following text red.
271#define VTC_YELLOW "\x1b[33m" //!< Colour following text yellow.
272#define VTC_BOLD "\x1b[1m" //!< Embolden following text.
273#define VTC_RESET "\x1b[0m" //!< Reset terminal text to default style/colour.
274/** @} */
275
276/** Maps log categories to VT100 style/colour escape sequences
277 */
288
289
290bool log_dates_utc = false;
291
293 .colourise = false, //!< Will be set later. Should be off before we do terminal detection.
294 .fd = STDOUT_FILENO,
295 .dst = L_DST_STDOUT,
296 .file = NULL,
297 .timestamp = L_TIMESTAMP_AUTO
298};
299
300/** Cleanup the memory pool used by vlog_request
301 *
302 */
303static int _fr_log_pool_free(void *arg)
304{
305 if (talloc_free(arg) < 0) return -1;
306 fr_log_pool = NULL;
307 return 0;
308}
309
310/** talloc ctx to use when composing log messages
311 *
312 * Functions must ensure that they allocate a new ctx from the one returned
313 * here, and that this ctx is freed before the function returns.
314 *
315 * @return talloc pool to use for scratch space.
316 */
317TALLOC_CTX *fr_log_pool_init(void)
318{
319 TALLOC_CTX *pool;
320
321 pool = fr_log_pool;
322 if (unlikely(!pool)) {
323 if (fr_atexit_is_exiting()) return NULL; /* No new pools if we're exiting */
324
325 pool = talloc_pool(NULL, 16384);
326 if (!pool) {
327 fr_perror("Failed allocating memory for vlog_request_pool");
328 return NULL;
329 }
331 }
332
333 return pool;
334}
335
336/** Send a server log message to its destination
337 *
338 * @param[in] log destination.
339 * @param[in] type of log message.
340 * @param[in] file src file the log message was generated in.
341 * @param[in] line number the log message was generated on.
342 * @param[in] fmt with printf style substitution tokens.
343 * @param[in] ap Substitution arguments.
344 */
345void fr_vlog(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, va_list ap)
346{
347 int colourise = log->colourise;
348 char *buffer;
349 TALLOC_CTX *pool, *thread_log_pool;
350 char const *fmt_colour = "";
351 char const *fmt_location = "";
352 char fmt_time[50];
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 * We always print "WARN" and "ERROR" prefixes.
432 */
433 switch (type) {
434 case L_DBG_WARN:
435 case L_DBG_ERR:
436 fmt_type = fr_table_str_by_value(fr_log_levels, type, NULL);
437 break;
438
439 default:
440 /*
441 * Otherwise, print the other info levels only if we're asked to print the level,
442 * and we're not colourizing the output. If we're colourizing the output, then
443 * the colors indicate the debug level (info, warning, error), and we don't need
444 * any prefix.
445 */
446 if (log->print_level && !log->colourise) fmt_type = fr_table_str_by_value(fr_log_levels, type, ": ");
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" /* message type */
545 "%s" /* message */
546 "%s" /* colourise reset */
547 "\n",
548 colourise ? fmt_colour : "",
549 fmt_location,
550 fmt_time,
551 fmt_time[0] ? ": " : "",
552 fmt_type,
553 fmt_msg,
554 colourise ? VTC_RESET : "");
555
556 len = talloc_array_length(buffer) - 1;
557 wrote = write(log->fd, buffer, len);
558 if (wrote < len) return;
559 }
560 break;
561
562 default:
563 case L_DST_NULL: /* should have been caught above */
564 break;
565 }
566
567 talloc_free(pool); /* clears all temporary allocations */
568
569 return;
570}
571
572/** Send a server log message to its destination
573 *
574 * @param log destination.
575 * @param type of log message.
576 * @param file where the log message originated
577 * @param line where the log message originated
578 * @param fmt with printf style substitution tokens.
579 * @param ... Substitution arguments.
580 */
581void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt, ...)
582{
583 va_list ap;
584
585 /*
586 * Non-debug message, or debugging is enabled. Log it.
587 */
588 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
589
590 va_start(ap, fmt);
591 fr_vlog(log, type, file, line, fmt, ap);
592 va_end(ap);
593}
594
595/** Drain any outstanding messages from the fr_strerror buffers
596 *
597 * This function drains any messages from fr_strerror buffer prefixing
598 * the first message with fmt + args.
599 *
600 * If a prefix is specified in rules, this is prepended to all lines
601 * logged. The prefix is useful for adding context, i.e. configuration
602 * file and line number information.
603 *
604 * @param[in] log destination.
605 * @param[in] type of log message.
606 * @param[in] file src file the log message was generated in.
607 * @param[in] line number the log message was generated on.
608 * @param[in] f_rules for printing multiline errors.
609 * @param[in] fmt with printf style substitution tokens.
610 * @param[in] ap Substitution arguments.
611 */
612void fr_vlog_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
613 fr_log_perror_format_t const *f_rules, char const *fmt, va_list ap)
614{
615 char const *error;
616 static fr_log_perror_format_t default_f_rules;
617
618 TALLOC_CTX *thread_log_pool;
619 fr_sbuff_marker_t prefix_m;
620
621 fr_sbuff_t sbuff;
623
624 /*
625 * Non-debug message, or debugging is enabled. Log it.
626 */
627 if (!(((type & L_DBG) == 0) || (fr_debug_lvl > 0))) return;
628
629 if (!f_rules) f_rules = &default_f_rules;
630
631 thread_log_pool = fr_log_pool_init();
632
633 /*
634 * Setup the aggregation buffer
635 */
636 fr_sbuff_init_talloc(thread_log_pool, &sbuff, &tctx, 1024, 16384);
637
638 /*
639 * Add the prefix for the first line
640 */
641 if (f_rules->first_prefix) (void) fr_sbuff_in_strcpy(&sbuff, f_rules->first_prefix);
642
643 /*
644 * Add the (optional) message, and/or (optional) error
645 * with the error_sep.
646 * i.e. <msg>: <error>
647 */
648 error = fr_strerror_pop();
649
650 if (!error && !fmt) return; /* NOOP */
651
652 if (fmt) {
653 va_list aq;
654
655 va_copy(aq, ap);
656 fr_sbuff_in_vsprintf(&sbuff, fmt, aq);
657 va_end(aq);
658 }
659
660 if (error && (fmt || f_rules->first_prefix)) {
661 if (fmt) (void) fr_sbuff_in_strcpy(&sbuff, ": ");
662 (void) fr_sbuff_in_strcpy(&sbuff, error);
663 }
664
665 error = fr_sbuff_start(&sbuff); /* may not be talloced with const */
666
667 /*
668 * Log the first line
669 */
670 fr_log(log, type, file, line, "%s", error);
671
672 fr_sbuff_set_to_start(&sbuff);
673 if (f_rules->subsq_prefix) {
674 (void) fr_sbuff_in_strcpy(&sbuff, f_rules->subsq_prefix);
675 fr_sbuff_marker(&prefix_m, &sbuff);
676 }
677
678 /*
679 * Print out additional error lines
680 */
681 while ((error = fr_strerror_pop())) {
682 if (f_rules->subsq_prefix) {
683 fr_sbuff_set(&sbuff, &prefix_m);
684 (void) fr_sbuff_in_strcpy(&sbuff, error); /* may not be talloced with const */
685 error = fr_sbuff_start(&sbuff);
686 }
687
688 fr_log(log, type, file, line, "%s", error);
689 }
690
691 talloc_free(sbuff.buff);
692}
693
694/** Drain any outstanding messages from the fr_strerror buffers
695 *
696 * This function drains any messages from fr_strerror buffer adding a prefix (fmt)
697 * to the first message.
698 *
699 * @param[in] log destination.
700 * @param[in] type of log message.
701 * @param[in] file src file the log message was generated in.
702 * @param[in] line number the log message was generated on.
703 * @param[in] rules for printing multiline errors.
704 * @param[in] fmt with printf style substitution tokens.
705 * @param[in] ... Substitution arguments.
706 */
707void fr_log_perror(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
708 fr_log_perror_format_t const *rules, char const *fmt, ...)
709{
710 va_list ap;
711
712 va_start(ap, fmt);
713 fr_vlog_perror(log, type, file, line, rules, fmt, ap);
714 va_end(ap);
715}
716
717DIAG_OFF(format-nonliteral)
718/** Print out an error marker
719 *
720 * @param[in] log destination.
721 * @param[in] type of log message.
722 * @param[in] file src file the log message was generated in.
723 * @param[in] line number the log message was generated on.
724 * @param[in] str Subject string we're printing a marker for.
725 * @param[in] str_len Subject string length. Use SIZE_MAX for the
726 * length of the string.
727 * @param[in] marker_idx Where to place the marker. May be negative.
728 * @param[in] marker text to print at marker_idx.
729 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
730 * @param[in] ... Arguments for line_prefix_fmt.
731 */
732void fr_log_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
733 char const *str, size_t str_len,
734 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
735{
736 char const *ellipses = "";
737 va_list ap;
738 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
739 char *line_prefix = NULL;
740 static char const marker_spaces[] = " "; /* 60 */
741
742 if (str_len == SIZE_MAX) str_len = strlen(str);
743
744 if (marker_idx < 0) marker_idx = marker_idx * -1;
745
746 if ((size_t)marker_idx >= sizeof(marker_spaces)) {
747 size_t offset = (marker_idx - (sizeof(marker_spaces) - 1)) + (sizeof(marker_spaces) * 0.75);
748 marker_idx -= offset;
749
750 if (offset > str_len) offset = str_len;
751 str += offset;
752 str_len -= offset;
753
754 ellipses = "... ";
755 }
756
757 if (line_prefix_fmt) {
758 va_start(ap, line_prefix_fmt);
759 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
760 va_end(ap);
761 }
762
763 fr_log(log, type, file, line, "%s%s%.*s",
764 line_prefix ? line_prefix : "", ellipses, (int)str_len, str);
765 fr_log(log, type, file, line, "%s%s%.*s^ %s",
766 line_prefix ? line_prefix : "", ellipses, (int)marker_idx, marker_spaces, marker);
767
768 if (line_prefix_fmt) talloc_free(line_prefix);
769}
770
771/** Print out hex block
772 *
773 * @param[in] log destination.
774 * @param[in] type of log message.
775 * @param[in] file src file the log message was generated in.
776 * @param[in] line number the log message was generated on.
777 * @param[in] data to print.
778 * @param[in] data_len length of data.
779 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
780 * @param[in] ... Arguments for line_prefix_fmt.
781 */
782void fr_log_hex(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
783 uint8_t const *data, size_t data_len, char const *line_prefix_fmt, ...)
784{
785 size_t i, j, len;
786 char buffer[(0x10 * 3) + 1];
787 char *p, *end = buffer + sizeof(buffer);
788 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
789 char *line_prefix = NULL;
790
791 if (line_prefix_fmt) {
792 va_list ap;
793
794 va_start(ap, line_prefix_fmt);
795 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
796 va_end(ap);
797 }
798
799 for (i = 0; i < data_len; i += 0x10) {
800 len = 0x10;
801 if ((i + len) > data_len) len = data_len - i;
802
803 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
804
805 if (line_prefix_fmt) {
806 fr_log(log, type, file, line, "%s%04x: %s",
807 line_prefix, (unsigned int) i, buffer);
808 } else {
809 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
810 }
811 }
812
813 if (line_prefix_fmt) talloc_free(line_prefix);
814}
815
816/** Print out hex block
817 *
818 * @param[in] log destination.
819 * @param[in] type of log message.
820 * @param[in] file src file the log message was generated in.
821 * @param[in] line number the log message was generated on.
822 * @param[in] data to print.
823 * @param[in] data_len length of data.
824 * @param[in] marker_idx Where to place the marker. May be negative.
825 * @param[in] marker text to print at marker_idx.
826 * @param[in] line_prefix_fmt Prefix to add to the marker messages.
827 * @param[in] ... Arguments for line_prefix_fmt.
828 */
829void fr_log_hex_marker(fr_log_t const *log, fr_log_type_t type, char const *file, int line,
830 uint8_t const *data, size_t data_len,
831 ssize_t marker_idx, char const *marker, char const *line_prefix_fmt, ...)
832{
833 size_t i, j, len;
834 char buffer[(0x10 * 3) + 1];
835 char *p, *end = buffer + sizeof(buffer);
836 TALLOC_CTX *thread_log_pool = fr_log_pool_init();
837
838 char *line_prefix = NULL;
839 static char spaces[3 * 0x10]; /* Bytes per line */
840
841 if (!*spaces) memset(spaces, ' ', sizeof(spaces) - 1); /* Leave a \0 */
842
843 if (marker_idx < 0) marker_idx = marker_idx * -1;
844 if (line_prefix_fmt) {
845 va_list ap;
846
847 va_start(ap, line_prefix_fmt);
848 line_prefix = fr_vasprintf(thread_log_pool, line_prefix_fmt, ap);
849 va_end(ap);
850 }
851
852 for (i = 0; i < data_len; i += 0x10) {
853 len = 0x10;
854 if ((i + len) > data_len) len = data_len - i;
855
856 for (p = buffer, j = 0; j < len; j++, p += 3) snprintf(p, end - p, "%02x ", data[i + j]);
857
858 if (line_prefix_fmt) {
859 fr_log(log, type, file, line, "%s%04x: %s",
860 line_prefix, (unsigned int) i, buffer);
861 } else {
862 fr_log(log, type, file, line, "%04x: %s", (unsigned int) i, buffer);
863 }
864
865 /*
866 * Marker is on this line
867 */
868 if (((size_t)marker_idx >= i) && ((size_t)marker_idx < (i + 0x10))) {
869 if (line_prefix_fmt) {
870 fr_log(log, type, file, line, "%s %.*s^ %s", line_prefix,
871 (int)((marker_idx - i) * 3), spaces, marker);
872 } else {
873 fr_log(log, type, file, line, " %.*s^ %s",
874 (int)((marker_idx - i) * 3), spaces, marker);
875 }
876 }
877 }
878
879 if (line_prefix_fmt) talloc_free(line_prefix);
880}
881DIAG_ON(format-nonliteral)
882/** On fault, reset STDOUT and STDERR to something useful
883 *
884 * @return 0
885 */
886static int _restore_std_legacy(UNUSED int sig)
887{
888 if ((stderr_fd > 0) && (stdout_fd > 0)) {
889 dup2(stderr_fd, STDOUT_FILENO);
890 dup2(stdout_fd, STDERR_FILENO);
891 return 0;
892 }
893
894 return 0;
895}
896
897/** Initialise file descriptors based on logging destination
898 *
899 * @param log Logger to manipulate.
900 * @param daemonize Whether the server is starting as a daemon.
901 * @return
902 * - 0 on success.
903 * - -1 on failure.
904 */
905int fr_log_init_legacy(fr_log_t *log, bool daemonize)
906{
907 int devnull_legacy;
908
909 fr_log_rate_limit = daemonize;
910
911 /*
912 * If we're running in foreground mode, save STDIN /
913 * STDERR as higher FDs, which won't get used by anyone
914 * else. When we fork/exec a program, its STD FDs will
915 * get set to pipes. We later set STDOUT / STDERR to
916 * /dev/null, so that any library trying to write to them
917 * doesn't screw anything up.
918 *
919 * Then, when something goes wrong, restore them so that
920 * any debugger called from the panic action has access
921 * to STDOUT / STDERR.
922 */
923 if (!daemonize) {
925
926 stdout_fd = dup(STDOUT_FILENO);
927 stderr_fd = dup(STDERR_FILENO);
928 }
929
930 devnull_legacy = open("/dev/null", O_RDWR);
931 if (devnull_legacy < 0) {
932 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
933 return -1;
934 }
935
936 /*
937 * STDOUT & STDERR go to /dev/null, unless we have "-x",
938 * then STDOUT & STDERR go to the "-l log" destination.
939 *
940 * The complexity here is because "-l log" can go to
941 * STDOUT or STDERR, too.
942 */
943 if (log->dst == L_DST_STDOUT) {
944 setlinebuf(stdout);
945 log->fd = STDOUT_FILENO;
946
947 /*
948 * If we're debugging, allow STDERR to go to
949 * STDOUT too, for executed programs.
950 *
951 * Allow stdout when running in foreground mode
952 * as it's useful for some profiling tools,
953 * like mutrace.
954 */
955 if (fr_debug_lvl || !daemonize) {
956 dup2(STDOUT_FILENO, STDERR_FILENO);
957 } else {
958 dup2(devnull_legacy, STDERR_FILENO);
959 }
960
961 } else if (log->dst == L_DST_STDERR) {
962 setlinebuf(stderr);
963 log->fd = STDERR_FILENO;
964
965 /*
966 * If we're debugging, allow STDOUT to go to
967 * STDERR too, for executed programs.
968 *
969 * Allow stdout when running in foreground mode
970 * as it's useful for some profiling tools,
971 * like mutrace.
972 */
973 if (fr_debug_lvl || !daemonize) {
974 dup2(STDERR_FILENO, STDOUT_FILENO);
975 } else {
976 dup2(devnull_legacy, STDOUT_FILENO);
977 }
978
979 } else if (log->dst == L_DST_SYSLOG) {
980 /*
981 * Discard STDOUT and STDERR no matter what the
982 * status of debugging. Syslog isn't a file
983 * descriptor, so we can't use it.
984 */
985 dup2(devnull_legacy, STDOUT_FILENO);
986 dup2(devnull_legacy, STDERR_FILENO);
987 log->print_level = false;
988
989 } else if (fr_debug_lvl) {
990 /*
991 * If we're debugging, allow STDOUT and STDERR to
992 * go to the log file.
993 */
994 dup2(log->fd, STDOUT_FILENO);
995 dup2(log->fd, STDERR_FILENO);
996
997 } else {
998 /*
999 * Not debugging, and the log isn't STDOUT or
1000 * STDERR. Ensure that we move both of them to
1001 * /dev/null, so that the calling terminal can
1002 * exit, and the output from executed programs
1003 * doesn't pollute STDOUT / STDERR.
1004 */
1005 dup2(devnull_legacy, STDOUT_FILENO);
1006 dup2(devnull_legacy, STDERR_FILENO);
1007 }
1008
1009 close(devnull_legacy);
1010
1011 fr_fault_set_log_fd(log->fd);
1012
1013 return 0;
1014}
1015
1016DIAG_ON(format-nonliteral)
1017
1018/** Initialise log dst for stdout, stderr or /dev/null
1019 *
1020 * @param[out] log Destination to initialise.
1021 * @param[in] dst_type The specific type of log destination to initialise.
1022 * @return
1023 * - 0 on success.
1024 * - -1 on failure.
1025 */
1027{
1028 memset(log, 0, sizeof(*log));
1029
1030 log->dst = dst_type;
1031 switch (log->dst) {
1032 case L_DST_STDOUT:
1033 log->handle = stdout;
1034 break;
1035
1036 case L_DST_STDERR:
1037 log->handle = stderr;
1038 break;
1039
1040 case L_DST_NULL:
1041 log->handle = devnull;
1042 break;
1043
1044 default:
1045 fr_strerror_const("Invalid dst type for FD log destination");
1046 return -1;
1047 }
1048
1049 return 0;
1050}
1051
1052/** Initialise a file logging destination to a FILE*
1053 *
1054 * @param[out] log Destination to initialise.
1055 * @param[in] fp pre-existing handle
1056 * @return
1057 * - 0 on success.
1058 * - -1 on failure.
1059 */
1060int fr_log_init_fp(fr_log_t *log, FILE *fp)
1061{
1062 memset(log, 0, sizeof(*log));
1063
1064 log->dst = L_DST_FILES;
1065 log->handle = fp;
1066
1067 setlinebuf(log->handle);
1068 log->fd = fileno(log->handle);
1069
1070 return 0;
1071}
1072
1073/** Initialise a file logging destination
1074 *
1075 * @param[out] log Destination to initialise.
1076 * @param[in] file to open handle for.
1077 * @return
1078 * - 0 on success.
1079 * - -1 on failure.
1080 */
1081int fr_log_init_file(fr_log_t *log, char const *file)
1082{
1083 FILE *fp;
1084
1085 if (unlikely((fp = fopen(file, "a")) == NULL)) {
1086 fr_strerror_printf("Failed opening log file \"%s\": %s", file, fr_syserror(errno));
1087 return -1;
1088 }
1089
1090 if (fr_log_init_fp(log, fp) < 0) return -1;
1091
1092 /*
1093 * The init over-rode any filename, so we reset it here.
1094 */
1095 log->file = file;
1096 return 0;
1097}
1098
1099/** Write complete lines to syslog
1100 *
1101 */
1102static ssize_t _syslog_write(UNUSED void *cookie, const char *buf, size_t size)
1103{
1104 static int syslog_priority_table[] = {
1105 [L_DBG] = LOG_DEBUG,
1106
1107 [L_INFO] = LOG_INFO,
1108 [L_DBG_INFO] = LOG_INFO,
1109
1110 [L_ERR] = LOG_ERR,
1111 [L_DBG_ERR] = LOG_ERR,
1112 [L_DBG_ERR_REQ] = LOG_ERR,
1113
1114 [L_WARN] = LOG_WARNING,
1115 [L_DBG_WARN] = LOG_WARNING,
1116 [L_DBG_WARN_REQ] = LOG_WARNING,
1117
1118 [L_AUTH] = LOG_AUTH | LOG_INFO
1119 };
1120
1121 syslog(syslog_priority_table[log_msg_type], "%.*s", (int)size, buf);
1122
1123 return size;
1124}
1125
1126/** Initialise a syslog logging destination
1127 *
1128 * @param[out] log Destination to initialise.
1129 * @return
1130 * - 0 on success.
1131 * - -1 on failure.
1132 */
1134{
1135 memset(log, 0, sizeof(*log));
1136
1137 log->dst = L_DST_SYSLOG;
1138 if (unlikely((log->handle = fopencookie(log, "w",
1140 .write = _syslog_write,
1141 })) == NULL)) {
1142 fr_strerror_printf("Failed opening syslog transpor: %s", fr_syserror(errno));
1143 return -1;
1144 }
1145
1146 setlinebuf(log->handle);
1147
1148 return 0;
1149}
1150
1151/** Initialise a function based logging destination
1152 *
1153 * @note Cookie functions receive the fr_log_t which contains the uctx, not the uctx directly.
1154 *
1155 * @param[out] log Destination to initialise.
1156 * @param[in] write Called when a complete log line is ready for writing.
1157 * @param[in] close May be NULL. Called when the logging destination has been closed.
1158 * @param[in] uctx for the write and close functions.
1159 * @return
1160 * - 0 on success.
1161 * - -1 on failure.
1162 */
1164{
1165 memset(log, 0, sizeof(*log));
1166
1167 log->dst = L_DST_FUNC;
1168
1169 if (unlikely((log->handle = fopencookie(log, "w",
1171 .write = write,
1172 .close = close
1173 })) == NULL)) {
1174 fr_strerror_printf("Failed opening func transport: %s", fr_syserror(errno));
1175 return -1;
1176 }
1177
1178 setlinebuf(log->handle);
1179 log->uctx = uctx;
1180
1181 return 0;
1182}
1183
1184/** Universal close function for all logging destinations
1185 *
1186 */
1188{
1189 switch (log->dst) {
1190 case L_DST_STDOUT:
1191 case L_DST_STDERR:
1192 case L_DST_NULL:
1193 return 0;
1194
1195 /*
1196 * Other log dsts
1197 */
1198 case L_DST_FILES:
1199 case L_DST_FUNC:
1200 case L_DST_SYSLOG:
1201 if (log->handle && (fclose(log->handle) < 0)) {
1202 fr_strerror_printf("Failed closing file handle: %s", fr_syserror(errno));
1203 return -1;
1204 }
1205 return 0;
1206
1207 case L_DST_NUM_DEST:
1208 break;
1209 }
1210
1211 fr_strerror_printf("Failed closing invalid log dst %u", log->dst);
1212 return -1;
1213}
1214
1215/** Manipulate stderr and stdout so that was capture all data send to it from libraries
1216 *
1217 * @param[in] el The event list we use to process logging data.
1218 * @param[in] daemonize Whether the server is starting as a daemon.
1219 * @return
1220 * - 0 on success.
1221 * - -1 on failure.
1222 */
1224{
1225 log_el = el;
1226
1227 fr_log_rate_limit = daemonize;
1228
1229 /*
1230 * dup the current stdout/stderr FDs and close
1231 * the FDs in the STDOUT/STDERR slots to get
1232 * the reference count back to one.
1233 */
1234 stdout_fd = dup(STDOUT_FILENO);
1235 if (unlikely(stdout_fd < 0)) {
1236 fr_strerror_printf("Failed cloning stdout FD: %s", fr_syserror(errno));
1237 return -1;
1238 }
1239
1240 /*
1241 * Create two unidirection pipes, duping one end
1242 * to the stdout/stderr slots and inserting the
1243 * other into our event loop
1244 */
1245 if (unlikely(pipe(stdout_pipe) < 0)) {
1246 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1247 error_0:
1248 log_el = NULL;
1250 return -1;
1251 }
1252
1253 /*
1254 * This closes the other ref to the stdout FD.
1255 */
1256 if (unlikely(dup2(stdout_pipe[0], STDOUT_FILENO) < 0)) {
1257 fr_strerror_printf("Failed copying pipe end over stdout: %s", fr_syserror(errno));
1258 error_1:
1259 close(stdout_pipe[0]);
1260 stdout_pipe[0] = -1;
1261 close(stdout_pipe[1]);
1262 stdout_pipe[1] = -1;
1263 goto error_0;
1264 }
1265
1267 stdout_ctx.prefix = "(stdout)";
1270
1271 /*
1272 * Now do stderr...
1273 */
1274 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stdout_pipe[1], fr_log_fd_event, NULL, NULL, &stdout_ctx) < 0)) {
1275 fr_strerror_const_push("Failed adding stdout handler to event loop");
1276 error_2:
1277 dup2(STDOUT_FILENO, stdout_fd); /* Copy back the stdout FD */
1278 goto error_1;
1279 }
1280
1281 stderr_fd = dup(STDERR_FILENO);
1282 if (unlikely(stderr_fd < 0)) {
1283 fr_strerror_printf("Failed cloning stderr FD: %s", fr_syserror(errno));
1284
1285 error_3:
1287 goto error_2;
1288 }
1289
1290 if (unlikely(pipe(stderr_pipe) < 0)) {
1291 fr_strerror_printf("Failed creating logging pipes: %s", fr_syserror(errno));
1292 error_4:
1294 goto error_3;
1295 }
1296
1297 if (unlikely(dup2(stderr_pipe[0], STDOUT_FILENO) < 0)) {
1298 fr_strerror_printf("Failed copying pipe end over stderr: %s", fr_syserror(errno));
1299 error_5:
1300 close(stderr_pipe[0]);
1301 stderr_pipe[0] = -1;
1302 close(stderr_pipe[1]);
1303 stderr_pipe[1] = -1;
1304 goto error_4;
1305 }
1306
1308 stdout_ctx.prefix = "(stderr)";
1310 stdout_ctx.lvl = L_DBG_LVL_OFF; /* Log at all debug levels */
1311
1312 if (unlikely(fr_event_fd_insert(NULL, NULL, el, stderr_pipe[1], fr_log_fd_event, NULL, NULL, &stderr_ctx) < 0)) {
1313 fr_strerror_const_push("Failed adding stdout handler to event loop");
1314 error_6:
1315 dup2(STDERR_FILENO, stderr_fd); /* Copy back the stderr FD */
1316 goto error_5;
1317 }
1318
1319 fr_fault_set_log_fd(STDERR_FILENO);
1320 fr_fault_set_cb(_restore_std_legacy); /* Restore the original file descriptors if we experience a fault */
1321
1322 /*
1323 * Setup our standard file *s
1324 */
1325 setlinebuf(stdout);
1326 setlinebuf(stderr);
1327
1328 devnull = fopen("/dev/null", "w");
1329 if (unlikely(!devnull)) {
1330 fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
1331 goto error_6;
1332 }
1333
1335
1336 return 0;
1337}
1338
1339/** Restores the original stdout and stderr FDs, closes the pipes and removes them from the event loop
1340 *
1341 */
1343{
1344 if (!log_el) return;
1345
1347 close(stdout_pipe[1]);
1348 stdout_pipe[1] = -1;
1350 close(stderr_pipe[1]);
1351 stderr_pipe[1] = -1;
1352
1353 _restore_std_legacy(0); /* Will close stdout_pipe[0] and stderr_pipe[0] with dup2 */
1354
1355 stdout_pipe[0] = -1;
1356 stderr_pipe[0] = -1;
1357
1358 fclose(devnull);
1359}
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:246
int fr_log_init_legacy(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
Definition log.c:905
#define VTC_RED
Colour following text red.
Definition log.c:270
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:1102
TALLOC_CTX * fr_log_pool_init(void)
talloc ctx to use when composing log messages
Definition log.c:317
int fr_log_init_syslog(fr_log_t *log)
Initialise a syslog logging destination.
Definition log.c:1133
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:1223
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:782
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:829
#define VTC_YELLOW
Colour following text yellow.
Definition log.c:271
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:1342
static int _restore_std_legacy(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Definition log.c:886
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:1026
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:1163
#define VTC_RESET
Reset terminal text to default style/colour.
Definition log.c:273
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:278
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:732
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:292
int fr_log_init_file(fr_log_t *log, char const *file)
Initialise a file logging destination.
Definition log.c:1081
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:707
int fr_log_init_fp(fr_log_t *log, FILE *fp)
Initialise a file logging destination to a FILE*.
Definition log.c:1060
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:612
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:345
static _Thread_local TALLOC_CTX * fr_log_pool
Definition log.c:42
bool log_dates_utc
Definition log.c:290
size_t fr_log_levels_len
Definition log.c:258
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:303
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:581
static int stderr_fd
The original unmolested stderr file descriptor.
Definition log.c:47
static size_t colours_len
Definition log.c:287
int fr_log_close(fr_log_t *log)
Universal close function for all logging destinations.
Definition log.c:1187
#define VTC_BOLD
Embolden following text.
Definition log.c:272
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:1288
#define fr_box_strvalue_len(_val, _len)
Definition value.h:305
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1020