Note that Tor requires Automake 1.7. Fixes bug 2305
[tor/rransom.git] / src / common / log.c
blobfe93bd7f57eeff429042470256ae632eb2de471b
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-2011, 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;
98 static int log_mutex_initialized = 0;
100 /** Linked list of logfile_t. */
101 static logfile_t *logfiles = NULL;
102 #ifdef HAVE_SYSLOG_H
103 /** The number of open syslog log handlers that we have. When this reaches 0,
104 * we can close our connection to the syslog facility. */
105 static int syslog_count = 0;
106 #endif
108 #define LOCK_LOGS() STMT_BEGIN \
109 tor_mutex_acquire(&log_mutex); \
110 STMT_END
111 #define UNLOCK_LOGS() STMT_BEGIN tor_mutex_release(&log_mutex); STMT_END
113 /** What's the lowest log level anybody cares about? Checking this lets us
114 * bail out early from log_debug if we aren't debugging. */
115 int _log_global_min_severity = LOG_NOTICE;
117 static void delete_log(logfile_t *victim);
118 static void close_log(logfile_t *victim);
120 /** Name of the application: used to generate the message we write at the
121 * start of each new log. */
122 static char *appname = NULL;
124 /** Set the "application name" for the logs to <b>name</b>: we'll use this
125 * name in the message we write when starting up, and at the start of each new
126 * log.
128 * Tor uses this string to write the version number to the log file. */
129 void
130 log_set_application_name(const char *name)
132 tor_free(appname);
133 appname = name ? tor_strdup(name) : NULL;
136 /** Helper: Write the standard prefix for log lines to a
137 * <b>buf_len</b> character buffer in <b>buf</b>.
139 static INLINE size_t
140 _log_prefix(char *buf, size_t buf_len, int severity)
142 time_t t;
143 struct timeval now;
144 struct tm tm;
145 size_t n;
146 int r;
148 tor_gettimeofday(&now);
149 t = (time_t)now.tv_sec;
151 n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
152 r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ",
153 (int)now.tv_usec / 1000, sev_to_string(severity));
154 if (r<0)
155 return buf_len-1;
156 else
157 return n+r;
160 /** If lf refers to an actual file that we have just opened, and the file
161 * contains no data, log an "opening new logfile" message at the top.
163 * Return -1 if the log is broken and needs to be deleted, else return 0.
165 static int
166 log_tor_version(logfile_t *lf, int reset)
168 char buf[256];
169 size_t n;
170 int is_new;
172 if (!lf->needs_close)
173 /* If it doesn't get closed, it isn't really a file. */
174 return 0;
175 if (lf->is_temporary)
176 /* If it's temporary, it isn't really a file. */
177 return 0;
179 is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
181 if (reset && !is_new)
182 /* We are resetting, but we aren't at the start of the file; no
183 * need to log again. */
184 return 0;
185 n = _log_prefix(buf, sizeof(buf), LOG_NOTICE);
186 if (appname) {
187 tor_snprintf(buf+n, sizeof(buf)-n,
188 "%s opening %slog file.\n", appname, is_new?"new ":"");
189 } else {
190 tor_snprintf(buf+n, sizeof(buf)-n,
191 "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
193 if (write_all(lf->fd, buf, strlen(buf), 0) < 0) /* error */
194 return -1; /* failed */
195 return 0;
198 /** Helper: Format a log message into a fixed-sized buffer. (This is
199 * factored out of <b>logv</b> so that we never format a message more
200 * than once.) Return a pointer to the first character of the message
201 * portion of the formatted string.
203 static INLINE char *
204 format_msg(char *buf, size_t buf_len,
205 log_domain_mask_t domain, int severity, const char *funcname,
206 const char *format, va_list ap, size_t *msg_len_out)
208 size_t n;
209 int r;
210 char *end_of_prefix;
212 assert(buf_len >= 2); /* prevent integer underflow */
213 buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
215 n = _log_prefix(buf, buf_len, severity);
216 end_of_prefix = buf+n;
218 if (funcname && should_log_function_name(domain, severity)) {
219 r = tor_snprintf(buf+n, buf_len-n, "%s(): ", funcname);
220 if (r<0)
221 n = strlen(buf);
222 else
223 n += r;
226 if (domain == LD_BUG && buf_len-n > 6) {
227 memcpy(buf+n, "Bug: ", 6);
228 n += 5;
231 r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
232 if (r < 0) {
233 /* The message was too long; overwrite the end of the buffer with
234 * "[...truncated]" */
235 if (buf_len >= TRUNCATED_STR_LEN) {
236 size_t offset = buf_len-TRUNCATED_STR_LEN;
237 /* We have an extra 2 characters after buf_len to hold the \n\0,
238 * so it's safe to add 1 to the size here. */
239 strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
241 /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
242 * Since we already subtracted 2 from buf_len, this is safe.*/
243 n = buf_len;
244 } else {
245 n += r;
247 buf[n]='\n';
248 buf[n+1]='\0';
249 *msg_len_out = n+1;
250 return end_of_prefix;
253 /** Helper: sends a message to the appropriate logfiles, at loglevel
254 * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
255 * message. The actual message is derived as from tor_snprintf(format,ap).
257 static void
258 logv(int severity, log_domain_mask_t domain, const char *funcname,
259 const char *format, va_list ap)
261 char buf[10024];
262 size_t msg_len = 0;
263 int formatted = 0;
264 logfile_t *lf;
265 char *end_of_prefix=NULL;
267 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
268 assert(format);
269 /* check that severity is sane. Overrunning the masks array leads to
270 * interesting and hard to diagnose effects */
271 assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
272 LOCK_LOGS();
273 lf = logfiles;
274 while (lf) {
275 if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
276 lf = lf->next;
277 continue;
279 if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
280 lf = lf->next;
281 continue;
283 if (lf->callback && (domain & LD_NOCB)) {
284 lf = lf->next;
285 continue;
287 if (lf->seems_dead) {
288 lf = lf->next;
289 continue;
292 if (!formatted) {
293 end_of_prefix =
294 format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
295 &msg_len);
296 formatted = 1;
298 if (lf->is_syslog) {
299 #ifdef HAVE_SYSLOG_H
300 char *m = end_of_prefix;
301 #ifdef MAXLINE
302 /* Some syslog implementations have limits on the length of what you can
303 * pass them, and some very old ones do not detect overflow so well.
304 * Regrettably, they call their maximum line length MAXLINE. */
305 #if MAXLINE < 64
306 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
307 #endif
308 if (msg_len >= MAXLINE)
309 m = tor_strndup(end_of_prefix, MAXLINE-1);
310 #endif
311 syslog(severity, "%s", m);
312 #ifdef MAXLINE
313 if (m != end_of_prefix) {
314 tor_free(m);
316 #endif
317 #endif
318 lf = lf->next;
319 continue;
320 } else if (lf->callback) {
321 lf->callback(severity, domain, end_of_prefix);
322 lf = lf->next;
323 continue;
325 if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
326 /* don't log the error! mark this log entry to be blown away, and
327 * continue. */
328 lf->seems_dead = 1;
330 lf = lf->next;
332 UNLOCK_LOGS();
335 /** Output a message to the log. */
336 void
337 _log(int severity, log_domain_mask_t domain, const char *format, ...)
339 va_list ap;
340 if (severity > _log_global_min_severity)
341 return;
342 va_start(ap,format);
343 logv(severity, domain, NULL, format, ap);
344 va_end(ap);
347 /** Output a message to the log, prefixed with a function name <b>fn</b>. */
348 #ifdef __GNUC__
349 void
350 _log_fn(int severity, log_domain_mask_t domain, const char *fn,
351 const char *format, ...)
353 va_list ap;
354 if (severity > _log_global_min_severity)
355 return;
356 va_start(ap,format);
357 logv(severity, domain, fn, format, ap);
358 va_end(ap);
360 #else
361 const char *_log_fn_function_name=NULL;
362 void
363 _log_fn(int severity, log_domain_mask_t domain, const char *format, ...)
365 va_list ap;
366 if (severity > _log_global_min_severity)
367 return;
368 va_start(ap,format);
369 logv(severity, domain, _log_fn_function_name, format, ap);
370 va_end(ap);
371 _log_fn_function_name = NULL;
373 void
374 _log_debug(log_domain_mask_t domain, const char *format, ...)
376 va_list ap;
377 /* For GCC we do this check in the macro. */
378 if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity))
379 return;
380 va_start(ap,format);
381 logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap);
382 va_end(ap);
383 _log_fn_function_name = NULL;
385 void
386 _log_info(log_domain_mask_t domain, const char *format, ...)
388 va_list ap;
389 if (LOG_INFO > _log_global_min_severity)
390 return;
391 va_start(ap,format);
392 logv(LOG_INFO, domain, _log_fn_function_name, format, ap);
393 va_end(ap);
394 _log_fn_function_name = NULL;
396 void
397 _log_notice(log_domain_mask_t domain, const char *format, ...)
399 va_list ap;
400 if (LOG_NOTICE > _log_global_min_severity)
401 return;
402 va_start(ap,format);
403 logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap);
404 va_end(ap);
405 _log_fn_function_name = NULL;
407 void
408 _log_warn(log_domain_mask_t domain, const char *format, ...)
410 va_list ap;
411 if (LOG_WARN > _log_global_min_severity)
412 return;
413 va_start(ap,format);
414 logv(LOG_WARN, domain, _log_fn_function_name, format, ap);
415 va_end(ap);
416 _log_fn_function_name = NULL;
418 void
419 _log_err(log_domain_mask_t domain, const char *format, ...)
421 va_list ap;
422 if (LOG_ERR > _log_global_min_severity)
423 return;
424 va_start(ap,format);
425 logv(LOG_ERR, domain, _log_fn_function_name, format, ap);
426 va_end(ap);
427 _log_fn_function_name = NULL;
429 #endif
431 /** Free all storage held by <b>victim</b>. */
432 static void
433 log_free(logfile_t *victim)
435 tor_free(victim->severities);
436 tor_free(victim->filename);
437 tor_free(victim);
440 /** Close all open log files, and free other static memory. */
441 void
442 logs_free_all(void)
444 logfile_t *victim, *next;
445 LOCK_LOGS();
446 next = logfiles;
447 logfiles = NULL;
448 UNLOCK_LOGS();
449 while (next) {
450 victim = next;
451 next = next->next;
452 close_log(victim);
453 log_free(victim);
455 tor_free(appname);
457 /* We _could_ destroy the log mutex here, but that would screw up any logs
458 * that happened between here and the end of execution. */
461 /** Remove and free the log entry <b>victim</b> from the linked-list
462 * logfiles (it is probably present, but it might not be due to thread
463 * racing issues). After this function is called, the caller shouldn't
464 * refer to <b>victim</b> anymore.
466 * Long-term, we need to do something about races in the log subsystem
467 * in general. See bug 222 for more details.
469 static void
470 delete_log(logfile_t *victim)
472 logfile_t *tmpl;
473 if (victim == logfiles)
474 logfiles = victim->next;
475 else {
476 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
477 // tor_assert(tmpl);
478 // tor_assert(tmpl->next == victim);
479 if (!tmpl)
480 return;
481 tmpl->next = victim->next;
483 log_free(victim);
486 /** Helper: release system resources (but not memory) held by a single
487 * logfile_t. */
488 static void
489 close_log(logfile_t *victim)
491 if (victim->needs_close && victim->fd >= 0) {
492 close(victim->fd);
493 victim->fd = -1;
494 } else if (victim->is_syslog) {
495 #ifdef HAVE_SYSLOG_H
496 if (--syslog_count == 0) {
497 /* There are no other syslogs; close the logging facility. */
498 closelog();
500 #endif
504 /** Adjust a log severity configuration in <b>severity_out</b> to contain
505 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
507 void
508 set_log_severity_config(int loglevelMin, int loglevelMax,
509 log_severity_list_t *severity_out)
511 int i;
512 tor_assert(loglevelMin >= loglevelMax);
513 tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
514 tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
515 memset(severity_out, 0, sizeof(log_severity_list_t));
516 for (i = loglevelMin; i >= loglevelMax; --i) {
517 severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
521 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
522 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
523 static void
524 add_stream_log_impl(const log_severity_list_t *severity,
525 const char *name, int fd)
527 logfile_t *lf;
528 lf = tor_malloc_zero(sizeof(logfile_t));
529 lf->fd = fd;
530 lf->filename = tor_strdup(name);
531 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
532 lf->next = logfiles;
534 logfiles = lf;
535 _log_global_min_severity = get_min_log_level();
538 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
539 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
540 * not use it after calling this function. */
541 void
542 add_stream_log(const log_severity_list_t *severity,
543 const char *name, int fd)
545 LOCK_LOGS();
546 add_stream_log_impl(severity, name, fd);
547 UNLOCK_LOGS();
550 /** Initialize the global logging facility */
551 void
552 init_logging(void)
554 if (!log_mutex_initialized) {
555 tor_mutex_init(&log_mutex);
556 log_mutex_initialized = 1;
560 /** Add a log handler to receive messages during startup (before the real
561 * logs are initialized).
563 void
564 add_temp_log(int min_severity)
566 log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
567 set_log_severity_config(min_severity, LOG_ERR, s);
568 LOCK_LOGS();
569 add_stream_log_impl(s, "<temp>", fileno(stdout));
570 tor_free(s);
571 logfiles->is_temporary = 1;
572 UNLOCK_LOGS();
576 * Add a log handler to send messages in <b>severity</b>
577 * to the function <b>cb</b>.
580 add_callback_log(const log_severity_list_t *severity, log_callback cb)
582 logfile_t *lf;
583 lf = tor_malloc_zero(sizeof(logfile_t));
584 lf->fd = -1;
585 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
586 lf->filename = tor_strdup("<callback>");
587 lf->callback = cb;
588 lf->next = logfiles;
590 LOCK_LOGS();
591 logfiles = lf;
592 _log_global_min_severity = get_min_log_level();
593 UNLOCK_LOGS();
594 return 0;
597 /** Adjust the configured severity of any logs whose callback function is
598 * <b>cb</b>. */
599 void
600 change_callback_log_severity(int loglevelMin, int loglevelMax,
601 log_callback cb)
603 logfile_t *lf;
604 log_severity_list_t severities;
605 set_log_severity_config(loglevelMin, loglevelMax, &severities);
606 LOCK_LOGS();
607 for (lf = logfiles; lf; lf = lf->next) {
608 if (lf->callback == cb) {
609 memcpy(lf->severities, &severities, sizeof(severities));
612 _log_global_min_severity = get_min_log_level();
613 UNLOCK_LOGS();
616 /** Close any log handlers added by add_temp_log() or marked by
617 * mark_logs_temp(). */
618 void
619 close_temp_logs(void)
621 logfile_t *lf, **p;
623 LOCK_LOGS();
624 for (p = &logfiles; *p; ) {
625 if ((*p)->is_temporary) {
626 lf = *p;
627 /* we use *p here to handle the edge case of the head of the list */
628 *p = (*p)->next;
629 close_log(lf);
630 log_free(lf);
631 } else {
632 p = &((*p)->next);
636 _log_global_min_severity = get_min_log_level();
637 UNLOCK_LOGS();
640 /** Make all currently temporary logs (set to be closed by close_temp_logs)
641 * live again, and close all non-temporary logs. */
642 void
643 rollback_log_changes(void)
645 logfile_t *lf;
646 LOCK_LOGS();
647 for (lf = logfiles; lf; lf = lf->next)
648 lf->is_temporary = ! lf->is_temporary;
649 UNLOCK_LOGS();
650 close_temp_logs();
653 /** Configure all log handles to be closed by close_temp_logs(). */
654 void
655 mark_logs_temp(void)
657 logfile_t *lf;
658 LOCK_LOGS();
659 for (lf = logfiles; lf; lf = lf->next)
660 lf->is_temporary = 1;
661 UNLOCK_LOGS();
665 * Add a log handler to send messages to <b>filename</b>. If opening the
666 * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
669 add_file_log(const log_severity_list_t *severity, const char *filename)
671 int fd;
672 logfile_t *lf;
674 fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
675 if (fd<0)
676 return -1;
677 if (tor_fd_seekend(fd)<0)
678 return -1;
680 LOCK_LOGS();
681 add_stream_log_impl(severity, filename, fd);
682 logfiles->needs_close = 1;
683 lf = logfiles;
684 _log_global_min_severity = get_min_log_level();
685 UNLOCK_LOGS();
687 if (log_tor_version(lf, 0) < 0) {
688 LOCK_LOGS();
689 delete_log(lf);
690 UNLOCK_LOGS();
693 return 0;
696 #ifdef HAVE_SYSLOG_H
698 * Add a log handler to send messages to they system log facility.
701 add_syslog_log(const log_severity_list_t *severity)
703 logfile_t *lf;
704 if (syslog_count++ == 0)
705 /* This is the first syslog. */
706 openlog("Tor", LOG_PID | LOG_NDELAY, LOGFACILITY);
708 lf = tor_malloc_zero(sizeof(logfile_t));
709 lf->fd = -1;
710 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
711 lf->filename = tor_strdup("<syslog>");
713 lf->is_syslog = 1;
715 LOCK_LOGS();
716 lf->next = logfiles;
717 logfiles = lf;
718 _log_global_min_severity = get_min_log_level();
719 UNLOCK_LOGS();
720 return 0;
722 #endif
724 /** If <b>level</b> is a valid log severity, return the corresponding
725 * numeric value. Otherwise, return -1. */
727 parse_log_level(const char *level)
729 if (!strcasecmp(level, "err"))
730 return LOG_ERR;
731 if (!strcasecmp(level, "warn"))
732 return LOG_WARN;
733 if (!strcasecmp(level, "notice"))
734 return LOG_NOTICE;
735 if (!strcasecmp(level, "info"))
736 return LOG_INFO;
737 if (!strcasecmp(level, "debug"))
738 return LOG_DEBUG;
739 return -1;
742 /** Return the string equivalent of a given log level. */
743 const char *
744 log_level_to_string(int level)
746 return sev_to_string(level);
749 /** NULL-terminated array of names for log domains such that domain_list[dom]
750 * is a description of <b>dom</b>. */
751 static const char *domain_list[] = {
752 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
753 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
754 "OR", "EDGE", "ACCT", "HIST", NULL
757 /** Return a bitmask for the log domain for which <b>domain</b> is the name,
758 * or 0 if there is no such name. */
759 static log_domain_mask_t
760 parse_log_domain(const char *domain)
762 int i;
763 for (i=0; domain_list[i]; ++i) {
764 if (!strcasecmp(domain, domain_list[i]))
765 return (1u<<i);
767 return 0;
769 #if 0
770 /** Translate a bitmask of log domains to a string, or NULL if the bitmask
771 * is undecodable. */
772 static const char *
773 domain_to_string(log_domain_mask_t domain)
775 int bit = tor_log2(domain);
776 if ((bit == 0 && domain == 0) || bit >= N_LOGGING_DOMAINS)
777 return NULL;
778 return domain_list[bit];
780 #endif
782 /** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
783 * the end of the severityPattern. Set the value of <b>severity_out</b> to
784 * the parsed pattern. Return 0 on success, -1 on failure.
786 * The syntax for a SeverityPattern is:
787 * <pre>
788 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
789 * DomainSeverity = (DomainList SP)? SeverityRange
790 * SeverityRange = MinSeverity ("-" MaxSeverity )?
791 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
792 * DomainSpec = "*" | Domain | "~" Domain
793 * </pre>
794 * A missing MaxSeverity defaults to ERR. Severities and domains are
795 * case-insensitive. "~" indicates negation for a domain; negation happens
796 * last inside a DomainList. Only one SeverityRange without a DomainList is
797 * allowed per line.
800 parse_log_severity_config(const char **cfg_ptr,
801 log_severity_list_t *severity_out)
803 const char *cfg = *cfg_ptr;
804 int got_anything = 0;
805 int got_an_unqualified_range = 0;
806 memset(severity_out, 0, sizeof(*severity_out));
808 cfg = eat_whitespace(cfg);
809 while (*cfg) {
810 const char *dash, *space;
811 char *sev_lo, *sev_hi;
812 int low, high, i;
813 log_domain_mask_t domains = ~0u;
815 if (*cfg == '[') {
816 int err = 0;
817 char *domains_str;
818 smartlist_t *domains_list;
819 log_domain_mask_t neg_domains = 0;
820 const char *closebracket = strchr(cfg, ']');
821 if (!closebracket)
822 return -1;
823 domains = 0;
824 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
825 domains_list = smartlist_create();
826 smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
827 -1);
828 tor_free(domains_str);
829 SMARTLIST_FOREACH(domains_list, const char *, domain,
831 if (!strcmp(domain, "*")) {
832 domains = ~0u;
833 } else {
834 int d;
835 int negate=0;
836 if (*domain == '~') {
837 negate = 1;
838 ++domain;
840 d = parse_log_domain(domain);
841 if (!d) {
842 log_warn(LD_CONFIG, "No such logging domain as %s", domain);
843 err = 1;
844 } else {
845 if (negate)
846 neg_domains |= d;
847 else
848 domains |= d;
852 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
853 smartlist_free(domains_list);
854 if (err)
855 return -1;
856 domains &= ~neg_domains;
857 cfg = eat_whitespace(closebracket+1);
858 } else {
859 ++got_an_unqualified_range;
861 if (!strcasecmpstart(cfg, "file") ||
862 !strcasecmpstart(cfg, "stderr") ||
863 !strcasecmpstart(cfg, "stdout") ||
864 !strcasecmpstart(cfg, "syslog")) {
865 goto done;
867 if (got_an_unqualified_range > 1)
868 return -1;
870 space = strchr(cfg, ' ');
871 dash = strchr(cfg, '-');
872 if (!space)
873 space = strchr(cfg, '\0');
874 if (dash && dash < space) {
875 sev_lo = tor_strndup(cfg, dash-cfg);
876 sev_hi = tor_strndup(dash+1, space-(dash+1));
877 } else {
878 sev_lo = tor_strndup(cfg, space-cfg);
879 sev_hi = tor_strdup("ERR");
881 low = parse_log_level(sev_lo);
882 high = parse_log_level(sev_hi);
883 tor_free(sev_lo);
884 tor_free(sev_hi);
885 if (low == -1)
886 return -1;
887 if (high == -1)
888 return -1;
890 got_anything = 1;
891 for (i=low; i >= high; --i)
892 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
894 cfg = eat_whitespace(space);
897 done:
898 *cfg_ptr = cfg;
899 return got_anything ? 0 : -1;
902 /** Return the least severe log level that any current log is interested in. */
904 get_min_log_level(void)
906 logfile_t *lf;
907 int i;
908 int min = LOG_ERR;
909 for (lf = logfiles; lf; lf = lf->next) {
910 for (i = LOG_DEBUG; i > min; --i)
911 if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
912 min = i;
914 return min;
917 /** Switch all logs to output at most verbose level. */
918 void
919 switch_logs_debug(void)
921 logfile_t *lf;
922 int i;
923 LOCK_LOGS();
924 for (lf = logfiles; lf; lf=lf->next) {
925 for (i = LOG_DEBUG; i >= LOG_ERR; --i)
926 lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
928 _log_global_min_severity = get_min_log_level();
929 UNLOCK_LOGS();
932 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
933 /** A string which, if it appears in a libevent log, should be ignored. */
934 static const char *suppress_msg = NULL;
935 /** Callback function passed to event_set_log() so we can intercept
936 * log messages from libevent. */
937 static void
938 libevent_logging_callback(int severity, const char *msg)
940 char buf[1024];
941 size_t n;
942 if (suppress_msg && strstr(msg, suppress_msg))
943 return;
944 n = strlcpy(buf, msg, sizeof(buf));
945 if (n && n < sizeof(buf) && buf[n-1] == '\n') {
946 buf[n-1] = '\0';
948 switch (severity) {
949 case _EVENT_LOG_DEBUG:
950 log(LOG_DEBUG, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
951 break;
952 case _EVENT_LOG_MSG:
953 log(LOG_INFO, LD_NOCB|LD_NET, "Message from libevent: %s", buf);
954 break;
955 case _EVENT_LOG_WARN:
956 log(LOG_WARN, LD_NOCB|LD_GENERAL, "Warning from libevent: %s", buf);
957 break;
958 case _EVENT_LOG_ERR:
959 log(LOG_ERR, LD_NOCB|LD_GENERAL, "Error from libevent: %s", buf);
960 break;
961 default:
962 log(LOG_WARN, LD_NOCB|LD_GENERAL, "Message [%d] from libevent: %s",
963 severity, buf);
964 break;
967 /** Set hook to intercept log messages from libevent. */
968 void
969 configure_libevent_logging(void)
971 event_set_log_callback(libevent_logging_callback);
973 /** Ignore any libevent log message that contains <b>msg</b>. */
974 void
975 suppress_libevent_log_msg(const char *msg)
977 suppress_msg = msg;
979 #else
980 void
981 configure_libevent_logging(void)
984 void
985 suppress_libevent_log_msg(const char *msg)
987 (void)msg;
989 #endif
991 #if 0
992 static void
993 dump_log_info(logfile_t *lf)
995 const char *tp;
997 if (lf->filename) {
998 printf("=== log into \"%s\" (%s-%s) (%stemporary)\n", lf->filename,
999 sev_to_string(lf->min_loglevel),
1000 sev_to_string(lf->max_loglevel),
1001 lf->is_temporary?"":"not ");
1002 } else if (lf->is_syslog) {
1003 printf("=== syslog (%s-%s) (%stemporary)\n",
1004 sev_to_string(lf->min_loglevel),
1005 sev_to_string(lf->max_loglevel),
1006 lf->is_temporary?"":"not ");
1007 } else {
1008 printf("=== log (%s-%s) (%stemporary)\n",
1009 sev_to_string(lf->min_loglevel),
1010 sev_to_string(lf->max_loglevel),
1011 lf->is_temporary?"":"not ");
1015 void
1016 describe_logs(void)
1018 logfile_t *lf;
1019 printf("==== BEGIN LOGS ====\n");
1020 for (lf = logfiles; lf; lf = lf->next)
1021 dump_log_info(lf);
1022 printf("==== END LOGS ====\n");
1024 #endif