1 /* Copyright (c) 2001, Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2013, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Functions to send messages to log files or the console.
18 #ifdef HAVE_SYS_TIME_H
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
37 #include "container.h"
40 /** The string we stick at the end of a log message when it is too long,
42 #define TRUNCATED_STR "[...truncated]"
43 #define TRUNCATED_STR_LEN 14
46 /** Information for a single logfile; only used in log.c */
47 typedef struct logfile_t
{
48 struct logfile_t
*next
; /**< Next logfile_t in the linked list. */
49 char *filename
; /**< Filename to open. */
50 int fd
; /**< fd to receive log messages, or -1 for none. */
51 int seems_dead
; /**< Boolean: true if the stream seems to be kaput. */
52 int needs_close
; /**< Boolean: true if the stream gets closed on shutdown. */
53 int is_temporary
; /**< Boolean: close after initializing logging subsystem.*/
54 int is_syslog
; /**< Boolean: send messages to syslog. */
55 log_callback callback
; /**< If not NULL, send messages to this function. */
56 log_severity_list_t
*severities
; /**< Which severity of messages should we
57 * log for each log domain? */
60 static void log_free(logfile_t
*victim
);
62 /** Helper: map a log severity to descriptive string. */
63 static INLINE
const char *
64 sev_to_string(int severity
)
67 case LOG_DEBUG
: return "debug";
68 case LOG_INFO
: return "info";
69 case LOG_NOTICE
: return "notice";
70 case LOG_WARN
: return "warn";
71 case LOG_ERR
: return "err";
72 default: /* Call assert, not tor_assert, since tor_assert
73 * calls log on failure. */
74 assert(0); return "UNKNOWN";
78 /** Helper: decide whether to include the function name in the log message. */
80 should_log_function_name(log_domain_mask_t domain
, int severity
)
85 /* All debugging messages occur in interesting places. */
90 /* We care about places where bugs occur. */
91 return (domain
== LD_BUG
);
93 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
98 /** A mutex to guard changes to logfiles and logging. */
99 static tor_mutex_t log_mutex
;
100 /** True iff we have initialized log_mutex */
101 static int log_mutex_initialized
= 0;
103 /** Linked list of logfile_t. */
104 static logfile_t
*logfiles
= NULL
;
105 /** Boolean: do we report logging domains? */
106 static int log_domains_are_logged
= 0;
109 /** The number of open syslog log handlers that we have. When this reaches 0,
110 * we can close our connection to the syslog facility. */
111 static int syslog_count
= 0;
114 /** Represents a log message that we are going to send to callback-driven
115 * loggers once we can do so in a non-reentrant way. */
116 typedef struct pending_cb_message_t
{
117 int severity
; /**< The severity of the message */
118 log_domain_mask_t domain
; /**< The domain of the message */
119 char *msg
; /**< The content of the message */
120 } pending_cb_message_t
;
122 /** Log messages waiting to be replayed onto callback-based logs */
123 static smartlist_t
*pending_cb_messages
= NULL
;
125 /** Lock the log_mutex to prevent others from changing the logfile_t list */
126 #define LOCK_LOGS() STMT_BEGIN \
127 tor_mutex_acquire(&log_mutex); \
129 /** Unlock the log_mutex */
130 #define UNLOCK_LOGS() STMT_BEGIN tor_mutex_release(&log_mutex); STMT_END
132 /** What's the lowest log level anybody cares about? Checking this lets us
133 * bail out early from log_debug if we aren't debugging. */
134 int log_global_min_severity_
= LOG_NOTICE
;
136 static void delete_log(logfile_t
*victim
);
137 static void close_log(logfile_t
*victim
);
139 static char *domain_to_string(log_domain_mask_t domain
,
140 char *buf
, size_t buflen
);
141 static INLINE
char *format_msg(char *buf
, size_t buf_len
,
142 log_domain_mask_t domain
, int severity
, const char *funcname
,
144 const char *format
, va_list ap
, size_t *msg_len_out
)
146 static void logv(int severity
, log_domain_mask_t domain
, const char *funcname
,
147 const char *suffix
, const char *format
, va_list ap
)
150 /** Name of the application: used to generate the message we write at the
151 * start of each new log. */
152 static char *appname
= NULL
;
154 /** Set the "application name" for the logs to <b>name</b>: we'll use this
155 * name in the message we write when starting up, and at the start of each new
158 * Tor uses this string to write the version number to the log file. */
160 log_set_application_name(const char *name
)
163 appname
= name
? tor_strdup(name
) : NULL
;
166 /** Log time granularity in milliseconds. */
167 static int log_time_granularity
= 1;
169 /** Define log time granularity for all logs to be <b>granularity_msec</b>
172 set_log_time_granularity(int granularity_msec
)
174 log_time_granularity
= granularity_msec
;
177 /** Helper: Write the standard prefix for log lines to a
178 * <b>buf_len</b> character buffer in <b>buf</b>.
181 log_prefix_(char *buf
, size_t buf_len
, int severity
)
189 tor_gettimeofday(&now
);
190 t
= (time_t)now
.tv_sec
;
191 ms
= (int)now
.tv_usec
/ 1000;
192 if (log_time_granularity
>= 1000) {
193 t
-= t
% (log_time_granularity
/ 1000);
196 ms
-= ((int)now
.tv_usec
/ 1000) % log_time_granularity
;
199 n
= strftime(buf
, buf_len
, "%b %d %H:%M:%S", tor_localtime_r(&t
, &tm
));
200 r
= tor_snprintf(buf
+n
, buf_len
-n
, ".%.3i [%s] ", ms
,
201 sev_to_string(severity
));
209 /** If lf refers to an actual file that we have just opened, and the file
210 * contains no data, log an "opening new logfile" message at the top.
212 * Return -1 if the log is broken and needs to be deleted, else return 0.
215 log_tor_version(logfile_t
*lf
, int reset
)
221 if (!lf
->needs_close
)
222 /* If it doesn't get closed, it isn't really a file. */
224 if (lf
->is_temporary
)
225 /* If it's temporary, it isn't really a file. */
228 is_new
= lf
->fd
>= 0 && tor_fd_getpos(lf
->fd
) == 0;
230 if (reset
&& !is_new
)
231 /* We are resetting, but we aren't at the start of the file; no
232 * need to log again. */
234 n
= log_prefix_(buf
, sizeof(buf
), LOG_NOTICE
);
236 tor_snprintf(buf
+n
, sizeof(buf
)-n
,
237 "%s opening %slog file.\n", appname
, is_new
?"new ":"");
239 tor_snprintf(buf
+n
, sizeof(buf
)-n
,
240 "Tor %s opening %slog file.\n", VERSION
, is_new
?"new ":"");
242 if (write_all(lf
->fd
, buf
, strlen(buf
), 0) < 0) /* error */
243 return -1; /* failed */
247 /** Helper: Format a log message into a fixed-sized buffer. (This is
248 * factored out of <b>logv</b> so that we never format a message more
249 * than once.) Return a pointer to the first character of the message
250 * portion of the formatted string.
253 format_msg(char *buf
, size_t buf_len
,
254 log_domain_mask_t domain
, int severity
, const char *funcname
,
256 const char *format
, va_list ap
, size_t *msg_len_out
)
263 assert(buf_len
>= 16); /* prevent integer underflow and general stupidity */
264 buf_len
-= 2; /* subtract 2 characters so we have room for \n\0 */
265 buf_end
= buf
+buf_len
; /* point *after* the last char we can write to */
267 n
= log_prefix_(buf
, buf_len
, severity
);
268 end_of_prefix
= buf
+n
;
270 if (log_domains_are_logged
) {
272 if (cp
== buf_end
) goto format_msg_no_room_for_domains
;
274 if (cp
== buf_end
) goto format_msg_no_room_for_domains
;
275 cp
= domain_to_string(domain
, cp
, (buf
+buf_len
-cp
));
276 if (cp
== buf_end
) goto format_msg_no_room_for_domains
;
278 if (cp
== buf_end
) goto format_msg_no_room_for_domains
;
280 if (cp
== buf_end
) goto format_msg_no_room_for_domains
;
283 format_msg_no_room_for_domains
:
284 /* This will leave end_of_prefix and n unchanged, and thus cause
285 * whatever log domain string we had written to be clobbered. */
289 if (funcname
&& should_log_function_name(domain
, severity
)) {
290 r
= tor_snprintf(buf
+n
, buf_len
-n
, "%s(): ", funcname
);
297 if (domain
== LD_BUG
&& buf_len
-n
> 6) {
298 memcpy(buf
+n
, "Bug: ", 6);
302 r
= tor_vsnprintf(buf
+n
,buf_len
-n
,format
,ap
);
304 /* The message was too long; overwrite the end of the buffer with
305 * "[...truncated]" */
306 if (buf_len
>= TRUNCATED_STR_LEN
) {
307 size_t offset
= buf_len
-TRUNCATED_STR_LEN
;
308 /* We have an extra 2 characters after buf_len to hold the \n\0,
309 * so it's safe to add 1 to the size here. */
310 strlcpy(buf
+offset
, TRUNCATED_STR
, buf_len
-offset
+1);
312 /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
313 * Since we already subtracted 2 from buf_len, this is safe.*/
318 size_t suffix_len
= strlen(suffix
);
319 if (buf_len
-n
>= suffix_len
) {
320 memcpy(buf
+n
, suffix
, suffix_len
);
328 return end_of_prefix
;
331 /** Helper: sends a message to the appropriate logfiles, at loglevel
332 * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
333 * message. The actual message is derived as from tor_snprintf(format,ap).
336 logv(int severity
, log_domain_mask_t domain
, const char *funcname
,
337 const char *suffix
, const char *format
, va_list ap
)
343 char *end_of_prefix
=NULL
;
344 int callbacks_deferred
= 0;
346 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
348 /* check that severity is sane. Overrunning the masks array leads to
349 * interesting and hard to diagnose effects */
350 assert(severity
>= LOG_ERR
&& severity
<= LOG_DEBUG
);
353 if ((! (domain
& LD_NOCB
)) && smartlist_len(pending_cb_messages
))
354 flush_pending_log_callbacks();
358 if (! (lf
->severities
->masks
[SEVERITY_MASK_IDX(severity
)] & domain
)) {
362 if (! (lf
->fd
>= 0 || lf
->is_syslog
|| lf
->callback
)) {
366 if (lf
->seems_dead
) {
373 format_msg(buf
, sizeof(buf
), domain
, severity
, funcname
, suffix
,
374 format
, ap
, &msg_len
);
380 char *m
= end_of_prefix
;
382 /* Some syslog implementations have limits on the length of what you can
383 * pass them, and some very old ones do not detect overflow so well.
384 * Regrettably, they call their maximum line length MAXLINE. */
386 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
388 if (msg_len
>= MAXLINE
)
389 m
= tor_strndup(end_of_prefix
, MAXLINE
-1);
391 syslog(severity
, "%s", m
);
393 if (m
!= end_of_prefix
) {
400 } else if (lf
->callback
) {
401 if (domain
& LD_NOCB
) {
402 if (!callbacks_deferred
&& pending_cb_messages
) {
403 pending_cb_message_t
*msg
= tor_malloc(sizeof(pending_cb_message_t
));
404 msg
->severity
= severity
;
405 msg
->domain
= domain
;
406 msg
->msg
= tor_strdup(end_of_prefix
);
407 smartlist_add(pending_cb_messages
, msg
);
409 callbacks_deferred
= 1;
412 lf
->callback(severity
, domain
, end_of_prefix
);
417 if (write_all(lf
->fd
, buf
, msg_len
, 0) < 0) { /* error */
418 /* don't log the error! mark this log entry to be blown away, and
427 /** Output a message to the log. It gets logged to all logfiles that
428 * care about messages with <b>severity</b> in <b>domain</b>. The content
429 * is formatted printf-style based on <b>format</b> and extra arguments.
432 tor_log(int severity
, log_domain_mask_t domain
, const char *format
, ...)
435 if (severity
> log_global_min_severity_
)
438 logv(severity
, domain
, NULL
, NULL
, format
, ap
);
442 /** Output a message to the log, prefixed with a function name <b>fn</b>. */
444 /** GCC-based implementation of the log_fn backend, used when we have
445 * variadic macros. All arguments are as for log_fn, except for
446 * <b>fn</b>, which is the name of the calling functions. */
448 log_fn_(int severity
, log_domain_mask_t domain
, const char *fn
,
449 const char *format
, ...)
452 if (severity
> log_global_min_severity_
)
455 logv(severity
, domain
, fn
, NULL
, format
, ap
);
459 log_fn_ratelim_(ratelim_t
*ratelim
, int severity
, log_domain_mask_t domain
,
460 const char *fn
, const char *format
, ...)
464 if (severity
> log_global_min_severity_
)
466 m
= rate_limit_log(ratelim
, approx_time());
469 va_start(ap
, format
);
470 logv(severity
, domain
, fn
, m
, format
, ap
);
476 /** Variant implementation of log_fn, log_debug, log_info,... for C compilers
477 * without variadic macros. In this case, the calling function sets
478 * log_fn_function_name_ to the name of the function, then invokes the
479 * appropriate log_fn_, log_debug_, etc. */
480 const char *log_fn_function_name_
=NULL
;
482 log_fn_(int severity
, log_domain_mask_t domain
, const char *format
, ...)
485 if (severity
> log_global_min_severity_
)
488 logv(severity
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
490 log_fn_function_name_
= NULL
;
493 log_fn_ratelim_(ratelim_t
*ratelim
, int severity
, log_domain_mask_t domain
,
494 const char *format
, ...)
498 if (severity
> log_global_min_severity_
)
500 m
= rate_limit_log(ratelim
, approx_time());
503 va_start(ap
, format
);
504 logv(severity
, domain
, log_fn_function_name_
, m
, format
, ap
);
509 log_debug_(log_domain_mask_t domain
, const char *format
, ...)
512 /* For GCC we do this check in the macro. */
513 if (PREDICT_LIKELY(LOG_DEBUG
> log_global_min_severity_
))
516 logv(LOG_DEBUG
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
518 log_fn_function_name_
= NULL
;
521 log_info_(log_domain_mask_t domain
, const char *format
, ...)
524 if (LOG_INFO
> log_global_min_severity_
)
527 logv(LOG_INFO
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
529 log_fn_function_name_
= NULL
;
532 log_notice_(log_domain_mask_t domain
, const char *format
, ...)
535 if (LOG_NOTICE
> log_global_min_severity_
)
538 logv(LOG_NOTICE
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
540 log_fn_function_name_
= NULL
;
543 log_warn_(log_domain_mask_t domain
, const char *format
, ...)
546 if (LOG_WARN
> log_global_min_severity_
)
549 logv(LOG_WARN
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
551 log_fn_function_name_
= NULL
;
554 log_err_(log_domain_mask_t domain
, const char *format
, ...)
557 if (LOG_ERR
> log_global_min_severity_
)
560 logv(LOG_ERR
, domain
, log_fn_function_name_
, NULL
, format
, ap
);
562 log_fn_function_name_
= NULL
;
567 /** Free all storage held by <b>victim</b>. */
569 log_free(logfile_t
*victim
)
573 tor_free(victim
->severities
);
574 tor_free(victim
->filename
);
578 /** Close all open log files, and free other static memory. */
582 logfile_t
*victim
, *next
;
583 smartlist_t
*messages
;
587 messages
= pending_cb_messages
;
588 pending_cb_messages
= NULL
;
598 SMARTLIST_FOREACH(messages
, pending_cb_message_t
*, msg
, {
602 smartlist_free(messages
);
604 /* We _could_ destroy the log mutex here, but that would screw up any logs
605 * that happened between here and the end of execution. */
608 /** Remove and free the log entry <b>victim</b> from the linked-list
609 * logfiles (it is probably present, but it might not be due to thread
610 * racing issues). After this function is called, the caller shouldn't
611 * refer to <b>victim</b> anymore.
613 * Long-term, we need to do something about races in the log subsystem
614 * in general. See bug 222 for more details.
617 delete_log(logfile_t
*victim
)
620 if (victim
== logfiles
)
621 logfiles
= victim
->next
;
623 for (tmpl
= logfiles
; tmpl
&& tmpl
->next
!= victim
; tmpl
=tmpl
->next
) ;
625 // tor_assert(tmpl->next == victim);
628 tmpl
->next
= victim
->next
;
633 /** Helper: release system resources (but not memory) held by a single
636 close_log(logfile_t
*victim
)
638 if (victim
->needs_close
&& victim
->fd
>= 0) {
641 } else if (victim
->is_syslog
) {
643 if (--syslog_count
== 0) {
644 /* There are no other syslogs; close the logging facility. */
651 /** Adjust a log severity configuration in <b>severity_out</b> to contain
652 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
655 set_log_severity_config(int loglevelMin
, int loglevelMax
,
656 log_severity_list_t
*severity_out
)
659 tor_assert(loglevelMin
>= loglevelMax
);
660 tor_assert(loglevelMin
>= LOG_ERR
&& loglevelMin
<= LOG_DEBUG
);
661 tor_assert(loglevelMax
>= LOG_ERR
&& loglevelMax
<= LOG_DEBUG
);
662 memset(severity_out
, 0, sizeof(log_severity_list_t
));
663 for (i
= loglevelMin
; i
>= loglevelMax
; --i
) {
664 severity_out
->masks
[SEVERITY_MASK_IDX(i
)] = ~0u;
668 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
669 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
671 add_stream_log_impl(const log_severity_list_t
*severity
,
672 const char *name
, int fd
)
675 lf
= tor_malloc_zero(sizeof(logfile_t
));
677 lf
->filename
= tor_strdup(name
);
678 lf
->severities
= tor_memdup(severity
, sizeof(log_severity_list_t
));
682 log_global_min_severity_
= get_min_log_level();
685 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
686 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
687 * not use it after calling this function. */
689 add_stream_log(const log_severity_list_t
*severity
, const char *name
, int fd
)
692 add_stream_log_impl(severity
, name
, fd
);
696 /** Initialize the global logging facility */
700 if (!log_mutex_initialized
) {
701 tor_mutex_init(&log_mutex
);
702 log_mutex_initialized
= 1;
704 if (pending_cb_messages
== NULL
)
705 pending_cb_messages
= smartlist_new();
708 /** Set whether we report logging domains as a part of our log messages.
711 logs_set_domain_logging(int enabled
)
714 log_domains_are_logged
= enabled
;
718 /** Add a log handler to receive messages during startup (before the real
719 * logs are initialized).
722 add_temp_log(int min_severity
)
724 log_severity_list_t
*s
= tor_malloc_zero(sizeof(log_severity_list_t
));
725 set_log_severity_config(min_severity
, LOG_ERR
, s
);
727 add_stream_log_impl(s
, "<temp>", fileno(stdout
));
729 logfiles
->is_temporary
= 1;
734 * Add a log handler to send messages in <b>severity</b>
735 * to the function <b>cb</b>.
738 add_callback_log(const log_severity_list_t
*severity
, log_callback cb
)
741 lf
= tor_malloc_zero(sizeof(logfile_t
));
743 lf
->severities
= tor_memdup(severity
, sizeof(log_severity_list_t
));
744 lf
->filename
= tor_strdup("<callback>");
750 log_global_min_severity_
= get_min_log_level();
755 /** Adjust the configured severity of any logs whose callback function is
758 change_callback_log_severity(int loglevelMin
, int loglevelMax
,
762 log_severity_list_t severities
;
763 set_log_severity_config(loglevelMin
, loglevelMax
, &severities
);
765 for (lf
= logfiles
; lf
; lf
= lf
->next
) {
766 if (lf
->callback
== cb
) {
767 memcpy(lf
->severities
, &severities
, sizeof(severities
));
770 log_global_min_severity_
= get_min_log_level();
774 /** If there are any log messages that were generated with LD_NOCB waiting to
775 * be sent to callback-based loggers, send them now. */
777 flush_pending_log_callbacks(void)
780 smartlist_t
*messages
, *messages_tmp
;
783 if (0 == smartlist_len(pending_cb_messages
)) {
788 messages
= pending_cb_messages
;
789 pending_cb_messages
= smartlist_new();
791 SMARTLIST_FOREACH_BEGIN(messages
, pending_cb_message_t
*, msg
) {
792 const int severity
= msg
->severity
;
793 const int domain
= msg
->domain
;
794 for (lf
= logfiles
; lf
; lf
= lf
->next
) {
795 if (! lf
->callback
|| lf
->seems_dead
||
796 ! (lf
->severities
->masks
[SEVERITY_MASK_IDX(severity
)] & domain
)) {
799 lf
->callback(severity
, domain
, msg
->msg
);
803 } SMARTLIST_FOREACH_END(msg
);
804 smartlist_clear(messages
);
806 messages_tmp
= pending_cb_messages
;
807 pending_cb_messages
= messages
;
808 messages
= messages_tmp
;
809 } while (smartlist_len(messages
));
811 smartlist_free(messages
);
816 /** Close any log handlers added by add_temp_log() or marked by
817 * mark_logs_temp(). */
819 close_temp_logs(void)
824 for (p
= &logfiles
; *p
; ) {
825 if ((*p
)->is_temporary
) {
827 /* we use *p here to handle the edge case of the head of the list */
836 log_global_min_severity_
= get_min_log_level();
840 /** Make all currently temporary logs (set to be closed by close_temp_logs)
841 * live again, and close all non-temporary logs. */
843 rollback_log_changes(void)
847 for (lf
= logfiles
; lf
; lf
= lf
->next
)
848 lf
->is_temporary
= ! lf
->is_temporary
;
853 /** Configure all log handles to be closed by close_temp_logs(). */
859 for (lf
= logfiles
; lf
; lf
= lf
->next
)
860 lf
->is_temporary
= 1;
865 * Add a log handler to send messages to <b>filename</b>. If opening the
866 * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
869 add_file_log(const log_severity_list_t
*severity
, const char *filename
)
874 fd
= tor_open_cloexec(filename
, O_WRONLY
|O_CREAT
|O_APPEND
, 0644);
877 if (tor_fd_seekend(fd
)<0) {
883 add_stream_log_impl(severity
, filename
, fd
);
884 logfiles
->needs_close
= 1;
886 log_global_min_severity_
= get_min_log_level();
888 if (log_tor_version(lf
, 0) < 0) {
898 * Add a log handler to send messages to they system log facility.
901 add_syslog_log(const log_severity_list_t
*severity
)
904 if (syslog_count
++ == 0)
905 /* This is the first syslog. */
906 openlog("Tor", LOG_PID
| LOG_NDELAY
, LOGFACILITY
);
908 lf
= tor_malloc_zero(sizeof(logfile_t
));
910 lf
->severities
= tor_memdup(severity
, sizeof(log_severity_list_t
));
911 lf
->filename
= tor_strdup("<syslog>");
917 log_global_min_severity_
= get_min_log_level();
923 /** If <b>level</b> is a valid log severity, return the corresponding
924 * numeric value. Otherwise, return -1. */
926 parse_log_level(const char *level
)
928 if (!strcasecmp(level
, "err"))
930 if (!strcasecmp(level
, "warn"))
932 if (!strcasecmp(level
, "notice"))
934 if (!strcasecmp(level
, "info"))
936 if (!strcasecmp(level
, "debug"))
941 /** Return the string equivalent of a given log level. */
943 log_level_to_string(int level
)
945 return sev_to_string(level
);
948 /** NULL-terminated array of names for log domains such that domain_list[dom]
949 * is a description of <b>dom</b>. */
950 static const char *domain_list
[] = {
951 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
952 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
953 "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL", NULL
956 /** Return a bitmask for the log domain for which <b>domain</b> is the name,
957 * or 0 if there is no such name. */
958 static log_domain_mask_t
959 parse_log_domain(const char *domain
)
962 for (i
=0; domain_list
[i
]; ++i
) {
963 if (!strcasecmp(domain
, domain_list
[i
]))
969 /** Translate a bitmask of log domains to a string. */
971 domain_to_string(log_domain_mask_t domain
, char *buf
, size_t buflen
)
974 char *eos
= buf
+buflen
;
981 int bit
= tor_log2(domain
);
983 if (bit
>= N_LOGGING_DOMAINS
) {
984 tor_snprintf(buf
, buflen
, "<BUG:Unknown domain %lx>", (long)domain
);
985 return buf
+strlen(buf
);
987 d
= domain_list
[bit
];
988 n
= strlcpy(cp
, d
, eos
-cp
);
990 tor_snprintf(buf
, buflen
, "<BUG:Truncating domain %lx>", (long)domain
);
991 return buf
+strlen(buf
);
996 if (domain
== 0 || (eos
-cp
) < 2)
999 memcpy(cp
, ",", 2); /*Nul-terminated ,"*/
1004 /** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
1005 * the end of the severityPattern. Set the value of <b>severity_out</b> to
1006 * the parsed pattern. Return 0 on success, -1 on failure.
1008 * The syntax for a SeverityPattern is:
1010 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
1011 * DomainSeverity = (DomainList SP)? SeverityRange
1012 * SeverityRange = MinSeverity ("-" MaxSeverity )?
1013 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
1014 * DomainSpec = "*" | Domain | "~" Domain
1016 * A missing MaxSeverity defaults to ERR. Severities and domains are
1017 * case-insensitive. "~" indicates negation for a domain; negation happens
1018 * last inside a DomainList. Only one SeverityRange without a DomainList is
1022 parse_log_severity_config(const char **cfg_ptr
,
1023 log_severity_list_t
*severity_out
)
1025 const char *cfg
= *cfg_ptr
;
1026 int got_anything
= 0;
1027 int got_an_unqualified_range
= 0;
1028 memset(severity_out
, 0, sizeof(*severity_out
));
1030 cfg
= eat_whitespace(cfg
);
1032 const char *dash
, *space
;
1033 char *sev_lo
, *sev_hi
;
1035 log_domain_mask_t domains
= ~0u;
1040 smartlist_t
*domains_list
;
1041 log_domain_mask_t neg_domains
= 0;
1042 const char *closebracket
= strchr(cfg
, ']');
1046 domains_str
= tor_strndup(cfg
+1, closebracket
-cfg
-1);
1047 domains_list
= smartlist_new();
1048 smartlist_split_string(domains_list
, domains_str
, ",", SPLIT_SKIP_SPACE
,
1050 tor_free(domains_str
);
1051 SMARTLIST_FOREACH_BEGIN(domains_list
, const char *, domain
) {
1052 if (!strcmp(domain
, "*")) {
1057 if (*domain
== '~') {
1061 d
= parse_log_domain(domain
);
1063 log_warn(LD_CONFIG
, "No such logging domain as %s", domain
);
1072 } SMARTLIST_FOREACH_END(domain
);
1073 SMARTLIST_FOREACH(domains_list
, char *, d
, tor_free(d
));
1074 smartlist_free(domains_list
);
1077 if (domains
== 0 && neg_domains
)
1078 domains
= ~neg_domains
;
1080 domains
&= ~neg_domains
;
1081 cfg
= eat_whitespace(closebracket
+1);
1083 ++got_an_unqualified_range
;
1085 if (!strcasecmpstart(cfg
, "file") ||
1086 !strcasecmpstart(cfg
, "stderr") ||
1087 !strcasecmpstart(cfg
, "stdout") ||
1088 !strcasecmpstart(cfg
, "syslog")) {
1091 if (got_an_unqualified_range
> 1)
1094 space
= strchr(cfg
, ' ');
1095 dash
= strchr(cfg
, '-');
1097 space
= strchr(cfg
, '\0');
1098 if (dash
&& dash
< space
) {
1099 sev_lo
= tor_strndup(cfg
, dash
-cfg
);
1100 sev_hi
= tor_strndup(dash
+1, space
-(dash
+1));
1102 sev_lo
= tor_strndup(cfg
, space
-cfg
);
1103 sev_hi
= tor_strdup("ERR");
1105 low
= parse_log_level(sev_lo
);
1106 high
= parse_log_level(sev_hi
);
1115 for (i
=low
; i
>= high
; --i
)
1116 severity_out
->masks
[SEVERITY_MASK_IDX(i
)] |= domains
;
1118 cfg
= eat_whitespace(space
);
1123 return got_anything
? 0 : -1;
1126 /** Return the least severe log level that any current log is interested in. */
1128 get_min_log_level(void)
1133 for (lf
= logfiles
; lf
; lf
= lf
->next
) {
1134 for (i
= LOG_DEBUG
; i
> min
; --i
)
1135 if (lf
->severities
->masks
[SEVERITY_MASK_IDX(i
)])
1141 /** Switch all logs to output at most verbose level. */
1143 switch_logs_debug(void)
1148 for (lf
= logfiles
; lf
; lf
=lf
->next
) {
1149 for (i
= LOG_DEBUG
; i
>= LOG_ERR
; --i
)
1150 lf
->severities
->masks
[SEVERITY_MASK_IDX(i
)] = ~0u;
1152 log_global_min_severity_
= get_min_log_level();
1158 dump_log_info(logfile_t
*lf
)
1163 printf("=== log into \"%s\" (%s-%s) (%stemporary)\n", lf
->filename
,
1164 sev_to_string(lf
->min_loglevel
),
1165 sev_to_string(lf
->max_loglevel
),
1166 lf
->is_temporary
?"":"not ");
1167 } else if (lf
->is_syslog
) {
1168 printf("=== syslog (%s-%s) (%stemporary)\n",
1169 sev_to_string(lf
->min_loglevel
),
1170 sev_to_string(lf
->max_loglevel
),
1171 lf
->is_temporary
?"":"not ");
1173 printf("=== log (%s-%s) (%stemporary)\n",
1174 sev_to_string(lf
->min_loglevel
),
1175 sev_to_string(lf
->max_loglevel
),
1176 lf
->is_temporary
?"":"not ");
1184 printf("==== BEGIN LOGS ====\n");
1185 for (lf
= logfiles
; lf
; lf
= lf
->next
)
1187 printf("==== END LOGS ====\n");