Merge branch 'maint-0.2.4' into release-0.2.4
[tor.git] / src / common / log.c
blobe196a1128703fa10c0aa9a3d46ccb7b58ce73670
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 */
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 "torlog.h"
37 #include "container.h"
39 /** @{ */
40 /** The string we stick at the end of a log message when it is too long,
41 * and its length. */
42 #define TRUNCATED_STR "[...truncated]"
43 #define TRUNCATED_STR_LEN 14
44 /** @} */
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? */
58 } logfile_t;
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)
66 switch (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. */
79 static INLINE int
80 should_log_function_name(log_domain_mask_t domain, int severity)
82 switch (severity) {
83 case LOG_DEBUG:
84 case LOG_INFO:
85 /* All debugging messages occur in interesting places. */
86 return 1;
87 case LOG_NOTICE:
88 case LOG_WARN:
89 case LOG_ERR:
90 /* We care about places where bugs occur. */
91 return (domain == LD_BUG);
92 default:
93 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
94 assert(0); return 0;
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;
108 #ifdef HAVE_SYSLOG_H
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;
112 #endif
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); \
128 STMT_END
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,
143 const char *suffix,
144 const char *format, va_list ap, size_t *msg_len_out)
145 CHECK_PRINTF(7,0);
146 static void logv(int severity, log_domain_mask_t domain, const char *funcname,
147 const char *suffix, const char *format, va_list ap)
148 CHECK_PRINTF(5,0);
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
156 * log.
158 * Tor uses this string to write the version number to the log file. */
159 void
160 log_set_application_name(const char *name)
162 tor_free(appname);
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>
170 * milliseconds. */
171 void
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>.
180 static INLINE size_t
181 log_prefix_(char *buf, size_t buf_len, int severity)
183 time_t t;
184 struct timeval now;
185 struct tm tm;
186 size_t n;
187 int r, ms;
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);
194 ms = 0;
195 } else {
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));
203 if (r<0)
204 return buf_len-1;
205 else
206 return n+r;
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.
214 static int
215 log_tor_version(logfile_t *lf, int reset)
217 char buf[256];
218 size_t n;
219 int is_new;
221 if (!lf->needs_close)
222 /* If it doesn't get closed, it isn't really a file. */
223 return 0;
224 if (lf->is_temporary)
225 /* If it's temporary, it isn't really a file. */
226 return 0;
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. */
233 return 0;
234 n = log_prefix_(buf, sizeof(buf), LOG_NOTICE);
235 if (appname) {
236 tor_snprintf(buf+n, sizeof(buf)-n,
237 "%s opening %slog file.\n", appname, is_new?"new ":"");
238 } else {
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 */
244 return 0;
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.
252 static INLINE char *
253 format_msg(char *buf, size_t buf_len,
254 log_domain_mask_t domain, int severity, const char *funcname,
255 const char *suffix,
256 const char *format, va_list ap, size_t *msg_len_out)
258 size_t n;
259 int r;
260 char *end_of_prefix;
261 char *buf_end;
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) {
271 char *cp = buf+n;
272 if (cp == buf_end) goto format_msg_no_room_for_domains;
273 *cp++ = '{';
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;
277 *cp++ = '}';
278 if (cp == buf_end) goto format_msg_no_room_for_domains;
279 *cp++ = ' ';
280 if (cp == buf_end) goto format_msg_no_room_for_domains;
281 end_of_prefix = cp;
282 n = cp-buf;
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);
291 if (r<0)
292 n = strlen(buf);
293 else
294 n += r;
297 if (domain == LD_BUG && buf_len-n > 6) {
298 memcpy(buf+n, "Bug: ", 6);
299 n += 5;
302 r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
303 if (r < 0) {
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.*/
314 n = buf_len;
315 } else {
316 n += r;
317 if (suffix) {
318 size_t suffix_len = strlen(suffix);
319 if (buf_len-n >= suffix_len) {
320 memcpy(buf+n, suffix, suffix_len);
321 n += suffix_len;
325 buf[n]='\n';
326 buf[n+1]='\0';
327 *msg_len_out = n+1;
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).
335 static void
336 logv(int severity, log_domain_mask_t domain, const char *funcname,
337 const char *suffix, const char *format, va_list ap)
339 char buf[10024];
340 size_t msg_len = 0;
341 int formatted = 0;
342 logfile_t *lf;
343 char *end_of_prefix=NULL;
344 int callbacks_deferred = 0;
346 /* Call assert, not tor_assert, since tor_assert calls log on failure. */
347 assert(format);
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);
351 LOCK_LOGS();
353 if ((! (domain & LD_NOCB)) && smartlist_len(pending_cb_messages))
354 flush_pending_log_callbacks();
356 lf = logfiles;
357 while (lf) {
358 if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
359 lf = lf->next;
360 continue;
362 if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
363 lf = lf->next;
364 continue;
366 if (lf->seems_dead) {
367 lf = lf->next;
368 continue;
371 if (!formatted) {
372 end_of_prefix =
373 format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
374 format, ap, &msg_len);
375 formatted = 1;
378 if (lf->is_syslog) {
379 #ifdef HAVE_SYSLOG_H
380 char *m = end_of_prefix;
381 #ifdef MAXLINE
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. */
385 #if MAXLINE < 64
386 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
387 #endif
388 if (msg_len >= MAXLINE)
389 m = tor_strndup(end_of_prefix, MAXLINE-1);
390 #endif
391 syslog(severity, "%s", m);
392 #ifdef MAXLINE
393 if (m != end_of_prefix) {
394 tor_free(m);
396 #endif
397 #endif
398 lf = lf->next;
399 continue;
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;
411 } else {
412 lf->callback(severity, domain, end_of_prefix);
414 lf = lf->next;
415 continue;
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
419 * continue. */
420 lf->seems_dead = 1;
422 lf = lf->next;
424 UNLOCK_LOGS();
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.
430 * */
431 void
432 tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
434 va_list ap;
435 if (severity > log_global_min_severity_)
436 return;
437 va_start(ap,format);
438 logv(severity, domain, NULL, NULL, format, ap);
439 va_end(ap);
442 /** Output a message to the log, prefixed with a function name <b>fn</b>. */
443 #ifdef __GNUC__
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. */
447 void
448 log_fn_(int severity, log_domain_mask_t domain, const char *fn,
449 const char *format, ...)
451 va_list ap;
452 if (severity > log_global_min_severity_)
453 return;
454 va_start(ap,format);
455 logv(severity, domain, fn, NULL, format, ap);
456 va_end(ap);
458 void
459 log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
460 const char *fn, const char *format, ...)
462 va_list ap;
463 char *m;
464 if (severity > log_global_min_severity_)
465 return;
466 m = rate_limit_log(ratelim, approx_time());
467 if (m == NULL)
468 return;
469 va_start(ap, format);
470 logv(severity, domain, fn, m, format, ap);
471 va_end(ap);
472 tor_free(m);
474 #else
475 /** @{ */
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;
481 void
482 log_fn_(int severity, log_domain_mask_t domain, const char *format, ...)
484 va_list ap;
485 if (severity > log_global_min_severity_)
486 return;
487 va_start(ap,format);
488 logv(severity, domain, log_fn_function_name_, NULL, format, ap);
489 va_end(ap);
490 log_fn_function_name_ = NULL;
492 void
493 log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
494 const char *format, ...)
496 va_list ap;
497 char *m;
498 if (severity > log_global_min_severity_)
499 return;
500 m = rate_limit_log(ratelim, approx_time());
501 if (m == NULL)
502 return;
503 va_start(ap, format);
504 logv(severity, domain, log_fn_function_name_, m, format, ap);
505 va_end(ap);
506 tor_free(m);
508 void
509 log_debug_(log_domain_mask_t domain, const char *format, ...)
511 va_list ap;
512 /* For GCC we do this check in the macro. */
513 if (PREDICT_LIKELY(LOG_DEBUG > log_global_min_severity_))
514 return;
515 va_start(ap,format);
516 logv(LOG_DEBUG, domain, log_fn_function_name_, NULL, format, ap);
517 va_end(ap);
518 log_fn_function_name_ = NULL;
520 void
521 log_info_(log_domain_mask_t domain, const char *format, ...)
523 va_list ap;
524 if (LOG_INFO > log_global_min_severity_)
525 return;
526 va_start(ap,format);
527 logv(LOG_INFO, domain, log_fn_function_name_, NULL, format, ap);
528 va_end(ap);
529 log_fn_function_name_ = NULL;
531 void
532 log_notice_(log_domain_mask_t domain, const char *format, ...)
534 va_list ap;
535 if (LOG_NOTICE > log_global_min_severity_)
536 return;
537 va_start(ap,format);
538 logv(LOG_NOTICE, domain, log_fn_function_name_, NULL, format, ap);
539 va_end(ap);
540 log_fn_function_name_ = NULL;
542 void
543 log_warn_(log_domain_mask_t domain, const char *format, ...)
545 va_list ap;
546 if (LOG_WARN > log_global_min_severity_)
547 return;
548 va_start(ap,format);
549 logv(LOG_WARN, domain, log_fn_function_name_, NULL, format, ap);
550 va_end(ap);
551 log_fn_function_name_ = NULL;
553 void
554 log_err_(log_domain_mask_t domain, const char *format, ...)
556 va_list ap;
557 if (LOG_ERR > log_global_min_severity_)
558 return;
559 va_start(ap,format);
560 logv(LOG_ERR, domain, log_fn_function_name_, NULL, format, ap);
561 va_end(ap);
562 log_fn_function_name_ = NULL;
564 /** @} */
565 #endif
567 /** Free all storage held by <b>victim</b>. */
568 static void
569 log_free(logfile_t *victim)
571 if (!victim)
572 return;
573 tor_free(victim->severities);
574 tor_free(victim->filename);
575 tor_free(victim);
578 /** Close all open log files, and free other static memory. */
579 void
580 logs_free_all(void)
582 logfile_t *victim, *next;
583 smartlist_t *messages;
584 LOCK_LOGS();
585 next = logfiles;
586 logfiles = NULL;
587 messages = pending_cb_messages;
588 pending_cb_messages = NULL;
589 UNLOCK_LOGS();
590 while (next) {
591 victim = next;
592 next = next->next;
593 close_log(victim);
594 log_free(victim);
596 tor_free(appname);
598 SMARTLIST_FOREACH(messages, pending_cb_message_t *, msg, {
599 tor_free(msg->msg);
600 tor_free(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.
616 static void
617 delete_log(logfile_t *victim)
619 logfile_t *tmpl;
620 if (victim == logfiles)
621 logfiles = victim->next;
622 else {
623 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
624 // tor_assert(tmpl);
625 // tor_assert(tmpl->next == victim);
626 if (!tmpl)
627 return;
628 tmpl->next = victim->next;
630 log_free(victim);
633 /** Helper: release system resources (but not memory) held by a single
634 * logfile_t. */
635 static void
636 close_log(logfile_t *victim)
638 if (victim->needs_close && victim->fd >= 0) {
639 close(victim->fd);
640 victim->fd = -1;
641 } else if (victim->is_syslog) {
642 #ifdef HAVE_SYSLOG_H
643 if (--syslog_count == 0) {
644 /* There are no other syslogs; close the logging facility. */
645 closelog();
647 #endif
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.
654 void
655 set_log_severity_config(int loglevelMin, int loglevelMax,
656 log_severity_list_t *severity_out)
658 int i;
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. */
670 static void
671 add_stream_log_impl(const log_severity_list_t *severity,
672 const char *name, int fd)
674 logfile_t *lf;
675 lf = tor_malloc_zero(sizeof(logfile_t));
676 lf->fd = fd;
677 lf->filename = tor_strdup(name);
678 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
679 lf->next = logfiles;
681 logfiles = lf;
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. */
688 void
689 add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
691 LOCK_LOGS();
692 add_stream_log_impl(severity, name, fd);
693 UNLOCK_LOGS();
696 /** Initialize the global logging facility */
697 void
698 init_logging(void)
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.
710 void
711 logs_set_domain_logging(int enabled)
713 LOCK_LOGS();
714 log_domains_are_logged = enabled;
715 UNLOCK_LOGS();
718 /** Add a log handler to receive messages during startup (before the real
719 * logs are initialized).
721 void
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);
726 LOCK_LOGS();
727 add_stream_log_impl(s, "<temp>", fileno(stdout));
728 tor_free(s);
729 logfiles->is_temporary = 1;
730 UNLOCK_LOGS();
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)
740 logfile_t *lf;
741 lf = tor_malloc_zero(sizeof(logfile_t));
742 lf->fd = -1;
743 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
744 lf->filename = tor_strdup("<callback>");
745 lf->callback = cb;
746 lf->next = logfiles;
748 LOCK_LOGS();
749 logfiles = lf;
750 log_global_min_severity_ = get_min_log_level();
751 UNLOCK_LOGS();
752 return 0;
755 /** Adjust the configured severity of any logs whose callback function is
756 * <b>cb</b>. */
757 void
758 change_callback_log_severity(int loglevelMin, int loglevelMax,
759 log_callback cb)
761 logfile_t *lf;
762 log_severity_list_t severities;
763 set_log_severity_config(loglevelMin, loglevelMax, &severities);
764 LOCK_LOGS();
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();
771 UNLOCK_LOGS();
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. */
776 void
777 flush_pending_log_callbacks(void)
779 logfile_t *lf;
780 smartlist_t *messages, *messages_tmp;
782 LOCK_LOGS();
783 if (0 == smartlist_len(pending_cb_messages)) {
784 UNLOCK_LOGS();
785 return;
788 messages = pending_cb_messages;
789 pending_cb_messages = smartlist_new();
790 do {
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)) {
797 continue;
799 lf->callback(severity, domain, msg->msg);
801 tor_free(msg->msg);
802 tor_free(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);
813 UNLOCK_LOGS();
816 /** Close any log handlers added by add_temp_log() or marked by
817 * mark_logs_temp(). */
818 void
819 close_temp_logs(void)
821 logfile_t *lf, **p;
823 LOCK_LOGS();
824 for (p = &logfiles; *p; ) {
825 if ((*p)->is_temporary) {
826 lf = *p;
827 /* we use *p here to handle the edge case of the head of the list */
828 *p = (*p)->next;
829 close_log(lf);
830 log_free(lf);
831 } else {
832 p = &((*p)->next);
836 log_global_min_severity_ = get_min_log_level();
837 UNLOCK_LOGS();
840 /** Make all currently temporary logs (set to be closed by close_temp_logs)
841 * live again, and close all non-temporary logs. */
842 void
843 rollback_log_changes(void)
845 logfile_t *lf;
846 LOCK_LOGS();
847 for (lf = logfiles; lf; lf = lf->next)
848 lf->is_temporary = ! lf->is_temporary;
849 UNLOCK_LOGS();
850 close_temp_logs();
853 /** Configure all log handles to be closed by close_temp_logs(). */
854 void
855 mark_logs_temp(void)
857 logfile_t *lf;
858 LOCK_LOGS();
859 for (lf = logfiles; lf; lf = lf->next)
860 lf->is_temporary = 1;
861 UNLOCK_LOGS();
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)
871 int fd;
872 logfile_t *lf;
874 fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
875 if (fd<0)
876 return -1;
877 if (tor_fd_seekend(fd)<0) {
878 close(fd);
879 return -1;
882 LOCK_LOGS();
883 add_stream_log_impl(severity, filename, fd);
884 logfiles->needs_close = 1;
885 lf = logfiles;
886 log_global_min_severity_ = get_min_log_level();
888 if (log_tor_version(lf, 0) < 0) {
889 delete_log(lf);
891 UNLOCK_LOGS();
893 return 0;
896 #ifdef HAVE_SYSLOG_H
898 * Add a log handler to send messages to they system log facility.
901 add_syslog_log(const log_severity_list_t *severity)
903 logfile_t *lf;
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));
909 lf->fd = -1;
910 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
911 lf->filename = tor_strdup("<syslog>");
912 lf->is_syslog = 1;
914 LOCK_LOGS();
915 lf->next = logfiles;
916 logfiles = lf;
917 log_global_min_severity_ = get_min_log_level();
918 UNLOCK_LOGS();
919 return 0;
921 #endif
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"))
929 return LOG_ERR;
930 if (!strcasecmp(level, "warn"))
931 return LOG_WARN;
932 if (!strcasecmp(level, "notice"))
933 return LOG_NOTICE;
934 if (!strcasecmp(level, "info"))
935 return LOG_INFO;
936 if (!strcasecmp(level, "debug"))
937 return LOG_DEBUG;
938 return -1;
941 /** Return the string equivalent of a given log level. */
942 const char *
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)
961 int i;
962 for (i=0; domain_list[i]; ++i) {
963 if (!strcasecmp(domain, domain_list[i]))
964 return (1u<<i);
966 return 0;
969 /** Translate a bitmask of log domains to a string. */
970 static char *
971 domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
973 char *cp = buf;
974 char *eos = buf+buflen;
976 buf[0] = '\0';
977 if (! domain)
978 return buf;
979 while (1) {
980 const char *d;
981 int bit = tor_log2(domain);
982 size_t n;
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);
989 if (n >= buflen) {
990 tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
991 return buf+strlen(buf);
993 cp += n;
994 domain &= ~(1<<bit);
996 if (domain == 0 || (eos-cp) < 2)
997 return cp;
999 memcpy(cp, ",", 2); /*Nul-terminated ,"*/
1000 cp++;
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:
1009 * <pre>
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
1015 * </pre>
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
1019 * allowed per line.
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);
1031 while (*cfg) {
1032 const char *dash, *space;
1033 char *sev_lo, *sev_hi;
1034 int low, high, i;
1035 log_domain_mask_t domains = ~0u;
1037 if (*cfg == '[') {
1038 int err = 0;
1039 char *domains_str;
1040 smartlist_t *domains_list;
1041 log_domain_mask_t neg_domains = 0;
1042 const char *closebracket = strchr(cfg, ']');
1043 if (!closebracket)
1044 return -1;
1045 domains = 0;
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,
1049 -1);
1050 tor_free(domains_str);
1051 SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
1052 if (!strcmp(domain, "*")) {
1053 domains = ~0u;
1054 } else {
1055 int d;
1056 int negate=0;
1057 if (*domain == '~') {
1058 negate = 1;
1059 ++domain;
1061 d = parse_log_domain(domain);
1062 if (!d) {
1063 log_warn(LD_CONFIG, "No such logging domain as %s", domain);
1064 err = 1;
1065 } else {
1066 if (negate)
1067 neg_domains |= d;
1068 else
1069 domains |= d;
1072 } SMARTLIST_FOREACH_END(domain);
1073 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
1074 smartlist_free(domains_list);
1075 if (err)
1076 return -1;
1077 if (domains == 0 && neg_domains)
1078 domains = ~neg_domains;
1079 else
1080 domains &= ~neg_domains;
1081 cfg = eat_whitespace(closebracket+1);
1082 } else {
1083 ++got_an_unqualified_range;
1085 if (!strcasecmpstart(cfg, "file") ||
1086 !strcasecmpstart(cfg, "stderr") ||
1087 !strcasecmpstart(cfg, "stdout") ||
1088 !strcasecmpstart(cfg, "syslog")) {
1089 goto done;
1091 if (got_an_unqualified_range > 1)
1092 return -1;
1094 space = strchr(cfg, ' ');
1095 dash = strchr(cfg, '-');
1096 if (!space)
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));
1101 } else {
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);
1107 tor_free(sev_lo);
1108 tor_free(sev_hi);
1109 if (low == -1)
1110 return -1;
1111 if (high == -1)
1112 return -1;
1114 got_anything = 1;
1115 for (i=low; i >= high; --i)
1116 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
1118 cfg = eat_whitespace(space);
1121 done:
1122 *cfg_ptr = cfg;
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)
1130 logfile_t *lf;
1131 int i;
1132 int min = LOG_ERR;
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)])
1136 min = i;
1138 return min;
1141 /** Switch all logs to output at most verbose level. */
1142 void
1143 switch_logs_debug(void)
1145 logfile_t *lf;
1146 int i;
1147 LOCK_LOGS();
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();
1153 UNLOCK_LOGS();
1156 #if 0
1157 static void
1158 dump_log_info(logfile_t *lf)
1160 const char *tp;
1162 if (lf->filename) {
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 ");
1172 } else {
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 ");
1180 void
1181 describe_logs(void)
1183 logfile_t *lf;
1184 printf("==== BEGIN LOGS ====\n");
1185 for (lf = logfiles; lf; lf = lf->next)
1186 dump_log_info(lf);
1187 printf("==== END LOGS ====\n");
1189 #endif