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 (domain & LD_BUG)
712 if (severity > log_global_min_severity_)
713 return;
714 va_start(ap,format);
715 logv(severity, domain, fn, NULL, format, ap);
716 va_end(ap);
717}
718void
719log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
720 const char *fn, const char *format, ...)
721{
722 va_list ap;
723 char *m;
724 if (domain & LD_BUG)
726 if (severity > log_global_min_severity_)
727 return;
728 m = rate_limit_log(ratelim, approx_time());
729 if (m == NULL)
730 return;
731 va_start(ap, format);
732 logv(severity, domain, fn, m, format, ap);
733 va_end(ap);
734 tor_free(m);
735}
736
737/** Free all storage held by <b>victim</b>. */
738static void
740{
741 if (!victim)
742 return;
743 tor_free(victim->severities);
744 tor_free(victim->filename);
745 tor_free(victim);
746}
747
748/** Close all open log files, and free other static memory. */
749void
751{
752 logfile_t *victim, *next;
753 smartlist_t *messages, *messages2;
754 LOCK_LOGS();
755 next = logfiles;
756 logfiles = NULL;
757 messages = pending_cb_messages;
758 pending_cb_messages = NULL;
759 pending_cb_cb = NULL;
760 messages2 = pending_startup_messages;
762 UNLOCK_LOGS();
763 while (next) {
764 victim = next;
765 next = next->next;
766 close_log(victim);
767 log_free(victim);
768 }
770
771 SMARTLIST_FOREACH(messages, pending_log_message_t *, msg, {
772 pending_log_message_free(msg);
773 });
774 smartlist_free(messages);
775
776 if (messages2) {
777 SMARTLIST_FOREACH(messages2, pending_log_message_t *, msg, {
778 pending_log_message_free(msg);
779 });
780 smartlist_free(messages2);
781 }
782
783 /* We _could_ destroy the log mutex here, but that would screw up any logs
784 * that happened between here and the end of execution.
785 * If tor is re-initialized, log_mutex_initialized will still be 1. So we
786 * won't trigger any undefined behaviour by trying to re-initialize the
787 * log mutex. */
788}
789
790/** Flush the signal-safe log files.
791 *
792 * This function is safe to call from a signal handler. It is currently called
793 * by the BUG() macros, when terminating the process on an abnormal condition.
794 */
795void
797{
798 /* If we don't have fsync() in unistd.h, we can't flush the logs. */
799#ifdef HAVE_FSYNC
800 logfile_t *victim, *next;
801 /* We can't LOCK_LOGS() in a signal handler, because it may call
802 * signal-unsafe functions. And we can't deallocate memory, either. */
803 next = logfiles;
804 logfiles = NULL;
805 while (next) {
806 victim = next;
807 next = next->next;
808 if (victim->needs_close) {
809 /* We can't do anything useful if the flush fails. */
810 (void)fsync(victim->fd);
811 }
812 }
813#endif /* defined(HAVE_FSYNC) */
814}
815
816/** Remove and free the log entry <b>victim</b> from the linked-list
817 * logfiles (it is probably present, but it might not be due to thread
818 * racing issues). After this function is called, the caller shouldn't
819 * refer to <b>victim</b> anymore.
820 */
821static void
823{
824 logfile_t *tmpl;
825 if (victim == logfiles)
826 logfiles = victim->next;
827 else {
828 for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
829// raw_assert(tmpl);
830// raw_assert(tmpl->next == victim);
831 if (!tmpl)
832 return;
833 tmpl->next = victim->next;
834 }
835 log_free(victim);
836}
837
838/** Helper: release system resources (but not memory) held by a single
839 * signal-safe logfile_t. If the log's resources can not be released in
840 * a signal handler, does nothing. */
841static void
843{
844 if (victim->needs_close && victim->fd >= 0) {
845 /* We can't do anything useful here if close() fails: we're shutting
846 * down logging, and the err module only does fatal errors. */
847 close(victim->fd);
848 victim->fd = -1;
849 }
850}
851
852/** Helper: release system resources (but not memory) held by a single
853 * logfile_t. */
854static void
856{
857 if (victim->needs_close) {
858 close_log_sigsafe(victim);
859 } else if (victim->is_syslog) {
860#ifdef HAVE_SYSLOG_H
861 if (--syslog_count == 0) {
862 /* There are no other syslogs; close the logging facility. */
863 closelog();
864 }
865#endif /* defined(HAVE_SYSLOG_H) */
866 }
867}
868
869/** Adjust a log severity configuration in <b>severity_out</b> to contain
870 * every domain between <b>loglevelMin</b> and <b>loglevelMax</b>, inclusive.
871 */
872void
873set_log_severity_config(int loglevelMin, int loglevelMax,
874 log_severity_list_t *severity_out)
875{
876 int i;
877 raw_assert(loglevelMin >= loglevelMax);
878 raw_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
879 raw_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
880 memset(severity_out, 0, sizeof(log_severity_list_t));
881 for (i = loglevelMin; i >= loglevelMax; --i) {
882 severity_out->masks[SEVERITY_MASK_IDX(i)] = LD_ALL_DOMAINS;
883 }
884}
885
886/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
887 * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */
888MOCK_IMPL(STATIC void,
890 const char *name, int fd))
891{
892 logfile_t *lf;
893 lf = tor_malloc_zero(sizeof(logfile_t));
894 lf->fd = fd;
895 lf->filename = tor_strdup(name);
896 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
897 lf->next = logfiles;
898
899 logfiles = lf;
901}
902
903/** Add a log handler named <b>name</b> to send all messages in <b>severity</b>
904 * to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
905 * not use it after calling this function. */
906void
907add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
908{
909 LOCK_LOGS();
910 add_stream_log_impl(severity, name, fd);
911 UNLOCK_LOGS();
912}
913
914/** Initialize the global logging facility */
915void
916init_logging(int disable_startup_queue)
917{
920 tor_bug_init_counter();
922 }
923#ifdef __GNUC__
924 if (strchr(__PRETTY_FUNCTION__, '(')) {
926 }
927#endif
928 if (pending_cb_messages == NULL)
930 if (disable_startup_queue)
934 }
935}
936
937/** Set whether we report logging domains as a part of our log messages.
938 */
939void
941{
942 LOCK_LOGS();
943 log_domains_are_logged = enabled;
944 UNLOCK_LOGS();
945}
946
947/** Add a log handler to accept messages when no other log is configured.
948 */
949void
950add_default_log(int min_severity)
951{
952 log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
953 set_log_severity_config(min_severity, LOG_ERR, s);
954 LOCK_LOGS();
955 add_stream_log_impl(s, "<default>", fileno(stdout));
956 tor_free(s);
957 UNLOCK_LOGS();
958}
959
960/**
961 * Register "cb" as the callback to call when there are new pending log
962 * callbacks to be flushed with flush_pending_log_callbacks().
963 *
964 * Note that this callback, if present, can be invoked from any thread.
965 *
966 * This callback must not log.
967 *
968 * It is intentional that this function contains the name "callback" twice: it
969 * sets a "callback" to be called on the condition that there is a "pending
970 * callback".
971 **/
972void
973logs_set_pending_callback_callback(pending_callback_callback cb)
974{
975 pending_cb_cb = cb;
976}
977
978/**
979 * Add a log handler to send messages in <b>severity</b>
980 * to the function <b>cb</b>.
981 */
982int
984{
985 logfile_t *lf;
986 lf = tor_malloc_zero(sizeof(logfile_t));
987 lf->fd = -1;
988 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
989 lf->filename = tor_strdup("<callback>");
990 lf->callback = cb;
991 lf->next = logfiles;
992
993 LOCK_LOGS();
994 logfiles = lf;
996 UNLOCK_LOGS();
997 return 0;
998}
999
1000/** Adjust the configured severity of any logs whose callback function is
1001 * <b>cb</b>. */
1002void
1003change_callback_log_severity(int loglevelMin, int loglevelMax,
1004 log_callback cb)
1005{
1006 logfile_t *lf;
1007 log_severity_list_t severities;
1008 set_log_severity_config(loglevelMin, loglevelMax, &severities);
1009 LOCK_LOGS();
1010 for (lf = logfiles; lf; lf = lf->next) {
1011 if (lf->callback == cb) {
1012 memcpy(lf->severities, &severities, sizeof(severities));
1013 }
1014 }
1016 UNLOCK_LOGS();
1017}
1018
1019/** If there are any log messages that were generated with LD_NOCB waiting to
1020 * be sent to callback-based loggers, send them now. */
1021void
1023{
1024 logfile_t *lf;
1025 smartlist_t *messages, *messages_tmp;
1026
1027 LOCK_LOGS();
1028 if (!pending_cb_messages || 0 == smartlist_len(pending_cb_messages)) {
1029 UNLOCK_LOGS();
1030 return;
1031 }
1032
1033 messages = pending_cb_messages;
1035 do {
1037 const int severity = msg->severity;
1038 const log_domain_mask_t domain = msg->domain;
1039 for (lf = logfiles; lf; lf = lf->next) {
1040 if (! lf->callback || lf->seems_dead ||
1041 ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
1042 continue;
1043 }
1044 lf->callback(severity, domain, msg->msg);
1045 }
1046 pending_log_message_free(msg);
1047 } SMARTLIST_FOREACH_END(msg);
1048 smartlist_clear(messages);
1049
1050 messages_tmp = pending_cb_messages;
1051 pending_cb_messages = messages;
1052 messages = messages_tmp;
1053 } while (smartlist_len(messages));
1054
1055 smartlist_free(messages);
1056
1057 UNLOCK_LOGS();
1058}
1059
1060/** Flush all the messages we stored from startup while waiting for log
1061 * initialization.
1062 */
1063void
1065{
1066 logfile_t *lf;
1067
1068 LOCK_LOGS();
1072 goto out;
1073
1075 msg) {
1076 int callbacks_deferred = 0;
1077 for (lf = logfiles; lf; lf = lf->next) {
1078 if (! logfile_wants_message(lf, msg->severity, msg->domain))
1079 continue;
1080
1081 /* We configure a temporary startup log that goes to stdout, so we
1082 * shouldn't replay to stdout/stderr*/
1083 if (lf->fd == STDOUT_FILENO || lf->fd == STDERR_FILENO) {
1084 continue;
1085 }
1086
1087 logfile_deliver(lf, msg->fullmsg, strlen(msg->fullmsg), msg->msg,
1088 msg->domain, msg->severity, &callbacks_deferred);
1089 }
1090 pending_log_message_free(msg);
1091 } SMARTLIST_FOREACH_END(msg);
1092 smartlist_free(pending_startup_messages);
1094
1095 out:
1096 UNLOCK_LOGS();
1097}
1098
1099/** Close any log handlers marked by mark_logs_temp(). */
1100void
1102{
1103 logfile_t *lf, **p;
1104
1105 LOCK_LOGS();
1106 for (p = &logfiles; *p; ) {
1107 if ((*p)->is_temporary) {
1108 lf = *p;
1109 /* we use *p here to handle the edge case of the head of the list */
1110 *p = (*p)->next;
1111 close_log(lf);
1112 log_free(lf);
1113 } else {
1114 p = &((*p)->next);
1115 }
1116 }
1117
1119 UNLOCK_LOGS();
1120}
1121
1122/** Make all currently temporary logs (set to be closed by close_temp_logs)
1123 * live again, and close all non-temporary logs. */
1124void
1126{
1127 logfile_t *lf;
1128 LOCK_LOGS();
1129 for (lf = logfiles; lf; lf = lf->next)
1130 lf->is_temporary = ! lf->is_temporary;
1131 UNLOCK_LOGS();
1133}
1134
1135/** Configure all log handles to be closed by close_temp_logs(). */
1136void
1138{
1139 logfile_t *lf;
1140 LOCK_LOGS();
1141 for (lf = logfiles; lf; lf = lf->next)
1142 lf->is_temporary = 1;
1143 UNLOCK_LOGS();
1144}
1145
1146/**
1147 * Add a log handler to send messages to <b>filename</b> via <b>fd</b>. If
1148 * opening the logfile failed, -1 is returned and errno is set appropriately
1149 * (by open(2)). Takes ownership of fd.
1150 */
1151MOCK_IMPL(int,
1152add_file_log,(const log_severity_list_t *severity,
1153 const char *filename,
1154 int fd))
1155{
1156 logfile_t *lf;
1157
1158 if (fd<0)
1159 return -1;
1160 if (tor_fd_seekend(fd)<0) {
1161 close(fd);
1162 return -1;
1163 }
1164
1165 LOCK_LOGS();
1166 add_stream_log_impl(severity, filename, fd);
1167 logfiles->needs_close = 1;
1168 lf = logfiles;
1170
1171 if (log_tor_version(lf, 0) < 0) {
1172 delete_log(lf);
1173 }
1174 UNLOCK_LOGS();
1175
1176 return 0;
1177}
1178
1179#ifdef HAVE_SYSLOG_H
1180/**
1181 * Add a log handler to send messages to they system log facility.
1182 *
1183 * If this is the first log handler, opens syslog with ident Tor or
1184 * Tor-<syslog_identity_tag> if that is not NULL.
1185 */
1186int
1187add_syslog_log(const log_severity_list_t *severity,
1188 const char* syslog_identity_tag)
1189{
1190 logfile_t *lf;
1191 if (syslog_count++ == 0) {
1192 /* This is the first syslog. */
1193 static char buf[256];
1194 if (syslog_identity_tag) {
1195 tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
1196 } else {
1197 tor_snprintf(buf, sizeof(buf), "Tor");
1198 }
1199 openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1200 }
1201
1202 lf = tor_malloc_zero(sizeof(logfile_t));
1203 lf->fd = -1;
1204 lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1205 lf->filename = tor_strdup("<syslog>");
1206 lf->is_syslog = 1;
1207
1208 LOCK_LOGS();
1209 lf->next = logfiles;
1210 logfiles = lf;
1212 UNLOCK_LOGS();
1213 return 0;
1214}
1215#endif /* defined(HAVE_SYSLOG_H) */
1216
1217/** If <b>level</b> is a valid log severity, return the corresponding
1218 * numeric value. Otherwise, return -1. */
1219int
1220parse_log_level(const char *level)
1221{
1222 if (!strcasecmp(level, "err"))
1223 return LOG_ERR;
1224 if (!strcasecmp(level, "warn"))
1225 return LOG_WARN;
1226 if (!strcasecmp(level, "notice"))
1227 return LOG_NOTICE;
1228 if (!strcasecmp(level, "info"))
1229 return LOG_INFO;
1230 if (!strcasecmp(level, "debug"))
1231 return LOG_DEBUG;
1232 return -1;
1233}
1234
1235/** Return the string equivalent of a given log level. */
1236const char *
1238{
1239 return sev_to_string(level);
1240}
1241
1242/** NULL-terminated array of names for log domains such that domain_list[dom]
1243 * is a description of <b>dom</b>.
1244 *
1245 * Remember to update doc/man/tor.1.txt if you modify this list.
1246 * */
1247static const char *domain_list[] = {
1248 "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
1249 "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
1250 "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
1251 "SCHED", "GUARD", "CONSDIFF", "DOS", "PROCESS", "PT", "BTRACK", "MESG",
1252 NULL
1253};
1254
1256
1260
1261/** Return a bitmask for the log domain for which <b>domain</b> is the name,
1262 * or 0 if there is no such name. */
1263static log_domain_mask_t
1264parse_log_domain(const char *domain)
1265{
1266 int i;
1267 for (i=0; domain_list[i]; ++i) {
1268 if (!strcasecmp(domain, domain_list[i]))
1269 return (UINT64_C(1)<<i);
1270 }
1271 return 0;
1272}
1273
1274/** Translate a bitmask of log domains to a string. */
1275static char *
1276domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
1277{
1278 char *cp = buf;
1279 char *eos = buf+buflen;
1280
1281 buf[0] = '\0';
1282 if (! domain)
1283 return buf;
1284 while (1) {
1285 const char *d;
1286 int bit = tor_log2(domain);
1287 size_t n;
1288 if ((unsigned)bit >= ARRAY_LENGTH(domain_list)-1 ||
1289 bit >= N_LOGGING_DOMAINS) {
1290 tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
1291 return buf+strlen(buf);
1292 }
1293 d = domain_list[bit];
1294 n = strlcpy(cp, d, eos-cp);
1295 if (n >= buflen) {
1296 tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
1297 return buf+strlen(buf);
1298 }
1299 cp += n;
1300 domain &= ~(1<<bit);
1301
1302 if (domain == 0 || (eos-cp) < 2)
1303 return cp;
1304
1305 memcpy(cp, ",", 2); /*Nul-terminated ,"*/
1306 cp++;
1307 }
1308}
1309
1310/** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
1311 * the end of the severityPattern. Set the value of <b>severity_out</b> to
1312 * the parsed pattern. Return 0 on success, -1 on failure.
1313 *
1314 * The syntax for a SeverityPattern is:
1315 * <pre>
1316 * SeverityPattern = *(DomainSeverity SP)* DomainSeverity
1317 * DomainSeverity = (DomainList SP)? SeverityRange
1318 * SeverityRange = MinSeverity ("-" MaxSeverity )?
1319 * DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
1320 * DomainSpec = "*" | Domain | "~" Domain
1321 * </pre>
1322 * A missing MaxSeverity defaults to ERR. Severities and domains are
1323 * case-insensitive. "~" indicates negation for a domain; negation happens
1324 * last inside a DomainList. Only one SeverityRange without a DomainList is
1325 * allowed per line.
1326 */
1327int
1328parse_log_severity_config(const char **cfg_ptr,
1329 log_severity_list_t *severity_out)
1330{
1331 const char *cfg = *cfg_ptr;
1332 int got_anything = 0;
1333 int got_an_unqualified_range = 0;
1334 memset(severity_out, 0, sizeof(*severity_out));
1335
1336 cfg = eat_whitespace(cfg);
1337 while (*cfg) {
1338 const char *dash, *space;
1339 char *sev_lo, *sev_hi;
1340 int low, high, i;
1342
1343 if (*cfg == '[') {
1344 int err = 0;
1345 char *domains_str;
1346 smartlist_t *domains_list;
1347 log_domain_mask_t neg_domains = 0;
1348 const char *closebracket = strchr(cfg, ']');
1349 if (!closebracket)
1350 return -1;
1351 domains = 0;
1352 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1353 domains_list = smartlist_new();
1354 smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
1355 -1);
1356 tor_free(domains_str);
1357 SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
1358 if (!strcmp(domain, "*")) {
1359 domains = LD_ALL_DOMAINS;
1360 } else {
1362 int negate=0;
1363 if (*domain == '~') {
1364 negate = 1;
1365 ++domain;
1366 }
1367 d = parse_log_domain(domain);
1368 if (!d) {
1369 log_warn(LD_CONFIG, "No such logging domain as %s", domain);
1370 err = 1;
1371 } else {
1372 if (negate)
1373 neg_domains |= d;
1374 else
1375 domains |= d;
1376 }
1377 }
1378 } SMARTLIST_FOREACH_END(domain);
1379 SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
1380 smartlist_free(domains_list);
1381 if (err)
1382 return -1;
1383 if (domains == 0 && neg_domains)
1384 domains = ~neg_domains;
1385 else
1386 domains &= ~neg_domains;
1387 cfg = eat_whitespace(closebracket+1);
1388 } else {
1389 ++got_an_unqualified_range;
1390 }
1391 if (!strcasecmpstart(cfg, "file") ||
1392 !strcasecmpstart(cfg, "stderr") ||
1393 !strcasecmpstart(cfg, "stdout") ||
1394 !strcasecmpstart(cfg, "syslog")) {
1395 goto done;
1396 }
1397 if (got_an_unqualified_range > 1)
1398 return -1;
1399
1400 space = find_whitespace(cfg);
1401 dash = strchr(cfg, '-');
1402 if (dash && dash < space) {
1403 sev_lo = tor_strndup(cfg, dash-cfg);
1404 sev_hi = tor_strndup(dash+1, space-(dash+1));
1405 } else {
1406 sev_lo = tor_strndup(cfg, space-cfg);
1407 sev_hi = tor_strdup("ERR");
1408 }
1409 low = parse_log_level(sev_lo);
1410 high = parse_log_level(sev_hi);
1411 tor_free(sev_lo);
1412 tor_free(sev_hi);
1413 if (low == -1)
1414 return -1;
1415 if (high == -1)
1416 return -1;
1417
1418 got_anything = 1;
1419 for (i=low; i >= high; --i)
1420 severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
1421
1422 cfg = eat_whitespace(space);
1423 }
1424
1425 done:
1426 *cfg_ptr = cfg;
1427 return got_anything ? 0 : -1;
1428}
1429
1430/** Return the least severe log level that any current log is interested in. */
1431int
1433{
1434 logfile_t *lf;
1435 int i;
1436 int min = LOG_ERR;
1437 for (lf = logfiles; lf; lf = lf->next) {
1438 for (i = LOG_DEBUG; i > min; --i)
1439 if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
1440 min = i;
1441 }
1442 return min;
1443}
1444
1445/** Switch all logs to output at most verbose level. */
1446void
1448{
1449 logfile_t *lf;
1450 int i;
1451 LOCK_LOGS();
1452 for (lf = logfiles; lf; lf=lf->next) {
1453 for (i = LOG_DEBUG; i >= LOG_ERR; --i)
1454 lf->severities->masks[SEVERITY_MASK_IDX(i)] = LD_ALL_DOMAINS;
1455 }
1457 UNLOCK_LOGS();
1458}
1459
1460/** Truncate all the log files. */
1461void
1463{
1464 logfile_t *lf;
1465 for (lf = logfiles; lf; lf = lf->next) {
1466 if (lf->fd >= 0) {
1467 tor_ftruncate(lf->fd);
1468 }
1469 }
1470}
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:1154
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:916
static int log_time_granularity
Definition: log.c:243
void flush_log_messages_from_startup(void)
Definition: log.c:1064
void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb)
Definition: log.c:1003
static char * domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
Definition: log.c:1276
void mark_logs_temp(void)
Definition: log.c:1137
static void log_free_(logfile_t *victim)
Definition: log.c:739
static log_domain_mask_t parse_log_domain(const char *domain)
Definition: log.c:1264
void logs_free_all(void)
Definition: log.c:750
void logs_flush_sigsafe(void)
Definition: log.c:796
void truncate_logs(void)
Definition: log.c:1462
void rollback_log_changes(void)
Definition: log.c:1125
void logs_set_pending_callback_callback(pending_callback_callback cb)
Definition: log.c:973
int add_callback_log(const log_severity_list_t *severity, log_callback cb)
Definition: log.c:983
void switch_logs_debug(void)
Definition: log.c:1447
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:873
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:1432
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:890
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:1022
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:855
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:842
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:1247
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:1237
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:907
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:950
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:1220
#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:822
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:940
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:1328
#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:1101
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
void tor_bug_increment_count_(void)
Definition: util_bug.c:115
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.