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