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