Fix compile warnings on Snow Leopard
[tor/rransom.git] / src / common / log.c
blob423a687a516e9ed6ac18b23b5fcb5c4f8edaa6f2
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-2009, 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->seems_dead) {
284 lf = lf->next;
285 continue;
288 if (!formatted) {
289 end_of_prefix =
290 format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
291 &msg_len);
292 formatted = 1;
294 if (lf->is_syslog) {
295 #ifdef HAVE_SYSLOG_H
296 char *m = end_of_prefix;
297 #ifdef MAXLINE
298 /* Some syslog implementations have limits on the length of what you can
299 * pass them, and some very old ones do not detect overflow so well.
300 * Regrettably, they call their maximum line length MAXLINE. */
301 #if MAXLINE < 64
302 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
303 #endif
304 if (msg_len >= MAXLINE)
305 m = tor_strndup(end_of_prefix, MAXLINE-1);
306 #endif
307 syslog(severity, "%s", m);
308 #ifdef MAXLINE
309 if (m != end_of_prefix) {
310 tor_free(m);
312 #endif
313 #endif
314 lf = lf->next;
315 continue;
316 } else if (lf->callback) {
317 lf->callback(severity, domain, end_of_prefix);
318 lf = lf->next;
319 continue;
321 if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
322 /* don't log the error! mark this log entry to be blown away, and
323 * continue. */
324 lf->seems_dead = 1;
326 lf = lf->next;
328 UNLOCK_LOGS();
331 /** Output a message to the log. */
332 void
333 _log(int severity, log_domain_mask_t domain, const char *format, ...)
335 va_list ap;
336 if (severity > _log_global_min_severity)
337 return;
338 va_start(ap,format);
339 logv(severity, domain, NULL, format, ap);
340 va_end(ap);
343 /** Output a message to the log, prefixed with a function name <b>fn</b>. */
344 #ifdef __GNUC__
345 void
346 _log_fn(int severity, log_domain_mask_t domain, const char *fn,
347 const char *format, ...)
349 va_list ap;
350 if (severity > _log_global_min_severity)
351 return;
352 va_start(ap,format);
353 logv(severity, domain, fn, format, ap);
354 va_end(ap);
356 #else
357 const char *_log_fn_function_name=NULL;
358 void
359 _log_fn(int severity, log_domain_mask_t domain, const char *format, ...)
361 va_list ap;
362 if (severity > _log_global_min_severity)
363 return;
364 va_start(ap,format);
365 logv(severity, domain, _log_fn_function_name, format, ap);
366 va_end(ap);
367 _log_fn_function_name = NULL;
369 void
370 _log_debug(log_domain_mask_t domain, const char *format, ...)
372 va_list ap;
373 /* For GCC we do this check in the macro. */
374 if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity))
375 return;
376 va_start(ap,format);
377 logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap);
378 va_end(ap);
379 _log_fn_function_name = NULL;
381 void
382 _log_info(log_domain_mask_t domain, const char *format, ...)
384 va_list ap;
385 if (LOG_INFO > _log_global_min_severity)
386 return;
387 va_start(ap,format);
388 logv(LOG_INFO, domain, _log_fn_function_name, format, ap);
389 va_end(ap);
390 _log_fn_function_name = NULL;
392 void
393 _log_notice(log_domain_mask_t domain, const char *format, ...)
395 va_list ap;
396 if (LOG_NOTICE > _log_global_min_severity)
397 return;
398 va_start(ap,format);
399 logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap);
400 va_end(ap);
401 _log_fn_function_name = NULL;
403 void
404 _log_warn(log_domain_mask_t domain, const char *format, ...)
406 va_list ap;
407 if (LOG_WARN > _log_global_min_severity)
408 return;
409 va_start(ap,format);
410 logv(LOG_WARN, domain, _log_fn_function_name, format, ap);
411 va_end(ap);
412 _log_fn_function_name = NULL;
414 void
415 _log_err(log_domain_mask_t domain, const char *format, ...)
417 va_list ap;
418 if (LOG_ERR > _log_global_min_severity)
419 return;
420 va_start(ap,format);
421 logv(LOG_ERR, domain, _log_fn_function_name, format, ap);
422 va_end(ap);
423 _log_fn_function_name = NULL;
425 #endif
427 /** Free all storage held by <b>victim</b>. */
428 static void
429 log_free(logfile_t *victim)
431 tor_free(victim->severities);
432 tor_free(victim->filename);
433 tor_free(victim);
436 /** Close all open log files, and free other static memory. */
437 void
438 logs_free_all(void)
440 logfile_t *victim, *next;
441 LOCK_LOGS();
442 next = logfiles;
443 logfiles = NULL;
444 UNLOCK_LOGS();
445 while (next) {
446 victim = next;
447 next = next->next;
448 close_log(victim);
449 log_free(victim);
451 tor_free(appname);
453 /* We _could_ destroy the log mutex here, but that would screw up any logs
454 * that happened between here and the end of execution. */
457 /** Remove and free the log entry <b>victim</b> from the linked-list
458 * logfiles (it is probably present, but it might not be due to thread
459 * racing issues). After this function is called, the caller shouldn't
460 * refer to <b>victim</b> anymore.
462 * Long-term, we need to do something about races in the log subsystem
463 * in general. See bug 222 for more details.
465 static void
466 delete_log(logfile_t *victim)
468 logfile_t *tmpl;
469 if (victim == logfiles)
470 logfiles = victim->next;
471 else {
472 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
473 // tor_assert(tmpl);
474 // tor_assert(tmpl->next == victim);
475 if (!tmpl)
476 return;
477 tmpl->next = victim->next;
479 log_free(victim);
482 /** Helper: release system resources (but not memory) held by a single
483 * logfile_t. */
484 static void
485 close_log(logfile_t *victim)
487 if (victim->needs_close && victim->fd >= 0) {
488 close(victim->fd);
489 victim->fd = -1;
490 } else if (victim->is_syslog) {
491 #ifdef HAVE_SYSLOG_H
492 if (--syslog_count == 0) {
493 /* There are no other syslogs; close the logging facility. */
494 closelog();
496 #endif
500 /** Adjust a log severity configuration in <b>severity_out</b> to contain
501 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
503 void
504 set_log_severity_config(int loglevelMin, int loglevelMax,
505 log_severity_list_t *severity_out)
507 int i;
508 tor_assert(loglevelMin >= loglevelMax);
509 tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
510 tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
511 memset(severity_out, 0, sizeof(log_severity_list_t));
512 for (i = loglevelMin; i >= loglevelMax; --i) {
513 severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
517 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
518 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
519 static void
520 add_stream_log_impl(const log_severity_list_t *severity,
521 const char *name, int fd)
523 logfile_t *lf;
524 lf = tor_malloc_zero(sizeof(logfile_t));
525 lf->fd = fd;
526 lf->filename = tor_strdup(name);
527 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
528 lf->next = logfiles;
530 logfiles = lf;
531 _log_global_min_severity = get_min_log_level();
534 /** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
535 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
536 * not use it after calling this function. */
537 void
538 add_stream_log(const log_severity_list_t *severity,
539 const char *name, int fd)
541 LOCK_LOGS();
542 add_stream_log_impl(severity, name, fd);
543 UNLOCK_LOGS();
546 /** Initialize the global logging facility */
547 void
548 init_logging(void)
550 if (!log_mutex_initialized) {
551 tor_mutex_init(&log_mutex);
552 log_mutex_initialized = 1;
556 /** Add a log handler to receive messages during startup (before the real
557 * logs are initialized).
559 void
560 add_temp_log(int min_severity)
562 log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
563 set_log_severity_config(min_severity, LOG_ERR, s);
564 LOCK_LOGS();
565 add_stream_log_impl(s, "<temp>", fileno(stdout));
566 tor_free(s);
567 logfiles->is_temporary = 1;
568 UNLOCK_LOGS();
572 * Add a log handler to send messages in <b>severity</b>
573 * to the function <b>cb</b>.
576 add_callback_log(const log_severity_list_t *severity, log_callback cb)
578 logfile_t *lf;
579 lf = tor_malloc_zero(sizeof(logfile_t));
580 lf->fd = -1;
581 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
582 lf->filename = tor_strdup("<callback>");
583 lf->callback = cb;
584 lf->next = logfiles;
586 LOCK_LOGS();
587 logfiles = lf;
588 _log_global_min_severity = get_min_log_level();
589 UNLOCK_LOGS();
590 return 0;
593 /** Adjust the configured severity of any logs whose callback function is
594 * <b>cb</b>. */
595 void
596 change_callback_log_severity(int loglevelMin, int loglevelMax,
597 log_callback cb)
599 logfile_t *lf;
600 log_severity_list_t severities;
601 set_log_severity_config(loglevelMin, loglevelMax, &severities);
602 LOCK_LOGS();
603 for (lf = logfiles; lf; lf = lf->next) {
604 if (lf->callback == cb) {
605 memcpy(lf->severities, &severities, sizeof(severities));
608 _log_global_min_severity = get_min_log_level();
609 UNLOCK_LOGS();
612 /** Close any log handlers added by add_temp_log() or marked by
613 * mark_logs_temp(). */
614 void
615 close_temp_logs(void)
617 logfile_t *lf, **p;
619 LOCK_LOGS();
620 for (p = &logfiles; *p; ) {
621 if ((*p)->is_temporary) {
622 lf = *p;
623 /* we use *p here to handle the edge case of the head of the list */
624 *p = (*p)->next;
625 close_log(lf);
626 log_free(lf);
627 } else {
628 p = &((*p)->next);
632 _log_global_min_severity = get_min_log_level();
633 UNLOCK_LOGS();
636 /** Make all currently temporary logs (set to be closed by close_temp_logs)
637 * live again, and close all non-temporary logs. */
638 void
639 rollback_log_changes(void)
641 logfile_t *lf;
642 LOCK_LOGS();
643 for (lf = logfiles; lf; lf = lf->next)
644 lf->is_temporary = ! lf->is_temporary;
645 UNLOCK_LOGS();
646 close_temp_logs();
649 /** Configure all log handles to be closed by close_temp_logs(). */
650 void
651 mark_logs_temp(void)
653 logfile_t *lf;
654 LOCK_LOGS();
655 for (lf = logfiles; lf; lf = lf->next)
656 lf->is_temporary = 1;
657 UNLOCK_LOGS();
661 * Add a log handler to send messages to <b>filename</b>. If opening the
662 * logfile fails, -1 is returned and errno is set appropriately (by open(2)).
665 add_file_log(const log_severity_list_t *severity, const char *filename)
667 int fd;
668 logfile_t *lf;
670 fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
671 if (fd<0)
672 return -1;
673 if (tor_fd_seekend(fd)<0)
674 return -1;
676 LOCK_LOGS();
677 add_stream_log_impl(severity, filename, fd);
678 logfiles->needs_close = 1;
679 lf = logfiles;
680 _log_global_min_severity = get_min_log_level();
681 UNLOCK_LOGS();
683 if (log_tor_version(lf, 0) < 0) {
684 LOCK_LOGS();
685 delete_log(lf);
686 UNLOCK_LOGS();
689 return 0;
692 #ifdef HAVE_SYSLOG_H
694 * Add a log handler to send messages to they system log facility.
697 add_syslog_log(const log_severity_list_t *severity)
699 logfile_t *lf;
700 if (syslog_count++ == 0)
701 /* This is the first syslog. */
702 openlog("Tor", LOG_PID | LOG_NDELAY, LOGFACILITY);
704 lf = tor_malloc_zero(sizeof(logfile_t));
705 lf->fd = -1;
706 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
707 lf->filename = tor_strdup("<syslog>");
709 lf->is_syslog = 1;
711 LOCK_LOGS();
712 lf->next = logfiles;
713 logfiles = lf;
714 _log_global_min_severity = get_min_log_level();
715 UNLOCK_LOGS();
716 return 0;
718 #endif
720 /** If <b>level</b> is a valid log severity, return the corresponding
721 * numeric value. Otherwise, return -1. */
723 parse_log_level(const char *level)
725 if (!strcasecmp(level, "err"))
726 return LOG_ERR;
727 if (!strcasecmp(level, "warn"))
728 return LOG_WARN;
729 if (!strcasecmp(level, "notice"))
730 return LOG_NOTICE;
731 if (!strcasecmp(level, "info"))
732 return LOG_INFO;
733 if (!strcasecmp(level, "debug"))
734 return LOG_DEBUG;
735 return -1;
738 /** Return the string equivalent of a given log level. */
739 const char *
740 log_level_to_string(int level)
742 return sev_to_string(level);
745 /** NULL-terminated array of names for log domains such that domain_list[dom]
746 * is a description of <b>dom</b>. */
747 static const char *domain_list[] = {
748 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
749 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
750 "OR", "EDGE", "ACCT", "HIST", NULL
753 /** Return a bitmask for the log domain for which <b>domain</b> is the name,
754 * or 0 if there is no such name. */
755 static log_domain_mask_t
756 parse_log_domain(const char *domain)
758 int i;
759 for (i=0; domain_list[i]; ++i) {
760 if (!strcasecmp(domain, domain_list[i]))
761 return (1u<<i);
763 return 0;
765 #if 0
766 /** Translate a bitmask of log domains to a string, or NULL if the bitmask
767 * is undecodable. */
768 static const char *
769 domain_to_string(log_domain_mask_t domain)
771 int bit = tor_log2(domain);
772 if ((bit == 0 && domain == 0) || bit >= N_LOGGING_DOMAINS)
773 return NULL;
774 return domain_list[bit];
776 #endif
778 /** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
779 * the end of the severityPattern. Set the value of <b>severity_out</b> to
780 * the parsed pattern. Return 0 on success, -1 on failure.
782 * The syntax for a SeverityPattern is:
783 * <pre>
784 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
785 * DomainSeverity = (DomainList SP)? SeverityRange
786 * SeverityRange = MinSeverity ("-" MaxSeverity )?
787 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
788 * DomainSpec = "*" | Domain | "~" Domain
789 * </pre>
790 * A missing MaxSeverity defaults to ERR. Severities and domains are
791 * case-insensitive. "~" indicates negation for a domain; negation happens
792 * last inside a DomainList. Only one SeverityRange without a DomainList is
793 * allowed per line.
796 parse_log_severity_config(const char **cfg_ptr,
797 log_severity_list_t *severity_out)
799 const char *cfg = *cfg_ptr;
800 int got_anything = 0;
801 int got_an_unqualified_range = 0;
802 memset(severity_out, 0, sizeof(*severity_out));
804 cfg = eat_whitespace(cfg);
805 while (*cfg) {
806 const char *dash, *space;
807 char *sev_lo, *sev_hi;
808 int low, high, i;
809 log_domain_mask_t domains = ~0u;
811 if (*cfg == '[') {
812 int err = 0;
813 char *domains_str;
814 smartlist_t *domains_list;
815 log_domain_mask_t neg_domains = 0;
816 const char *closebracket = strchr(cfg, ']');
817 if (!closebracket)
818 return -1;
819 domains = 0;
820 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
821 domains_list = smartlist_create();
822 smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
823 -1);
824 tor_free(domains_str);
825 SMARTLIST_FOREACH(domains_list, const char *, domain,
827 if (!strcmp(domain, "*")) {
828 domains = ~0u;
829 } else {
830 int d;
831 int negate=0;
832 if (*domain == '~') {
833 negate = 1;
834 ++domain;
836 d = parse_log_domain(domain);
837 if (!d) {
838 log_warn(LD_CONFIG, "No such logging domain as %s", domain);
839 err = 1;
840 } else {
841 if (negate)
842 neg_domains |= d;
843 else
844 domains |= d;
848 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
849 smartlist_free(domains_list);
850 if (err)
851 return -1;
852 domains &= ~neg_domains;
853 cfg = eat_whitespace(closebracket+1);
854 } else {
855 ++got_an_unqualified_range;
857 if (!strcasecmpstart(cfg, "file") ||
858 !strcasecmpstart(cfg, "stderr") ||
859 !strcasecmpstart(cfg, "stdout") ||
860 !strcasecmpstart(cfg, "syslog")) {
861 goto done;
863 if (got_an_unqualified_range > 1)
864 return -1;
866 space = strchr(cfg, ' ');
867 dash = strchr(cfg, '-');
868 if (!space)
869 space = strchr(cfg, '\0');
870 if (dash && dash < space) {
871 sev_lo = tor_strndup(cfg, dash-cfg);
872 sev_hi = tor_strndup(dash+1, space-(dash+1));
873 } else {
874 sev_lo = tor_strndup(cfg, space-cfg);
875 sev_hi = tor_strdup("ERR");
877 low = parse_log_level(sev_lo);
878 high = parse_log_level(sev_hi);
879 tor_free(sev_lo);
880 tor_free(sev_hi);
881 if (low == -1)
882 return -1;
883 if (high == -1)
884 return -1;
886 got_anything = 1;
887 for (i=low; i >= high; --i)
888 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
890 cfg = eat_whitespace(space);
893 done:
894 *cfg_ptr = cfg;
895 return got_anything ? 0 : -1;
898 /** Return the least severe log level that any current log is interested in. */
900 get_min_log_level(void)
902 logfile_t *lf;
903 int i;
904 int min = LOG_ERR;
905 for (lf = logfiles; lf; lf = lf->next) {
906 for (i = LOG_DEBUG; i > min; --i)
907 if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
908 min = i;
910 return min;
913 /** Switch all logs to output at most verbose level. */
914 void
915 switch_logs_debug(void)
917 logfile_t *lf;
918 int i;
919 LOCK_LOGS();
920 for (lf = logfiles; lf; lf=lf->next) {
921 for (i = LOG_DEBUG; i >= LOG_ERR; --i)
922 lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
924 _log_global_min_severity = get_min_log_level();
925 UNLOCK_LOGS();
928 #ifdef HAVE_EVENT_SET_LOG_CALLBACK
929 /** A string which, if it appears in a libevent log, should be ignored. */
930 static const char *suppress_msg = NULL;
931 /** Callback function passed to event_set_log() so we can intercept
932 * log messages from libevent. */
933 static void
934 libevent_logging_callback(int severity, const char *msg)
936 char buf[1024];
937 size_t n;
938 if (suppress_msg && strstr(msg, suppress_msg))
939 return;
940 n = strlcpy(buf, msg, sizeof(buf));
941 if (n && n < sizeof(buf) && buf[n-1] == '\n') {
942 buf[n-1] = '\0';
944 switch (severity) {
945 case _EVENT_LOG_DEBUG:
946 log(LOG_DEBUG, LD_NET, "Message from libevent: %s", buf);
947 break;
948 case _EVENT_LOG_MSG:
949 log(LOG_INFO, LD_NET, "Message from libevent: %s", buf);
950 break;
951 case _EVENT_LOG_WARN:
952 log(LOG_WARN, LD_GENERAL, "Warning from libevent: %s", buf);
953 break;
954 case _EVENT_LOG_ERR:
955 log(LOG_ERR, LD_GENERAL, "Error from libevent: %s", buf);
956 break;
957 default:
958 log(LOG_WARN, LD_GENERAL, "Message [%d] from libevent: %s",
959 severity, buf);
960 break;
963 /** Set hook to intercept log messages from libevent. */
964 void
965 configure_libevent_logging(void)
967 event_set_log_callback(libevent_logging_callback);
969 /** Ignore any libevent log message that contains <b>msg</b>. */
970 void
971 suppress_libevent_log_msg(const char *msg)
973 suppress_msg = msg;
975 #else
976 void
977 configure_libevent_logging(void)
980 void
981 suppress_libevent_log_msg(const char *msg)
983 (void)msg;
985 #endif
987 #if 0
988 static void
989 dump_log_info(logfile_t *lf)
991 const char *tp;
993 if (lf->filename) {
994 printf("=== log into \"%s\" (%s-%s) (%stemporary)\n", lf->filename,
995 sev_to_string(lf->min_loglevel),
996 sev_to_string(lf->max_loglevel),
997 lf->is_temporary?"":"not ");
998 } else if (lf->is_syslog) {
999 printf("=== syslog (%s-%s) (%stemporary)\n",
1000 sev_to_string(lf->min_loglevel),
1001 sev_to_string(lf->max_loglevel),
1002 lf->is_temporary?"":"not ");
1003 } else {
1004 printf("=== log (%s-%s) (%stemporary)\n",
1005 sev_to_string(lf->min_loglevel),
1006 sev_to_string(lf->max_loglevel),
1007 lf->is_temporary?"":"not ");
1011 void
1012 describe_logs(void)
1014 logfile_t *lf;
1015 printf("==== BEGIN LOGS ====\n");
1016 for (lf = logfiles; lf; lf = lf->next)
1017 dump_log_info(lf);
1018 printf("==== END LOGS ====\n");
1020 #endif