Document some variables used for generating statistics on usage of V0 hidden service...
[tor/rransom.git] / src / common / log.c
blobadab467976af8e51e04501c6aaa119ab4793f573
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-2008, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file log.c
9 * \brief Functions to send messages to log files or the console.
10 **/
12 #include "orconfig.h"
13 #include <stdarg.h>
14 #include <assert.h>
15 // #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #ifdef HAVE_SYS_TIME_H
19 #include <sys/time.h>
20 #endif
21 #ifdef HAVE_TIME_H
22 #include <time.h>
23 #endif
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
29 #endif
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
33 #include "compat.h"
34 #include "util.h"
35 #define LOG_PRIVATE
36 #include "log.h"
37 #include "container.h"
39 #include <event.h>
41 #define TRUNCATED_STR "[...truncated]"
42 #define TRUNCATED_STR_LEN 14
44 /** Information for a single logfile; only used in log.c */
45 typedef struct logfile_t {
46 struct logfile_t *next; /**< Next logfile_t in the linked list. */
47 char *filename; /**< Filename to open. */
48 int fd; /**< fd to receive log messages, or -1 for none. */
49 int seems_dead; /**< Boolean: true if the stream seems to be kaput. */
50 int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
51 int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
52 int is_syslog; /**< Boolean: send messages to syslog. */
53 log_callback callback; /**< If not NULL, send messages to this function. */
54 log_severity_list_t *severities; /**< Which severity of messages should we
55 * log for each log domain? */
56 } logfile_t;
58 static void log_free(logfile_t *victim);
60 /** Helper: map a log severity to descriptive string. */
61 static INLINE const char *
62 sev_to_string(int severity)
64 switch (severity) {
65 case LOG_DEBUG: return "debug";
66 case LOG_INFO: return "info";
67 case LOG_NOTICE: return "notice";
68 case LOG_WARN: return "warn";
69 case LOG_ERR: return "err";
70 default: /* Call assert, not tor_assert, since tor_assert
71 * calls log on failure. */
72 assert(0); return "UNKNOWN";
76 /** Helper: decide whether to include the function name in the log message. */
77 static INLINE int
78 should_log_function_name(log_domain_mask_t domain, int severity)
80 switch (severity) {
81 case LOG_DEBUG:
82 case LOG_INFO:
83 /* All debugging messages occur in interesting places. */
84 return 1;
85 case LOG_NOTICE:
86 case LOG_WARN:
87 case LOG_ERR:
88 /* We care about places where bugs occur. */
89 return (domain == LD_BUG);
90 default:
91 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
92 assert(0); return 0;
96 /** A mutex to guard changes to logfiles and logging. */
97 static tor_mutex_t *log_mutex = NULL;
99 /** Linked list of logfile_t. */
100 static logfile_t *logfiles = NULL;
101 #ifdef HAVE_SYSLOG_H
102 /** The number of open syslog log handlers that we have. When this reaches 0,
103 * we can close our connection to the syslog facility. */
104 static int syslog_count = 0;
105 #endif
107 #define LOCK_LOGS() STMT_BEGIN \
108 tor_mutex_acquire(log_mutex); \
109 STMT_END
110 #define UNLOCK_LOGS() STMT_BEGIN tor_mutex_release(log_mutex); STMT_END
112 /** What's the lowest log level anybody cares about? Checking this lets us
113 * bail out early from log_debug if we aren't debugging. */
114 int _log_global_min_severity = LOG_NOTICE;
116 static void delete_log(logfile_t *victim);
117 static void close_log(logfile_t *victim);
119 /** Name of the application: used to generate the message we write at the
120 * start of each new log. */
121 static char *appname = NULL;
123 /** Set the "application name" for the logs to <b>name</b>: we'll use this
124 * name in the message we write when starting up, and at the start of each new
125 * log.
127 * Tor uses this string to write the version number to the log file. */
128 void
129 log_set_application_name(const char *name)
131 tor_free(appname);
132 appname = name ? tor_strdup(name) : NULL;
135 /** Helper: Write the standard prefix for log lines to a
136 * <b>buf_len</b> character buffer in <b>buf</b>.
138 static INLINE size_t
139 _log_prefix(char *buf, size_t buf_len, int severity)
141 time_t t;
142 struct timeval now;
143 struct tm tm;
144 size_t n;
145 int r;
147 tor_gettimeofday(&now);
148 t = (time_t)now.tv_sec;
150 n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
151 r = tor_snprintf(buf+n, buf_len-n, ".%.3ld [%s] ",
152 (long)now.tv_usec / 1000, sev_to_string(severity));
153 if (r<0)
154 return buf_len-1;
155 else
156 return n+r;
159 /** If lf refers to an actual file that we have just opened, and the file
160 * contains no data, log an "opening new logfile" message at the top.
162 * Return -1 if the log is broken and needs to be deleted, else return 0.
164 static int
165 log_tor_version(logfile_t *lf, int reset)
167 char buf[256];
168 size_t n;
169 int is_new;
171 if (!lf->needs_close)
172 /* If it doesn't get closed, it isn't really a file. */
173 return 0;
174 if (lf->is_temporary)
175 /* If it's temporary, it isn't really a file. */
176 return 0;
178 is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
180 if (reset && !is_new)
181 /* We are resetting, but we aren't at the start of the file; no
182 * need to log again. */
183 return 0;
184 n = _log_prefix(buf, sizeof(buf), LOG_NOTICE);
185 if (appname) {
186 tor_snprintf(buf+n, sizeof(buf)-n,
187 "%s opening %slog file.\n", appname, is_new?"new ":"");
188 } else {
189 tor_snprintf(buf+n, sizeof(buf)-n,
190 "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
192 if (write_all(lf->fd, buf, strlen(buf), 0) < 0) /* error */
193 return -1; /* failed */
194 return 0;
197 /** Helper: Format a log message into a fixed-sized buffer. (This is
198 * factored out of <b>logv</b> so that we never format a message more
199 * than once.) Return a pointer to the first character of the message
200 * portion of the formatted string.
202 static INLINE char *
203 format_msg(char *buf, size_t buf_len,
204 log_domain_mask_t domain, int severity, const char *funcname,
205 const char *format, va_list ap, size_t *msg_len_out)
207 size_t n;
208 int r;
209 char *end_of_prefix;
211 assert(buf_len >= 2); /* prevent integer underflow */
212 buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
214 n = _log_prefix(buf, buf_len, severity);
215 end_of_prefix = buf+n;
217 if (funcname && should_log_function_name(domain, severity)) {
218 r = tor_snprintf(buf+n, buf_len-n, "%s(): ", funcname);
219 if (r<0)
220 n = strlen(buf);
221 else
222 n += r;
225 if (domain == LD_BUG && buf_len-n > 6) {
226 memcpy(buf+n, "Bug: ", 6);
227 n += 5;
230 r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
231 if (r < 0) {
232 /* The message was too long; overwrite the end of the buffer with
233 * "[...truncated]" */
234 if (buf_len >= TRUNCATED_STR_LEN) {
235 size_t offset = buf_len-TRUNCATED_STR_LEN;
236 /* We have an extra 2 characters after buf_len to hold the \n\0,
237 * so it's safe to add 1 to the size here. */
238 strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
240 /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
241 * Since we already subtracted 2 from buf_len, this is safe.*/
242 n = buf_len;
243 } else {
244 n += r;
246 buf[n]='\n';
247 buf[n+1]='\0';
248 *msg_len_out = n+1;
249 return end_of_prefix;
252 /** Helper: sends a message to the appropriate logfiles, at loglevel
253 * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
254 * message. The actual message is derived as from tor_snprintf(format,ap).
256 static void
257 logv(int severity, log_domain_mask_t domain, const char *funcname,
258 const char *format, va_list ap)
260 char buf[10024];
261 size_t msg_len = 0;
262 int formatted = 0;
263 logfile_t *lf;
264 char *end_of_prefix=NULL;
266 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
267 assert(format);
268 /* check that severity is sane. Overrunning the masks array leads to
269 * interesting and hard to diagnose effects */
270 assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
271 LOCK_LOGS();
272 lf = logfiles;
273 while (lf) {
274 if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
275 lf = lf->next;
276 continue;
278 if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
279 lf = lf->next;
280 continue;
282 if (lf->seems_dead) {
283 lf = lf->next;
284 continue;
287 if (!formatted) {
288 end_of_prefix =
289 format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
290 &msg_len);
291 formatted = 1;
293 if (lf->is_syslog) {
294 #ifdef HAVE_SYSLOG_H
295 char *m = end_of_prefix;
296 #ifdef MAXLINE
297 /* Some syslog implementations have limits on the length of what you can
298 * pass them, and some very old ones do not detect overflow so well.
299 * Regrettably, they call their maximum line length MAXLINE. */
300 #if MAXLINE < 64
301 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
302 #endif
303 if (msg_len >= MAXLINE)
304 m = tor_strndup(end_of_prefix, MAXLINE-1);
305 #endif
306 syslog(severity, "%s", m);
307 #ifdef MAXLINE
308 if (m != end_of_prefix) {
309 tor_free(m);
311 #endif
312 #endif
313 lf = lf->next;
314 continue;
315 } else if (lf->callback) {
316 lf->callback(severity, domain, end_of_prefix);
317 lf = lf->next;
318 continue;
320 if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
321 /* don't log the error! mark this log entry to be blown away, and
322 * continue. */
323 lf->seems_dead = 1;
325 lf = lf->next;
327 UNLOCK_LOGS();
330 /** Output a message to the log. */
331 void
332 _log(int severity, log_domain_mask_t domain, const char *format, ...)
334 va_list ap;
335 if (severity > _log_global_min_severity)
336 return;
337 va_start(ap,format);
338 logv(severity, domain, NULL, format, ap);
339 va_end(ap);
342 /** Output a message to the log, prefixed with a function name <b>fn</b>. */
343 #ifdef __GNUC__
344 void
345 _log_fn(int severity, log_domain_mask_t domain, const char *fn,
346 const char *format, ...)
348 va_list ap;
349 if (severity > _log_global_min_severity)
350 return;
351 va_start(ap,format);
352 logv(severity, domain, fn, format, ap);
353 va_end(ap);
355 #else
356 const char *_log_fn_function_name=NULL;
357 void
358 _log_fn(int severity, log_domain_mask_t domain, const char *format, ...)
360 va_list ap;
361 if (severity > _log_global_min_severity)
362 return;
363 va_start(ap,format);
364 logv(severity, domain, _log_fn_function_name, format, ap);
365 va_end(ap);
366 _log_fn_function_name = NULL;
368 void
369 _log_debug(log_domain_mask_t domain, const char *format, ...)
371 va_list ap;
372 /* For GCC we do this check in the macro. */
373 if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity))
374 return;
375 va_start(ap,format);
376 logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap);
377 va_end(ap);
378 _log_fn_function_name = NULL;
380 void
381 _log_info(log_domain_mask_t domain, const char *format, ...)
383 va_list ap;
384 if (LOG_INFO > _log_global_min_severity)
385 return;
386 va_start(ap,format);
387 logv(LOG_INFO, domain, _log_fn_function_name, format, ap);
388 va_end(ap);
389 _log_fn_function_name = NULL;
391 void
392 _log_notice(log_domain_mask_t domain, const char *format, ...)
394 va_list ap;
395 if (LOG_NOTICE > _log_global_min_severity)
396 return;
397 va_start(ap,format);
398 logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap);
399 va_end(ap);
400 _log_fn_function_name = NULL;
402 void
403 _log_warn(log_domain_mask_t domain, const char *format, ...)
405 va_list ap;
406 if (LOG_WARN > _log_global_min_severity)
407 return;
408 va_start(ap,format);
409 logv(LOG_WARN, domain, _log_fn_function_name, format, ap);
410 va_end(ap);
411 _log_fn_function_name = NULL;
413 void
414 _log_err(log_domain_mask_t domain, const char *format, ...)
416 va_list ap;
417 if (LOG_ERR > _log_global_min_severity)
418 return;
419 va_start(ap,format);
420 logv(LOG_ERR, domain, _log_fn_function_name, format, ap);
421 va_end(ap);
422 _log_fn_function_name = NULL;
424 #endif
426 /** Free all storage held by <b>victim</b>. */
427 static void
428 log_free(logfile_t *victim)
430 tor_free(victim->severities);
431 tor_free(victim->filename);
432 tor_free(victim);
435 /** Close all open log files, and free other static memory. */
436 void
437 logs_free_all(void)
439 logfile_t *victim, *next;
440 LOCK_LOGS();
441 next = logfiles;
442 logfiles = NULL;
443 UNLOCK_LOGS();
444 while (next) {
445 victim = next;
446 next = next->next;
447 close_log(victim);
448 log_free(victim);
450 tor_free(appname);
451 tor_mutex_free(log_mutex);
452 log_mutex = NULL;
455 /** Remove and free the log entry <b>victim</b> from the linked-list
456 * logfiles (it is probably present, but it might not be due to thread
457 * racing issues). After this function is called, the caller shouldn't
458 * refer to <b>victim</b> anymore.
460 * Long-term, we need to do something about races in the log subsystem
461 * in general. See bug 222 for more details.
463 static void
464 delete_log(logfile_t *victim)
466 logfile_t *tmpl;
467 if (victim == logfiles)
468 logfiles = victim->next;
469 else {
470 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
471 // tor_assert(tmpl);
472 // tor_assert(tmpl->next == victim);
473 if (!tmpl)
474 return;
475 tmpl->next = victim->next;
477 log_free(victim);
480 /** Helper: release system resources (but not memory) held by a single
481 * logfile_t. */
482 static void
483 close_log(logfile_t *victim)
485 if (victim->needs_close && victim->fd >= 0) {
486 close(victim->fd);
487 victim->fd = -1;
488 } else if (victim->is_syslog) {
489 #ifdef HAVE_SYSLOG_H
490 if (--syslog_count == 0) {
491 /* There are no other syslogs; close the logging facility. */
492 closelog();
494 #endif
498 /** Adjust a log severity configuration in <b>severity_out</b> to contain
499 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
501 void
502 set_log_severity_config(int loglevelMin, int loglevelMax,
503 log_severity_list_t *severity_out)
505 int i;
506 tor_assert(loglevelMin >= loglevelMax);
507 tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
508 tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
509 memset(severity_out, 0, sizeof(log_severity_list_t));
510 for (i = loglevelMin; i >= loglevelMax; --i) {
511 severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
515 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
516 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
517 static void
518 add_stream_log_impl(const log_severity_list_t *severity,
519 const char *name, int fd)
521 logfile_t *lf;
522 lf = tor_malloc_zero(sizeof(logfile_t));
523 lf->fd = fd;
524 lf->filename = tor_strdup(name);
525 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
526 lf->next = logfiles;
528 logfiles = lf;
529 _log_global_min_severity = get_min_log_level();
532 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
533 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
534 * not use it after calling this function. */
535 void
536 add_stream_log(const log_severity_list_t *severity,
537 const char *name, int fd)
539 LOCK_LOGS();
540 add_stream_log_impl(severity, name, fd);
541 UNLOCK_LOGS();
544 /** Initialize the global logging facility */
545 void
546 init_logging(void)
548 if (!log_mutex)
549 log_mutex = tor_mutex_new();
552 /** Add a log handler to receive messages during startup (before the real
553 * logs are initialized).
555 void
556 add_temp_log(int min_severity)
558 log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
559 set_log_severity_config(min_severity, LOG_ERR, s);
560 LOCK_LOGS();
561 add_stream_log_impl(s, "<temp>", fileno(stdout));
562 tor_free(s);
563 logfiles->is_temporary = 1;
564 UNLOCK_LOGS();
568 * Add a log handler to send messages in <b>severity</b>
569 * to the function <b>cb</b>.
572 add_callback_log(const log_severity_list_t *severity, log_callback cb)
574 logfile_t *lf;
575 lf = tor_malloc_zero(sizeof(logfile_t));
576 lf->fd = -1;
577 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
578 lf->filename = tor_strdup("<callback>");
579 lf->callback = cb;
580 lf->next = logfiles;
582 LOCK_LOGS();
583 logfiles = lf;
584 _log_global_min_severity = get_min_log_level();
585 UNLOCK_LOGS();
586 return 0;
589 /** Adjust the configured severity of any logs whose callback function is
590 * <b>cb</b>. */
591 void
592 change_callback_log_severity(int loglevelMin, int loglevelMax,
593 log_callback cb)
595 logfile_t *lf;
596 log_severity_list_t severities;
597 set_log_severity_config(loglevelMin, loglevelMax, &severities);
598 LOCK_LOGS();
599 for (lf = logfiles; lf; lf = lf->next) {
600 if (lf->callback == cb) {
601 memcpy(lf->severities, &severities, sizeof(severities));
604 _log_global_min_severity = get_min_log_level();
605 UNLOCK_LOGS();
608 /** Close any log handlers added by add_temp_log() or marked by
609 * mark_logs_temp(). */
610 void
611 close_temp_logs(void)
613 logfile_t *lf, **p;
615 LOCK_LOGS();
616 for (p = &logfiles; *p; ) {
617 if ((*p)->is_temporary) {
618 lf = *p;
619 /* we use *p here to handle the edge case of the head of the list */
620 *p = (*p)->next;
621 close_log(lf);
622 log_free(lf);
623 } else {
624 p = &((*p)->next);
628 _log_global_min_severity = get_min_log_level();
629 UNLOCK_LOGS();
632 /** Make all currently temporary logs (set to be closed by close_temp_logs)
633 * live again, and close all non-temporary logs. */
634 void
635 rollback_log_changes(void)
637 logfile_t *lf;
638 LOCK_LOGS();
639 for (lf = logfiles; lf; lf = lf->next)
640 lf->is_temporary = ! lf->is_temporary;
641 UNLOCK_LOGS();
642 close_temp_logs();
645 /** Configure all log handles to be closed by close_temp_logs(). */
646 void
647 mark_logs_temp(void)
649 logfile_t *lf;
650 LOCK_LOGS();
651 for (lf = logfiles; lf; lf = lf->next)
652 lf->is_temporary = 1;
653 UNLOCK_LOGS();
657 * Add a log handler to send messages to <b>filename</b>. If opening the
658 * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
661 add_file_log(const log_severity_list_t *severity, const char *filename)
663 int fd;
664 logfile_t *lf;
666 fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
667 if (fd<0)
668 return -1;
669 if (tor_fd_seekend(fd)<0)
670 return -1;
672 LOCK_LOGS();
673 add_stream_log_impl(severity, filename, fd);
674 logfiles->needs_close = 1;
675 lf = logfiles;
676 _log_global_min_severity = get_min_log_level();
677 UNLOCK_LOGS();
679 if (log_tor_version(lf, 0) < 0) {
680 LOCK_LOGS();
681 delete_log(lf);
682 UNLOCK_LOGS();
685 return 0;
688 #ifdef HAVE_SYSLOG_H
690 * Add a log handler to send messages to they system log facility.
693 add_syslog_log(const log_severity_list_t *severity)
695 logfile_t *lf;
696 if (syslog_count++ == 0)
697 /* This is the first syslog. */
698 openlog("Tor", LOG_PID | LOG_NDELAY, LOGFACILITY);
700 lf = tor_malloc_zero(sizeof(logfile_t));
701 lf->fd = -1;
702 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
703 lf->filename = tor_strdup("<syslog>");
705 lf->is_syslog = 1;
707 LOCK_LOGS();
708 lf->next = logfiles;
709 logfiles = lf;
710 _log_global_min_severity = get_min_log_level();
711 UNLOCK_LOGS();
712 return 0;
714 #endif
716 /** If <b>level</b> is a valid log severity, return the corresponding
717 * numeric value. Otherwise, return -1. */
719 parse_log_level(const char *level)
721 if (!strcasecmp(level, "err"))
722 return LOG_ERR;
723 if (!strcasecmp(level, "warn"))
724 return LOG_WARN;
725 if (!strcasecmp(level, "notice"))
726 return LOG_NOTICE;
727 if (!strcasecmp(level, "info"))
728 return LOG_INFO;
729 if (!strcasecmp(level, "debug"))
730 return LOG_DEBUG;
731 return -1;
734 /** Return the string equivalent of a given log level. */
735 const char *
736 log_level_to_string(int level)
738 return sev_to_string(level);
741 /** NULL-terminated array of names for log domains such that domain_list[dom]
742 * is a description of <b>dom</b>. */
743 static const char *domain_list[] = {
744 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
745 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
746 "OR", "EDGE", "ACCT", "HIST", NULL
749 /** Return a bitmask for the log domain for which <b>domain</b> is the name,
750 * or 0 if there is no such name. */
751 static log_domain_mask_t
752 parse_log_domain(const char *domain)
754 int i;
755 for (i=0; domain_list[i]; ++i) {
756 if (!strcasecmp(domain, domain_list[i]))
757 return (1u<<i);
759 return 0;
761 #if 0
762 /** Translate a bitmask of log domains to a string, or NULL if the bitmask
763 * is undecodable. */
764 static const char *
765 domain_to_string(log_domain_mask_t domain)
767 int bit = tor_log2(domain);
768 if ((bit == 0 && domain == 0) || bit >= N_LOGGING_DOMAINS)
769 return NULL;
770 return domain_list[bit];
772 #endif
774 /** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
775 * the end of the severityPattern. Set the value of <b>severity_out</b> to
776 * the parsed pattern. Return 0 on success, -1 on failure.
778 * The syntax for a SeverityPattern is:
779 * <pre>
780 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
781 * DomainSeverity = (DomainList SP)? SeverityRange
782 * SeverityRange = MinSeverity ("-" MaxSeverity )?
783 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
784 * DomainSpec = "*" | Domain | "~" Domain
785 * </pre>
786 * A missing MaxSeverity defaults to ERR. Severities and domains are
787 * case-insensitive. "~" indicates negation for a domain; negation happens
788 * last inside a DomainList. Only one SeverityRange without a DomainList is
789 * allowed per line.
792 parse_log_severity_config(const char **cfg_ptr,
793 log_severity_list_t *severity_out)
795 const char *cfg = *cfg_ptr;
796 int got_anything = 0;
797 int got_an_unqualified_range = 0;
798 memset(severity_out, 0, sizeof(*severity_out));
800 cfg = eat_whitespace(cfg);
801 while (*cfg) {
802 const char *dash, *space;
803 char *sev_lo, *sev_hi;
804 int low, high, i;
805 log_domain_mask_t domains = ~0u;
807 if (*cfg == '[') {
808 int err = 0;
809 char *domains_str;
810 smartlist_t *domains_list;
811 log_domain_mask_t neg_domains = 0;
812 const char *closebracket = strchr(cfg, ']');
813 if (!closebracket)
814 return -1;
815 domains = 0;
816 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
817 domains_list = smartlist_create();
818 smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
819 -1);
820 tor_free(domains_str);
821 SMARTLIST_FOREACH(domains_list, const char *, domain,
823 if (!strcmp(domain, "*")) {
824 domains = ~0u;
825 } else {
826 int d;
827 int negate=0;
828 if (*domain == '~') {
829 negate = 1;
830 ++domain;
832 d = parse_log_domain(domain);
833 if (!d) {
834 log_warn(LD_CONFIG, "No such loggging domain as %s", domain);
835 err = 1;
836 } else {
837 if (negate)
838 neg_domains |= d;
839 else
840 domains |= d;
844 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
845 smartlist_free(domains_list);
846 if (err)
847 return -1;
848 domains &= ~neg_domains;
849 cfg = eat_whitespace(closebracket+1);
850 } else {
851 ++got_an_unqualified_range;
853 if (!strcasecmpstart(cfg, "file") ||
854 !strcasecmpstart(cfg, "stderr") ||
855 !strcasecmpstart(cfg, "stdout") ||
856 !strcasecmpstart(cfg, "syslog")) {
857 goto done;
859 if (got_an_unqualified_range > 1)
860 return -1;
862 space = strchr(cfg, ' ');
863 dash = strchr(cfg, '-');
864 if (!space)
865 space = strchr(cfg, '\0');
866 if (dash && dash < space) {
867 sev_lo = tor_strndup(cfg, dash-cfg);
868 sev_hi = tor_strndup(dash+1, space-(dash+1));
869 } else {
870 sev_lo = tor_strndup(cfg, space-cfg);
871 sev_hi = tor_strdup("ERR");
873 low = parse_log_level(sev_lo);
874 high = parse_log_level(sev_hi);
875 tor_free(sev_lo);
876 tor_free(sev_hi);
877 if (low == -1)
878 return -1;
879 if (high == -1)
880 return -1;
882 got_anything = 1;
883 for (i=low; i >= high; --i)
884 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
886 cfg = eat_whitespace(space);
889 done:
890 *cfg_ptr = cfg;
891 return got_anything ? 0 : -1;
894 /** Return the least severe log level that any current log is interested in. */
896 get_min_log_level(void)
898 logfile_t *lf;
899 int i;
900 int min = LOG_ERR;
901 for (lf = logfiles; lf; lf = lf->next) {
902 for (i = LOG_DEBUG; i > min; --i)
903 if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
904 min = i;
906 return min;
909 /** Switch all logs to output at most verbose level. */
910 void
911 switch_logs_debug(void)
913 logfile_t *lf;
914 int i;
915 LOCK_LOGS();
916 for (lf = logfiles; lf; lf=lf->next) {
917 for (i = LOG_DEBUG; i >= LOG_ERR; --i)
918 lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
920 _log_global_min_severity = get_min_log_level();
921 UNLOCK_LOGS();
924 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
925 /** A string which, if it appears in a libevent log, should be ignored. */
926 static const char *suppress_msg = NULL;
927 /** Callback function passed to event_set_log() so we can intercept
928 * log messages from libevent. */
929 static void
930 libevent_logging_callback(int severity, const char *msg)
932 char buf[1024];
933 size_t n;
934 if (suppress_msg && strstr(msg, suppress_msg))
935 return;
936 n = strlcpy(buf, msg, sizeof(buf));
937 if (n && n < sizeof(buf) && buf[n-1] == '\n') {
938 buf[n-1] = '\0';
940 switch (severity) {
941 case _EVENT_LOG_DEBUG:
942 log(LOG_DEBUG, LD_NET, "Message from libevent: %s", buf);
943 break;
944 case _EVENT_LOG_MSG:
945 log(LOG_INFO, LD_NET, "Message from libevent: %s", buf);
946 break;
947 case _EVENT_LOG_WARN:
948 log(LOG_WARN, LD_GENERAL, "Warning from libevent: %s", buf);
949 break;
950 case _EVENT_LOG_ERR:
951 log(LOG_ERR, LD_GENERAL, "Error from libevent: %s", buf);
952 break;
953 default:
954 log(LOG_WARN, LD_GENERAL, "Message [%d] from libevent: %s",
955 severity, buf);
956 break;
959 /** Set hook to intercept log messages from libevent. */
960 void
961 configure_libevent_logging(void)
963 event_set_log_callback(libevent_logging_callback);
965 /** Ignore any libevent log message that contains <b>msg</b>. */
966 void
967 suppress_libevent_log_msg(const char *msg)
969 suppress_msg = msg;
971 #else
972 void
973 configure_libevent_logging(void)
976 void
977 suppress_libevent_log_msg(const char *msg)
979 (void)msg;
981 #endif
983 #if 0
984 static void
985 dump_log_info(logfile_t *lf)
987 const char *tp;
989 if (lf->filename) {
990 printf("=== log into \"%s\" (%s-%s) (%stemporary)\n", lf->filename,
991 sev_to_string(lf->min_loglevel),
992 sev_to_string(lf->max_loglevel),
993 lf->is_temporary?"":"not ");
994 } else if (lf->is_syslog) {
995 printf("=== syslog (%s-%s) (%stemporary)\n",
996 sev_to_string(lf->min_loglevel),
997 sev_to_string(lf->max_loglevel),
998 lf->is_temporary?"":"not ");
999 } else {
1000 printf("=== log (%s-%s) (%stemporary)\n",
1001 sev_to_string(lf->min_loglevel),
1002 sev_to_string(lf->max_loglevel),
1003 lf->is_temporary?"":"not ");
1007 void
1008 describe_logs(void)
1010 logfile_t *lf;
1011 printf("==== BEGIN LOGS ====\n");
1012 for (lf = logfiles; lf; lf = lf->next)
1013 dump_log_info(lf);
1014 printf("==== END LOGS ====\n");
1016 #endif