Tor 0.4.9.0-alpha-dev
log.c
Go to the documentation of this file.
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-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * \file log.c
9 * \brief Functions to send messages to log files or the console.
10 **/
11
12#include "orconfig.h"
13#include <stdarg.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#ifdef HAVE_SYS_TIME_H
18#include <sys/time.h>
19#endif
20#ifdef HAVE_TIME_H
21#include <time.h>
22#endif
23#ifdef HAVE_UNISTD_H
24#include <unistd.h>
25#endif
26#ifdef HAVE_SYS_TYPES_H
27#include <sys/types.h>
28#endif
29#ifdef HAVE_FCNTL_H
30#include <fcntl.h>
31#endif
32
33#define LOG_PRIVATE
34#include "lib/log/log.h"
35#include "lib/log/log_sys.h"
36#include "lib/log/util_bug.h"
38#include "lib/log/ratelim.h"
43#include "lib/err/torerr.h"
44#include "lib/intmath/bits.h"
46#include "lib/string/printf.h"
47#include "lib/malloc/malloc.h"
52#include "lib/fdio/fdio.h"
53#include "lib/cc/ctassert.h"
54
55/** @{ */
56/** The string we stick at the end of a log message when it is too long,
57 * and its length. */
58#define TRUNCATED_STR "[...truncated]"
59#define TRUNCATED_STR_LEN 14
60/** @} */
61
62/** Defining compile-time constants for Tor log levels (used by the Rust
63 * log wrapper at src/rust/tor_log) */
64const int LOG_WARN_ = LOG_WARN;
65const int LOG_NOTICE_ = LOG_NOTICE;
66const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
67const log_domain_mask_t LD_NET_ = LD_NET;
68
69/** Information for a single logfile; only used in log.c */
70typedef struct logfile_t {
71 struct logfile_t *next; /**< Next logfile_t in the linked list. */
72 char *filename; /**< Filename to open. */
73 int fd; /**< fd to receive log messages, or -1 for none. */
74 int seems_dead; /**< Boolean: true if the stream seems to be kaput. */
75 int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
76 int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
77 int is_syslog; /**< Boolean: send messages to syslog. */
78 log_callback callback; /**< If not NULL, send messages to this function. */
79 log_severity_list_t *severities; /**< Which severity of messages should we
80 * log for each log domain? */
81} logfile_t;
82
83static void log_free_(logfile_t *victim);
84#define log_free(lg) \
85 FREE_AND_NULL(logfile_t, log_free_, (lg))
86
87/** Helper: map a log severity to descriptive string. */
88static inline const char *
89sev_to_string(int severity)
90{
91 switch (severity) {
92 case LOG_DEBUG: return "debug";
93 case LOG_INFO: return "info";
94 case LOG_NOTICE: return "notice";
95 case LOG_WARN: return "warn";
96 case LOG_ERR: return "err";
97 default: /* Call raw_assert, not tor_assert, since tor_assert
98 * calls log on failure. */
99 raw_assert_unreached(); return "UNKNOWN"; // LCOV_EXCL_LINE
100 }
101}
102
103/** Helper: decide whether to include the function name in the log message. */
104static inline int
106{
107 switch (severity) {
108 case LOG_DEBUG:
109 case LOG_INFO:
110 /* All debugging messages occur in interesting places. */
111 return (domain & LD_NOFUNCNAME) == 0;
112 case LOG_NOTICE:
113 case LOG_WARN:
114 case LOG_ERR:
115 /* We care about places where bugs occur. */
116 return (domain & (LD_BUG|LD_NOFUNCNAME)) == LD_BUG;
117 default:
118 /* Call raw_assert, not tor_assert, since tor_assert calls
119 * log on failure. */
120 raw_assert(0); return 0; // LCOV_EXCL_LINE
121 }
122}
123
124/** A mutex to guard changes to logfiles and logging. */
126/** True iff we have initialized log_mutex */
128
129/** Linked list of logfile_t. */
130static logfile_t *logfiles = NULL;
131/** Boolean: do we report logging domains? */
133
134#ifdef HAVE_SYSLOG_H
135/** The number of open syslog log handlers that we have. When this reaches 0,
136 * we can close our connection to the syslog facility. */
137static int syslog_count = 0;
138#endif
139
140/** Represents a log message that we are going to send to callback-driven
141 * loggers once we can do so in a non-reentrant way. */
142typedef struct pending_log_message_t {
143 int severity; /**< The severity of the message */
144 log_domain_mask_t domain; /**< The domain of the message */
145 char *fullmsg; /**< The message, with all decorations */
146 char *msg; /**< The content of the message */
148
149/** Log messages waiting to be replayed onto callback-based logs */
151
152/** Callback to invoke when pending_cb_messages becomes nonempty. */
153static pending_callback_callback pending_cb_cb = NULL;
154
155/** Log messages waiting to be replayed once the logging system is initialized.
156 */
158
159/** Number of bytes of messages queued in pending_startup_messages. (This is
160 * the length of the messages, not the number of bytes used to store
161 * them.) */
163
164/** True iff we should store messages while waiting for the logs to get
165 * configured. */
167
168/** True iff __PRETTY_FUNCTION__ includes parenthesized arguments. */
169static int pretty_fn_has_parens = 0;
170
171/** Don't store more than this many bytes of messages while waiting for the
172 * logs to get configured. */
173#define MAX_STARTUP_MSG_LEN (1<<16)
174
175/** Lock the log_mutex to prevent others from changing the logfile_t list */
176#define LOCK_LOGS() STMT_BEGIN \
177 raw_assert(log_mutex_initialized); \
178 tor_mutex_acquire(&log_mutex); \
179 STMT_END
180/** Unlock the log_mutex */
181#define UNLOCK_LOGS() STMT_BEGIN \
182 raw_assert(log_mutex_initialized); \
183 tor_mutex_release(&log_mutex); \
184 STMT_END
185
186/** What's the lowest log level anybody cares about? Checking this lets us
187 * bail out early from log_debug if we aren't debugging. */
189
190static void delete_log(logfile_t *victim);
191static void close_log(logfile_t *victim);
192static void close_log_sigsafe(logfile_t *victim);
193
194static char *domain_to_string(log_domain_mask_t domain,
195 char *buf, size_t buflen);
196static inline char *format_msg(char *buf, size_t buf_len,
197 log_domain_mask_t domain, int severity, const char *funcname,
198 const char *suffix,
199 const char *format, va_list ap, size_t *msg_len_out)
200 CHECK_PRINTF(7,0);
201
202/** Name of the application: used to generate the message we write at the
203 * start of each new log. */
204static char *appname = NULL;
205
206/** Set the "application name" for the logs to <b>name</b>: we'll use this
207 * name in the message we write when starting up, and at the start of each new
208 * log.
209 *
210 * Tor uses this string to write the version number to the log file. */
211void
213{
215 appname = name ? tor_strdup(name) : NULL;
216}
217
218/** Return true if some of the running logs might be interested in a log
219 * message of the given severity in the given domains. If this function
220 * returns true, the log message might be ignored anyway, but if it returns
221 * false, it is definitely_ safe not to log the message. */
222int
224{
225 (void) domain;
226 return (severity <= log_global_min_severity_);
227}
228
229/**
230 * As tor_log, but takes an optional function name, and does not treat its
231 * <b>string</b> as a printf format.
232 *
233 * For use by Rust integration.
234 */
235void
237 const char *function, const char *string)
238{
239 log_fn_(severity, domain, function, "%s", string);
240}
241
242/** Log time granularity in milliseconds. */
243static int log_time_granularity = 1;
244
245/** Define log time granularity for all logs to be <b>granularity_msec</b>
246 * milliseconds. */
247MOCK_IMPL(void,
248set_log_time_granularity,(int granularity_msec))
249{
250 log_time_granularity = granularity_msec;
251 tor_log_sigsafe_err_set_granularity(granularity_msec);
252}
253
254/** Helper: Write the standard prefix for log lines to a
255 * <b>buf_len</b> character buffer in <b>buf</b>.
256 */
257static inline size_t
258log_prefix_(char *buf, size_t buf_len, int severity)
259{
260 time_t t;
261 struct timeval now;
262 struct tm tm;
263 size_t n;
264 int r, ms;
265
266 tor_gettimeofday(&now);
267 t = (time_t)now.tv_sec;
268 ms = (int)now.tv_usec / 1000;
269 if (log_time_granularity >= 1000) {
270 t -= t % (log_time_granularity / 1000);
271 ms = 0;
272 } else {
273 ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
274 }
275
276 n = strftime(buf, buf_len, "%b %d %H:%M:%S",
277 tor_localtime_r_msg(&t, &tm, NULL));
278 r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
279 sev_to_string(severity));
280
281 if (r<0)
282 return buf_len-1;
283 else
284 return n+r;
285}
286
287/** If lf refers to an actual file that we have just opened, and the file
288 * contains no data, log an "opening new logfile" message at the top.
289 *
290 * Return -1 if the log is broken and needs to be deleted, else return 0.
291 */
292static int
294{
295 char buf[256];
296 size_t n;
297 int is_new;
298
299 if (!lf->needs_close)
300 /* If it doesn't get closed, it isn't really a file. */
301 return 0;
302 if (lf->is_temporary)
303 /* If it's temporary, it isn't really a file. */
304 return 0;
305
306 is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
307
308 if (reset && !is_new)
309 /* We are resetting, but we aren't at the start of the file; no
310 * need to log again. */
311 return 0;
312 n = log_prefix_(buf, sizeof(buf), LOG_NOTICE);
313 if (appname) {
314 tor_snprintf(buf+n, sizeof(buf)-n,
315 "%s opening %slog file.\n", appname, is_new?"new ":"");
316 } else {
317 tor_snprintf(buf+n, sizeof(buf)-n,
318 "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
319 }
320 if (write_all_to_fd_minimal(lf->fd, buf, strlen(buf)) < 0) /* error */
321 return -1; /* failed */
322 return 0;
323}
324
325/** Helper: Format a log message into a fixed-sized buffer. (This is
326 * factored out of <b>logv</b> so that we never format a message more
327 * than once.) Return a pointer to the first character of the message
328 * portion of the formatted string.
329 */
330static inline char *
331format_msg(char *buf, size_t buf_len,
332 log_domain_mask_t domain, int severity, const char *funcname,
333 const char *suffix,
334 const char *format, va_list ap, size_t *msg_len_out)
335{
336 size_t n;
337 int r;
338 char *end_of_prefix;
339 char *buf_end;
340
341 raw_assert(buf_len >= 16); /* prevent integer underflow and stupidity */
342 buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
343 buf_end = buf+buf_len; /* point *after* the last char we can write to */
344
345 n = log_prefix_(buf, buf_len, severity);
346 end_of_prefix = buf+n;
347
349 char *cp = buf+n;
350 if (cp == buf_end) goto format_msg_no_room_for_domains;
351 *cp++ = '{';
352 if (cp == buf_end) goto format_msg_no_room_for_domains;
353 cp = domain_to_string(domain, cp, (buf+buf_len-cp));
354 if (cp == buf_end) goto format_msg_no_room_for_domains;
355 *cp++ = '}';
356 if (cp == buf_end) goto format_msg_no_room_for_domains;
357 *cp++ = ' ';
358 if (cp == buf_end) goto format_msg_no_room_for_domains;
359 end_of_prefix = cp;
360 n = cp-buf;
361 format_msg_no_room_for_domains:
362 /* This will leave end_of_prefix and n unchanged, and thus cause
363 * whatever log domain string we had written to be clobbered. */
364 ;
365 }
366
367 if (funcname && should_log_function_name(domain, severity)) {
368 r = tor_snprintf(buf+n, buf_len-n,
369 pretty_fn_has_parens ? "%s: " : "%s(): ",
370 funcname);
371 if (r<0)
372 n = strlen(buf);
373 else
374 n += r;
375 }
376
377 if (domain == LD_BUG && buf_len-n > 6) {
378 memcpy(buf+n, "Bug: ", 6);
379 n += 5;
380 }
381
382 r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
383 if (r < 0) {
384 /* The message was too long; overwrite the end of the buffer with
385 * "[...truncated]" */
386 if (buf_len >= TRUNCATED_STR_LEN) {
387 size_t offset = buf_len-TRUNCATED_STR_LEN;
388 /* We have an extra 2 characters after buf_len to hold the \n\0,
389 * so it's safe to add 1 to the size here. */
390 strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
391 }
392 /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
393 * Since we already subtracted 2 from buf_len, this is safe.*/
394 n = buf_len;
395 } else {
396 n += r;
397 if (suffix) {
398 size_t suffix_len = strlen(suffix);
399 if (buf_len-n >= suffix_len) {
400 memcpy(buf+n, suffix, suffix_len);
401 n += suffix_len;
402 }
403 }
404 }
405
406 if (domain == LD_BUG &&
407 buf_len - n > strlen(tor_bug_suffix)+1) {
408 memcpy(buf+n, tor_bug_suffix, strlen(tor_bug_suffix));
409 n += strlen(tor_bug_suffix);
410 }
411
412 buf[n]='\n';
413 buf[n+1]='\0';
414 *msg_len_out = n+1;
415 return end_of_prefix;
416}
417
418/* Create a new pending_log_message_t with appropriate values */
420pending_log_message_new(int severity, log_domain_mask_t domain,
421 const char *fullmsg, const char *shortmsg)
422{
423 pending_log_message_t *m = tor_malloc(sizeof(pending_log_message_t));
424 m->severity = severity;
425 m->domain = domain;
426 m->fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
427 m->msg = tor_strdup(shortmsg);
428 return m;
429}
430
431#define pending_log_message_free(msg) \
432 FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
433
434/** Release all storage held by <b>msg</b>. */
435static void
437{
438 if (!msg)
439 return;
440 tor_free(msg->msg);
441 tor_free(msg->fullmsg);
442 tor_free(msg);
443}
444
445/** Helper function: returns true iff the log file, given in <b>lf</b>, is
446 * handled externally via the system log API, or is an
447 * external callback function. */
448static inline int
450{
451 raw_assert(lf);
452 return lf->is_syslog || lf->callback;
453}
454
455/** Return true iff <b>lf</b> would like to receive a message with the
456 * specified <b>severity</b> in the specified <b>domain</b>.
457 */
458static inline int
459logfile_wants_message(const logfile_t *lf, int severity,
460 log_domain_mask_t domain)
461{
462 if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
463 return 0;
464 }
465 if (! (lf->fd >= 0 || logfile_is_external(lf))) {
466 return 0;
467 }
468 if (lf->seems_dead) {
469 return 0;
470 }
471
472 return 1;
473}
474
475/** Send a message to <b>lf</b>. The full message, with time prefix and
476 * severity, is in <b>buf</b>. The message itself is in
477 * <b>msg_after_prefix</b>. If <b>callbacks_deferred</b> points to true, then
478 * we already deferred this message for pending callbacks and don't need to do
479 * it again. Otherwise, if we need to do it, do it, and set
480 * <b>callbacks_deferred</b> to 1. */
481static inline void
482logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
483 const char *msg_after_prefix, log_domain_mask_t domain,
484 int severity, int *callbacks_deferred)
485{
486
487 if (lf->is_syslog) {
488#ifdef HAVE_SYSLOG_H
489#ifdef MAXLINE
490 /* Some syslog implementations have limits on the length of what you can
491 * pass them, and some very old ones do not detect overflow so well.
492 * Regrettably, they call their maximum line length MAXLINE. */
493#if MAXLINE < 64
494#warning "MAXLINE is very low; it might not be from syslog.h."
495#endif
496 char *m = msg_after_prefix;
497 if (msg_len >= MAXLINE)
498 m = tor_strndup(msg_after_prefix, MAXLINE-1);
499 syslog(severity, "%s", m);
500 if (m != msg_after_prefix) {
501 tor_free(m);
502 }
503#else /* !defined(MAXLINE) */
504 /* We have syslog but not MAXLINE. That's promising! */
505 syslog(severity, "%s", msg_after_prefix);
506#endif /* defined(MAXLINE) */
507#endif /* defined(HAVE_SYSLOG_H) */
508 } else if (lf->callback) {
509 if (domain & LD_NOCB) {
510 if (!*callbacks_deferred && pending_cb_messages) {
512 pending_log_message_new(severity,domain,NULL,msg_after_prefix));
513 *callbacks_deferred = 1;
514 if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
516 }
517 }
518 } else {
519 lf->callback(severity, domain, msg_after_prefix);
520 }
521 } else {
522 if (write_all_to_fd_minimal(lf->fd, buf, msg_len) < 0) { /* error */
523 /* don't log the error! mark this log entry to be blown away, and
524 * continue. */
525 lf->seems_dead = 1;
526 }
527 }
528}
529
530/** Helper: sends a message to the appropriate logfiles, at loglevel
531 * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
532 * message. The actual message is derived as from tor_snprintf(format,ap).
533 */
534MOCK_IMPL(STATIC void,
535logv,(int severity, log_domain_mask_t domain, const char *funcname,
536 const char *suffix, const char *format, va_list ap))
537{
538 char buf[10240];
539 size_t msg_len = 0;
540 int formatted = 0;
541 logfile_t *lf;
542 char *end_of_prefix=NULL;
543 int callbacks_deferred = 0;
544
545 /* Call raw_assert, not tor_assert, since tor_assert calls log on failure. */
546 raw_assert(format);
547 /* check that severity is sane. Overrunning the masks array leads to
548 * interesting and hard to diagnose effects */
549 raw_assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
550
551 LOCK_LOGS();
552
553 if ((! (domain & LD_NOCB)) && pending_cb_messages
554 && smartlist_len(pending_cb_messages))
556
559 end_of_prefix =
560 format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
561 format, ap, &msg_len);
562 formatted = 1;
563
565 pending_log_message_new(severity,domain,buf,end_of_prefix));
567 }
568
569 for (lf = logfiles; lf; lf = lf->next) {
570 if (! logfile_wants_message(lf, severity, domain))
571 continue;
572
573 if (!formatted) {
574 end_of_prefix =
575 format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
576 format, ap, &msg_len);
577 formatted = 1;
578 }
579
580 logfile_deliver(lf, buf, msg_len, end_of_prefix, domain, severity,
581 &callbacks_deferred);
582 }
583 UNLOCK_LOGS();
584}
585
586/** Output a message to the log. It gets logged to all logfiles that
587 * care about messages with <b>severity</b> in <b>domain</b>. The content
588 * is formatted printf-style based on <b>format</b> and extra arguments.
589 * */
590void
591tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
592{
593 va_list ap;
594
595 /* check that domain is composed of known domains and flags */
596 raw_assert((domain & (LD_ALL_DOMAINS|LD_ALL_FLAGS)) == domain);
597
598 if (severity > log_global_min_severity_)
599 return;
600 va_start(ap,format);
601#ifdef TOR_UNIT_TESTS
602 if (domain & LD_NO_MOCK)
603 logv__real(severity, domain, NULL, NULL, format, ap);
604 else
605#endif
606 logv(severity, domain, NULL, NULL, format, ap);
607 va_end(ap);
608}
609
610/** Helper function; return true iff the <b>n</b>-element array <b>array</b>
611 * contains <b>item</b>. */
612static int
613int_array_contains(const int *array, int n, int item)
614{
615 int j;
616 for (j = 0; j < n; ++j) {
617 if (array[j] == item)
618 return 1;
619 }
620 return 0;
621}
622
623/** Function to call whenever the list of logs changes to get ready to log
624 * from signal handlers. */
625void
627{
628 const logfile_t *lf;
629 int found_real_stderr = 0;
630
631 /* The fds are the file descriptors of tor's stdout, stderr, and file
632 * logs. The log and err modules flush these fds during their shutdowns. */
634 int n_fds;
635
636 LOCK_LOGS();
637 /* Reserve the first one for stderr. This is safe because when we daemonize,
638 * we dup2 /dev/null to stderr. */
639 fds[0] = STDERR_FILENO;
640 n_fds = 1;
641
642 for (lf = logfiles; lf; lf = lf->next) {
643 /* Don't try callback to the control port, syslogs, or any
644 * other non-file descriptor log: We can't call arbitrary functions from a
645 * signal handler.
646 */
647 if (lf->is_temporary || logfile_is_external(lf)
648 || lf->seems_dead || lf->fd < 0)
649 continue;
650 if (lf->severities->masks[SEVERITY_MASK_IDX(LOG_ERR)] &
651 (LD_BUG|LD_GENERAL)) {
652 if (lf->fd == STDERR_FILENO)
653 found_real_stderr = 1;
654 /* Avoid duplicates by checking the log module fd against fds */
655 if (int_array_contains(fds, n_fds, lf->fd))
656 continue;
657 /* Update fds using the log module's fd */
658 fds[n_fds] = lf->fd;
659 n_fds++;
660 if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
661 break;
662 }
663 }
664
665 if (!found_real_stderr &&
666 int_array_contains(fds, n_fds, STDOUT_FILENO)) {
667 /* Don't use a virtual stderr when we're also logging to stdout.
668 * If we reached max_fds logs, we'll now have (max_fds - 1) logs.
669 * That's ok, max_fds is large enough that most tor instances don't exceed
670 * it. */
671 raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
672 --n_fds;
673 fds[0] = fds[n_fds];
674 }
675
676 UNLOCK_LOGS();
677
678 tor_log_set_sigsafe_err_fds(fds, n_fds);
679}
680
681/** Add to <b>out</b> a copy of every currently configured log file name. Used
682 * to enable access to these filenames with the sandbox code. */
683void
685{
686 logfile_t *lf;
687 raw_assert(out);
688
689 LOCK_LOGS();
690
691 for (lf = logfiles; lf; lf = lf->next) {
692 if (lf->is_temporary || logfile_is_external(lf))
693 continue;
694 if (lf->filename == NULL)
695 continue;
697 }
698
699 UNLOCK_LOGS();
700}
701
702/** Implementation of the log_fn backend, used when we have
703 * variadic macros. All arguments are as for log_fn, except for
704 * <b>fn</b>, which is the name of the calling function. */
705void
706log_fn_(int severity, log_domain_mask_t domain, const char *fn,
707 const char *format, ...)
708{
709 va_list ap;
710 if (severity > log_global_min_severity_)
711 return;
712 va_start(ap,format);
713 logv(severity, domain, fn, NULL, format, ap);
714 va_end(ap);
715}
716void
717log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
718 const char *fn, const char *format, ...)
719{
720 va_list ap;
721 char *m;
722 if (severity > log_global_min_severity_)
723 return;
724 m = rate_limit_log(ratelim, approx_time());
725 if (m == NULL)
726 return;
727 va_start(ap, format);
728 logv(severity, domain, fn, m, format, ap);
729 va_end(ap);
730 tor_free(m);
731}
732
733/** Free all storage held by <b>victim</b>. */
734static void
736{
737 if (!victim)
738 return;
739 tor_free(victim->severities);
740 tor_free(victim->filename);
741 tor_free(victim);
742}
743
744/** Close all open log files, and free other static memory. */
745void
747{
748 logfile_t *victim, *next;
749 smartlist_t *messages, *messages2;
750 LOCK_LOGS();
751 next = logfiles;
752 logfiles = NULL;
753 messages = pending_cb_messages;
754 pending_cb_messages = NULL;
755 pending_cb_cb = NULL;
756 messages2 = pending_startup_messages;
758 UNLOCK_LOGS();
759 while (next) {
760 victim = next;
761 next = next->next;
762 close_log(victim);
763 log_free(victim);
764 }
766
767 SMARTLIST_FOREACH(messages, pending_log_message_t *, msg, {
768 pending_log_message_free(msg);
769 });
770 smartlist_free(messages);
771
772 if (messages2) {
773 SMARTLIST_FOREACH(messages2, pending_log_message_t *, msg, {
774 pending_log_message_free(msg);
775 });
776 smartlist_free(messages2);
777 }
778
779 /* We _could_ destroy the log mutex here, but that would screw up any logs
780 * that happened between here and the end of execution.
781 * If tor is re-initialized, log_mutex_initialized will still be 1. So we
782 * won't trigger any undefined behaviour by trying to re-initialize the
783 * log mutex. */
784}
785
786/** Flush the signal-safe log files.
787 *
788 * This function is safe to call from a signal handler. It is currently called
789 * by the BUG() macros, when terminating the process on an abnormal condition.
790 */
791void
793{
794 /* If we don't have fsync() in unistd.h, we can't flush the logs. */
795#ifdef HAVE_FSYNC
796 logfile_t *victim, *next;
797 /* We can't LOCK_LOGS() in a signal handler, because it may call
798 * signal-unsafe functions. And we can't deallocate memory, either. */
799 next = logfiles;
800 logfiles = NULL;
801 while (next) {
802 victim = next;
803 next = next->next;
804 if (victim->needs_close) {
805 /* We can't do anything useful if the flush fails. */
806 (void)fsync(victim->fd);
807 }
808 }
809#endif /* defined(HAVE_FSYNC) */
810}
811
812/** Remove and free the log entry <b>victim</b> from the linked-list
813 * logfiles (it is probably present, but it might not be due to thread
814 * racing issues). After this function is called, the caller shouldn't
815 * refer to <b>victim</b> anymore.
816 */
817static void
819{
820 logfile_t *tmpl;
821 if (victim == logfiles)
822 logfiles = victim->next;
823 else {
824 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
825// raw_assert(tmpl);
826// raw_assert(tmpl->next == victim);
827 if (!tmpl)
828 return;
829 tmpl->next = victim->next;
830 }
831 log_free(victim);
832}
833
834/** Helper: release system resources (but not memory) held by a single
835 * signal-safe logfile_t. If the log's resources can not be released in
836 * a signal handler, does nothing. */
837static void
839{
840 if (victim->needs_close && victim->fd >= 0) {
841 /* We can't do anything useful here if close() fails: we're shutting
842 * down logging, and the err module only does fatal errors. */
843 close(victim->fd);
844 victim->fd = -1;
845 }
846}
847
848/** Helper: release system resources (but not memory) held by a single
849 * logfile_t. */
850static void
852{
853 if (victim->needs_close) {
854 close_log_sigsafe(victim);
855 } else if (victim->is_syslog) {
856#ifdef HAVE_SYSLOG_H
857 if (--syslog_count == 0) {
858 /* There are no other syslogs; close the logging facility. */
859 closelog();
860 }
861#endif /* defined(HAVE_SYSLOG_H) */
862 }
863}
864
865/** Adjust a log severity configuration in <b>severity_out</b> to contain
866 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
867 */
868void
869set_log_severity_config(int loglevelMin, int loglevelMax,
870 log_severity_list_t *severity_out)
871{
872 int i;
873 raw_assert(loglevelMin >= loglevelMax);
874 raw_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
875 raw_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
876 memset(severity_out, 0, sizeof(log_severity_list_t));
877 for (i = loglevelMin; i >= loglevelMax; --i) {
878 severity_out->masks[SEVERITY_MASK_IDX(i)] = LD_ALL_DOMAINS;
879 }
880}
881
882/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
883 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
884MOCK_IMPL(STATIC void,
886 const char *name, int fd))
887{
888 logfile_t *lf;
889 lf = tor_malloc_zero(sizeof(logfile_t));
890 lf->fd = fd;
891 lf->filename = tor_strdup(name);
892 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
893 lf->next = logfiles;
894
895 logfiles = lf;
897}
898
899/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
900 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
901 * not use it after calling this function. */
902void
903add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
904{
905 LOCK_LOGS();
906 add_stream_log_impl(severity, name, fd);
907 UNLOCK_LOGS();
908}
909
910/** Initialize the global logging facility */
911void
912init_logging(int disable_startup_queue)
913{
916 tor_bug_init_counter();
918 }
919#ifdef __GNUC__
920 if (strchr(__PRETTY_FUNCTION__, '(')) {
922 }
923#endif
924 if (pending_cb_messages == NULL)
926 if (disable_startup_queue)
930 }
931}
932
933/** Set whether we report logging domains as a part of our log messages.
934 */
935void
937{
938 LOCK_LOGS();
939 log_domains_are_logged = enabled;
940 UNLOCK_LOGS();
941}
942
943/** Add a log handler to accept messages when no other log is configured.
944 */
945void
946add_default_log(int min_severity)
947{
948 log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
949 set_log_severity_config(min_severity, LOG_ERR, s);
950 LOCK_LOGS();
951 add_stream_log_impl(s, "<default>", fileno(stdout));
952 tor_free(s);
953 UNLOCK_LOGS();
954}
955
956/**
957 * Register "cb" as the callback to call when there are new pending log
958 * callbacks to be flushed with flush_pending_log_callbacks().
959 *
960 * Note that this callback, if present, can be invoked from any thread.
961 *
962 * This callback must not log.
963 *
964 * It is intentional that this function contains the name "callback" twice: it
965 * sets a "callback" to be called on the condition that there is a "pending
966 * callback".
967 **/
968void
969logs_set_pending_callback_callback(pending_callback_callback cb)
970{
971 pending_cb_cb = cb;
972}
973
974/**
975 * Add a log handler to send messages in <b>severity</b>
976 * to the function <b>cb</b>.
977 */
978int
980{
981 logfile_t *lf;
982 lf = tor_malloc_zero(sizeof(logfile_t));
983 lf->fd = -1;
984 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
985 lf->filename = tor_strdup("<callback>");
986 lf->callback = cb;
987 lf->next = logfiles;
988
989 LOCK_LOGS();
990 logfiles = lf;
992 UNLOCK_LOGS();
993 return 0;
994}
995
996/** Adjust the configured severity of any logs whose callback function is
997 * <b>cb</b>. */
998void
999change_callback_log_severity(int loglevelMin, int loglevelMax,
1000 log_callback cb)
1001{
1002 logfile_t *lf;
1003 log_severity_list_t severities;
1004 set_log_severity_config(loglevelMin, loglevelMax, &severities);
1005 LOCK_LOGS();
1006 for (lf = logfiles; lf; lf = lf->next) {
1007 if (lf->callback == cb) {
1008 memcpy(lf->severities, &severities, sizeof(severities));
1009 }
1010 }
1012 UNLOCK_LOGS();
1013}
1014
1015/** If there are any log messages that were generated with LD_NOCB waiting to
1016 * be sent to callback-based loggers, send them now. */
1017void
1019{
1020 logfile_t *lf;
1021 smartlist_t *messages, *messages_tmp;
1022
1023 LOCK_LOGS();
1024 if (!pending_cb_messages || 0 == smartlist_len(pending_cb_messages)) {
1025 UNLOCK_LOGS();
1026 return;
1027 }
1028
1029 messages = pending_cb_messages;
1031 do {
1033 const int severity = msg->severity;
1034 const log_domain_mask_t domain = msg->domain;
1035 for (lf = logfiles; lf; lf = lf->next) {
1036 if (! lf->callback || lf->seems_dead ||
1037 ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
1038 continue;
1039 }
1040 lf->callback(severity, domain, msg->msg);
1041 }
1042 pending_log_message_free(msg);
1043 } SMARTLIST_FOREACH_END(msg);
1044 smartlist_clear(messages);
1045
1046 messages_tmp = pending_cb_messages;
1047 pending_cb_messages = messages;
1048 messages = messages_tmp;
1049 } while (smartlist_len(messages));
1050
1051 smartlist_free(messages);
1052
1053 UNLOCK_LOGS();
1054}
1055
1056/** Flush all the messages we stored from startup while waiting for log
1057 * initialization.
1058 */
1059void
1061{
1062 logfile_t *lf;
1063
1064 LOCK_LOGS();
1068 goto out;
1069
1071 msg) {
1072 int callbacks_deferred = 0;
1073 for (lf = logfiles; lf; lf = lf->next) {
1074 if (! logfile_wants_message(lf, msg->severity, msg->domain))
1075 continue;
1076
1077 /* We configure a temporary startup log that goes to stdout, so we
1078 * shouldn't replay to stdout/stderr*/
1079 if (lf->fd == STDOUT_FILENO || lf->fd == STDERR_FILENO) {
1080 continue;
1081 }
1082
1083 logfile_deliver(lf, msg->fullmsg, strlen(msg->fullmsg), msg->msg,
1084 msg->domain, msg->severity, &callbacks_deferred);
1085 }
1086 pending_log_message_free(msg);
1087 } SMARTLIST_FOREACH_END(msg);
1088 smartlist_free(pending_startup_messages);
1090
1091 out:
1092 UNLOCK_LOGS();
1093}
1094
1095/** Close any log handlers marked by mark_logs_temp(). */
1096void
1098{
1099 logfile_t *lf, **p;
1100
1101 LOCK_LOGS();
1102 for (p = &logfiles; *p; ) {
1103 if ((*p)->is_temporary) {
1104 lf = *p;
1105 /* we use *p here to handle the edge case of the head of the list */
1106 *p = (*p)->next;
1107 close_log(lf);
1108 log_free(lf);
1109 } else {
1110 p = &((*p)->next);
1111 }
1112 }
1113
1115 UNLOCK_LOGS();
1116}
1117
1118/** Make all currently temporary logs (set to be closed by close_temp_logs)
1119 * live again, and close all non-temporary logs. */
1120void
1122{
1123 logfile_t *lf;
1124 LOCK_LOGS();
1125 for (lf = logfiles; lf; lf = lf->next)
1126 lf->is_temporary = ! lf->is_temporary;
1127 UNLOCK_LOGS();
1129}
1130
1131/** Configure all log handles to be closed by close_temp_logs(). */
1132void
1134{
1135 logfile_t *lf;
1136 LOCK_LOGS();
1137 for (lf = logfiles; lf; lf = lf->next)
1138 lf->is_temporary = 1;
1139 UNLOCK_LOGS();
1140}
1141
1142/**
1143 * Add a log handler to send messages to <b>filename</b> via <b>fd</b>. If
1144 * opening the logfile failed, -1 is returned and errno is set appropriately
1145 * (by open(2)). Takes ownership of fd.
1146 */
1147MOCK_IMPL(int,
1148add_file_log,(const log_severity_list_t *severity,
1149 const char *filename,
1150 int fd))
1151{
1152 logfile_t *lf;
1153
1154 if (fd<0)
1155 return -1;
1156 if (tor_fd_seekend(fd)<0) {
1157 close(fd);
1158 return -1;
1159 }
1160
1161 LOCK_LOGS();
1162 add_stream_log_impl(severity, filename, fd);
1163 logfiles->needs_close = 1;
1164 lf = logfiles;
1166
1167 if (log_tor_version(lf, 0) < 0) {
1168 delete_log(lf);
1169 }
1170 UNLOCK_LOGS();
1171
1172 return 0;
1173}
1174
1175#ifdef HAVE_SYSLOG_H
1176/**
1177 * Add a log handler to send messages to they system log facility.
1178 *
1179 * If this is the first log handler, opens syslog with ident Tor or
1180 * Tor-<syslog_identity_tag> if that is not NULL.
1181 */
1182int
1183add_syslog_log(const log_severity_list_t *severity,
1184 const char* syslog_identity_tag)
1185{
1186 logfile_t *lf;
1187 if (syslog_count++ == 0) {
1188 /* This is the first syslog. */
1189 static char buf[256];
1190 if (syslog_identity_tag) {
1191 tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
1192 } else {
1193 tor_snprintf(buf, sizeof(buf), "Tor");
1194 }
1195 openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1196 }
1197
1198 lf = tor_malloc_zero(sizeof(logfile_t));
1199 lf->fd = -1;
1200 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1201 lf->filename = tor_strdup("<syslog>");
1202 lf->is_syslog = 1;
1203
1204 LOCK_LOGS();
1205 lf->next = logfiles;
1206 logfiles = lf;
1208 UNLOCK_LOGS();
1209 return 0;
1210}
1211#endif /* defined(HAVE_SYSLOG_H) */
1212
1213/** If <b>level</b> is a valid log severity, return the corresponding
1214 * numeric value. Otherwise, return -1. */
1215int
1216parse_log_level(const char *level)
1217{
1218 if (!strcasecmp(level, "err"))
1219 return LOG_ERR;
1220 if (!strcasecmp(level, "warn"))
1221 return LOG_WARN;
1222 if (!strcasecmp(level, "notice"))
1223 return LOG_NOTICE;
1224 if (!strcasecmp(level, "info"))
1225 return LOG_INFO;
1226 if (!strcasecmp(level, "debug"))
1227 return LOG_DEBUG;
1228 return -1;
1229}
1230
1231/** Return the string equivalent of a given log level. */
1232const char *
1234{
1235 return sev_to_string(level);
1236}
1237
1238/** NULL-terminated array of names for log domains such that domain_list[dom]
1239 * is a description of <b>dom</b>.
1240 *
1241 * Remember to update doc/man/tor.1.txt if you modify this list.
1242 * */
1243static const char *domain_list[] = {
1244 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
1245 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
1246 "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
1247 "SCHED", "GUARD", "CONSDIFF", "DOS", "PROCESS", "PT", "BTRACK", "MESG",
1248 NULL
1249};
1250
1252
1256
1257/** Return a bitmask for the log domain for which <b>domain</b> is the name,
1258 * or 0 if there is no such name. */
1259static log_domain_mask_t
1260parse_log_domain(const char *domain)
1261{
1262 int i;
1263 for (i=0; domain_list[i]; ++i) {
1264 if (!strcasecmp(domain, domain_list[i]))
1265 return (UINT64_C(1)<<i);
1266 }
1267 return 0;
1268}
1269
1270/** Translate a bitmask of log domains to a string. */
1271static char *
1272domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
1273{
1274 char *cp = buf;
1275 char *eos = buf+buflen;
1276
1277 buf[0] = '\0';
1278 if (! domain)
1279 return buf;
1280 while (1) {
1281 const char *d;
1282 int bit = tor_log2(domain);
1283 size_t n;
1284 if ((unsigned)bit >= ARRAY_LENGTH(domain_list)-1 ||
1285 bit >= N_LOGGING_DOMAINS) {
1286 tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
1287 return buf+strlen(buf);
1288 }
1289 d = domain_list[bit];
1290 n = strlcpy(cp, d, eos-cp);
1291 if (n >= buflen) {
1292 tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
1293 return buf+strlen(buf);
1294 }
1295 cp += n;
1296 domain &= ~(1<<bit);
1297
1298 if (domain == 0 || (eos-cp) < 2)
1299 return cp;
1300
1301 memcpy(cp, ",", 2); /*Nul-terminated ,"*/
1302 cp++;
1303 }
1304}
1305
1306/** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
1307 * the end of the severityPattern. Set the value of <b>severity_out</b> to
1308 * the parsed pattern. Return 0 on success, -1 on failure.
1309 *
1310 * The syntax for a SeverityPattern is:
1311 * <pre>
1312 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
1313 * DomainSeverity = (DomainList SP)? SeverityRange
1314 * SeverityRange = MinSeverity ("-" MaxSeverity )?
1315 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
1316 * DomainSpec = "*" | Domain | "~" Domain
1317 * </pre>
1318 * A missing MaxSeverity defaults to ERR. Severities and domains are
1319 * case-insensitive. "~" indicates negation for a domain; negation happens
1320 * last inside a DomainList. Only one SeverityRange without a DomainList is
1321 * allowed per line.
1322 */
1323int
1324parse_log_severity_config(const char **cfg_ptr,
1325 log_severity_list_t *severity_out)
1326{
1327 const char *cfg = *cfg_ptr;
1328 int got_anything = 0;
1329 int got_an_unqualified_range = 0;
1330 memset(severity_out, 0, sizeof(*severity_out));
1331
1332 cfg = eat_whitespace(cfg);
1333 while (*cfg) {
1334 const char *dash, *space;
1335 char *sev_lo, *sev_hi;
1336 int low, high, i;
1338
1339 if (*cfg == '[') {
1340 int err = 0;
1341 char *domains_str;
1342 smartlist_t *domains_list;
1343 log_domain_mask_t neg_domains = 0;
1344 const char *closebracket = strchr(cfg, ']');
1345 if (!closebracket)
1346 return -1;
1347 domains = 0;
1348 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1349 domains_list = smartlist_new();
1350 smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
1351 -1);
1352 tor_free(domains_str);
1353 SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
1354 if (!strcmp(domain, "*")) {
1355 domains = LD_ALL_DOMAINS;
1356 } else {
1358 int negate=0;
1359 if (*domain == '~') {
1360 negate = 1;
1361 ++domain;
1362 }
1363 d = parse_log_domain(domain);
1364 if (!d) {
1365 log_warn(LD_CONFIG, "No such logging domain as %s", domain);
1366 err = 1;
1367 } else {
1368 if (negate)
1369 neg_domains |= d;
1370 else
1371 domains |= d;
1372 }
1373 }
1374 } SMARTLIST_FOREACH_END(domain);
1375 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
1376 smartlist_free(domains_list);
1377 if (err)
1378 return -1;
1379 if (domains == 0 && neg_domains)
1380 domains = ~neg_domains;
1381 else
1382 domains &= ~neg_domains;
1383 cfg = eat_whitespace(closebracket+1);
1384 } else {
1385 ++got_an_unqualified_range;
1386 }
1387 if (!strcasecmpstart(cfg, "file") ||
1388 !strcasecmpstart(cfg, "stderr") ||
1389 !strcasecmpstart(cfg, "stdout") ||
1390 !strcasecmpstart(cfg, "syslog")) {
1391 goto done;
1392 }
1393 if (got_an_unqualified_range > 1)
1394 return -1;
1395
1396 space = find_whitespace(cfg);
1397 dash = strchr(cfg, '-');
1398 if (dash && dash < space) {
1399 sev_lo = tor_strndup(cfg, dash-cfg);
1400 sev_hi = tor_strndup(dash+1, space-(dash+1));
1401 } else {
1402 sev_lo = tor_strndup(cfg, space-cfg);
1403 sev_hi = tor_strdup("ERR");
1404 }
1405 low = parse_log_level(sev_lo);
1406 high = parse_log_level(sev_hi);
1407 tor_free(sev_lo);
1408 tor_free(sev_hi);
1409 if (low == -1)
1410 return -1;
1411 if (high == -1)
1412 return -1;
1413
1414 got_anything = 1;
1415 for (i=low; i >= high; --i)
1416 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
1417
1418 cfg = eat_whitespace(space);
1419 }
1420
1421 done:
1422 *cfg_ptr = cfg;
1423 return got_anything ? 0 : -1;
1424}
1425
1426/** Return the least severe log level that any current log is interested in. */
1427int
1429{
1430 logfile_t *lf;
1431 int i;
1432 int min = LOG_ERR;
1433 for (lf = logfiles; lf; lf = lf->next) {
1434 for (i = LOG_DEBUG; i > min; --i)
1435 if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
1436 min = i;
1437 }
1438 return min;
1439}
1440
1441/** Switch all logs to output at most verbose level. */
1442void
1444{
1445 logfile_t *lf;
1446 int i;
1447 LOCK_LOGS();
1448 for (lf = logfiles; lf; lf=lf->next) {
1449 for (i = LOG_DEBUG; i >= LOG_ERR; --i)
1450 lf->severities->masks[SEVERITY_MASK_IDX(i)] = LD_ALL_DOMAINS;
1451 }
1453 UNLOCK_LOGS();
1454}
1455
1456/** Truncate all the log files. */
1457void
1459{
1460 logfile_t *lf;
1461 for (lf = logfiles; lf; lf = lf->next) {
1462 if (lf->fd >= 0) {
1463 tor_ftruncate(lf->fd);
1464 }
1465 }
1466}
time_t approx_time(void)
Definition: approx_time.c:32
Header for approx_time.c.
int tor_log2(uint64_t u64)
Definition: bits.c:16
Header for bits.c.
#define ARRAY_LENGTH(x)
Header for compat_mutex.c.
void tor_mutex_init(tor_mutex_t *m)
Header for compat_string.c.
const char * name
Definition: config.c:2462
Compile-time assertions: CTASSERT(expression).
CTASSERT(NUMBER_SECOND_GUARDS< 20)
int tor_fd_seekend(int fd)
Definition: fdio.c:61
off_t tor_fd_getpos(int fd)
Definition: fdio.c:48
int write_all_to_fd_minimal(int fd, const char *buf, size_t count)
Definition: fdio.c:108
int tor_ftruncate(int fd)
Definition: fdio.c:92
Header for fdio.c.
const char tor_bug_suffix[]
Definition: git_revision.c:32
Header for git_revision.c.
const int LOG_WARN_
Definition: log.c:64
int add_file_log(const log_severity_list_t *severity, const char *filename, int fd)
Definition: log.c:1150
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:591
void init_logging(int disable_startup_queue)
Definition: log.c:912
static int log_time_granularity
Definition: log.c:243
void flush_log_messages_from_startup(void)
Definition: log.c:1060
void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb)
Definition: log.c:999
static char * domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
Definition: log.c:1272
void mark_logs_temp(void)
Definition: log.c:1133
static void log_free_(logfile_t *victim)
Definition: log.c:735
static log_domain_mask_t parse_log_domain(const char *domain)
Definition: log.c:1260
void logs_free_all(void)
Definition: log.c:746
void logs_flush_sigsafe(void)
Definition: log.c:792
void truncate_logs(void)
Definition: log.c:1458
void rollback_log_changes(void)
Definition: log.c:1121
void logs_set_pending_callback_callback(pending_callback_callback cb)
Definition: log.c:969
int add_callback_log(const log_severity_list_t *severity, log_callback cb)
Definition: log.c:979
void switch_logs_debug(void)
Definition: log.c:1443
static char * format_msg(char *buf, size_t buf_len, log_domain_mask_t domain, int severity, const char *funcname, const char *suffix, const char *format, va_list ap, size_t *msg_len_out)
Definition: log.c:331
void log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format,...)
Definition: log.c:706
#define LOCK_LOGS()
Definition: log.c:176
void set_log_severity_config(int loglevelMin, int loglevelMax, log_severity_list_t *severity_out)
Definition: log.c:869
void tor_log_string(int severity, log_domain_mask_t domain, const char *function, const char *string)
Definition: log.c:236
static int pretty_fn_has_parens
Definition: log.c:169
int get_min_log_level(void)
Definition: log.c:1428
static int logfile_wants_message(const logfile_t *lf, int severity, log_domain_mask_t domain)
Definition: log.c:459
void log_set_application_name(const char *name)
Definition: log.c:212
STATIC void add_stream_log_impl(const log_severity_list_t *severity, const char *name, int fd)
Definition: log.c:886
static smartlist_t * pending_startup_messages
Definition: log.c:157
void set_log_time_granularity(int granularity_msec)
Definition: log.c:248
void flush_pending_log_callbacks(void)
Definition: log.c:1018
int log_message_is_interesting(int severity, log_domain_mask_t domain)
Definition: log.c:223
static void close_log(logfile_t *victim)
Definition: log.c:851
static int log_tor_version(logfile_t *lf, int reset)
Definition: log.c:293
static void close_log_sigsafe(logfile_t *victim)
Definition: log.c:838
static int logfile_is_external(const logfile_t *lf)
Definition: log.c:449
int log_global_min_severity_
Definition: log.c:188
static const char * domain_list[]
Definition: log.c:1243
static void pending_log_message_free_(pending_log_message_t *msg)
Definition: log.c:436
void tor_log_update_sigsafe_err_fds(void)
Definition: log.c:626
static int log_domains_are_logged
Definition: log.c:132
const char * log_level_to_string(int level)
Definition: log.c:1233
static tor_mutex_t log_mutex
Definition: log.c:125
void add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
Definition: log.c:903
static smartlist_t * pending_cb_messages
Definition: log.c:150
static char * appname
Definition: log.c:204
void add_default_log(int min_severity)
Definition: log.c:946
static logfile_t * logfiles
Definition: log.c:130
STATIC void logv(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap)
Definition: log.c:536
static size_t log_prefix_(char *buf, size_t buf_len, int severity)
Definition: log.c:258
static int log_mutex_initialized
Definition: log.c:127
int parse_log_level(const char *level)
Definition: log.c:1216
#define MAX_STARTUP_MSG_LEN
Definition: log.c:173
static void logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len, const char *msg_after_prefix, log_domain_mask_t domain, int severity, int *callbacks_deferred)
Definition: log.c:482
#define TRUNCATED_STR
Definition: log.c:58
static void delete_log(logfile_t *victim)
Definition: log.c:818
static int int_array_contains(const int *array, int n, int item)
Definition: log.c:613
void logs_set_domain_logging(int enabled)
Definition: log.c:936
void tor_log_get_logfile_names(smartlist_t *out)
Definition: log.c:684
static int queue_startup_messages
Definition: log.c:166
static const char * sev_to_string(int severity)
Definition: log.c:89
int parse_log_severity_config(const char **cfg_ptr, log_severity_list_t *severity_out)
Definition: log.c:1324
#define UNLOCK_LOGS()
Definition: log.c:181
static pending_callback_callback pending_cb_cb
Definition: log.c:153
static int should_log_function_name(log_domain_mask_t domain, int severity)
Definition: log.c:105
void close_temp_logs(void)
Definition: log.c:1097
static size_t pending_startup_messages_len
Definition: log.c:162
Headers for log.c.
#define LD_ALL_DOMAINS
Definition: log.h:128
#define LD_ALL_FLAGS
Definition: log.h:135
#define LD_NOCB
Definition: log.h:144
#define LOG_DEBUG
Definition: log.h:42
#define LD_NOFUNCNAME
Definition: log.h:147
void(* log_callback)(int severity, log_domain_mask_t domain, const char *msg)
Definition: log.h:158
#define LOWEST_RESERVED_LD_FLAG_
Definition: log.h:133
#define LOG_ERR
Definition: log.h:56
#define LD_BUG
Definition: log.h:86
#define LD_NET
Definition: log.h:66
#define LD_GENERAL
Definition: log.h:62
#define N_LOGGING_DOMAINS
Definition: log.h:124
#define LOG_NOTICE
Definition: log.h:50
#define HIGHEST_RESERVED_LD_DOMAIN_
Definition: log.h:126
#define LD_CONFIG
Definition: log.h:68
#define LOG_WARN
Definition: log.h:53
#define LOG_INFO
Definition: log.h:45
Declare subsystem object for the logging module.
uint64_t log_domain_mask_t
Definition: logging_types.h:21
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
Definition: printf.c:41
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
Header for printf.c.
char * rate_limit_log(ratelim_t *lim, time_t now)
Definition: ratelim.c:42
Summarize similar messages that would otherwise flood the logs.
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_clear(smartlist_t *sl)
Top-level declarations for the smartlist_t dynamic array type.
Macros for iterating over the elements of a smartlist_t.
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
Header for smartlist_split.c.
log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1]
Definition: log.h:154
Definition: log.c:70
log_severity_list_t * severities
Definition: log.c:79
struct logfile_t * next
Definition: log.c:71
int needs_close
Definition: log.c:75
int fd
Definition: log.c:73
int seems_dead
Definition: log.c:74
int is_syslog
Definition: log.c:77
log_callback callback
Definition: log.c:78
char * filename
Definition: log.c:72
int is_temporary
Definition: log.c:76
char * fullmsg
Definition: log.c:145
log_domain_mask_t domain
Definition: log.c:144
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
Definitions for timing-related constants.
struct tm * tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
Definition: time_to_tm.c:133
Header for time_to_tm.c.
void tor_gettimeofday(struct timeval *timeval)
Header for tor_gettimeofday.c.
void tor_log_sigsafe_err_set_granularity(int ms)
Definition: torerr.c:182
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
Definition: torerr.c:123
Headers for torerr.c.
#define TOR_SIGSAFE_LOG_MAX_FDS
Definition: torerr.h:37
Macros to manage assertions, fatal and non-fatal.
int strcasecmpstart(const char *s1, const char *s2)
Definition: util_string.c:227
const char * find_whitespace(const char *s)
Definition: util_string.c:355
const char * eat_whitespace(const char *s)
Definition: util_string.c:279
Header for util_string.c.