tor  0.4.2.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-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
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/version/git_revision.h"
37 #include "lib/log/ratelim.h"
38 #include "lib/lock/compat_mutex.h"
42 #include "lib/err/torerr.h"
43 #include "lib/intmath/bits.h"
45 #include "lib/string/printf.h"
46 #include "lib/malloc/malloc.h"
47 #include "lib/string/util_string.h"
51 #include "lib/fdio/fdio.h"
52 #include "lib/cc/ctassert.h"
53 
54 #ifdef HAVE_ANDROID_LOG_H
55 #include <android/log.h>
56 #endif // HAVE_ANDROID_LOG_H.
57 
60 #define SEVERITY_MASK_IDX(sev) ((sev) - LOG_ERR)
61 
65 #define TRUNCATED_STR "[...truncated]"
66 #define TRUNCATED_STR_LEN 14
67 
71 const int LOG_WARN_ = LOG_WARN;
72 const int LOG_NOTICE_ = LOG_NOTICE;
73 const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
74 const log_domain_mask_t LD_NET_ = LD_NET;
75 
77 typedef struct logfile_t {
78  struct logfile_t *next;
79  char *filename;
80  int fd;
81  int seems_dead;
84  int is_syslog;
85  int is_android;
86  char *android_tag;
90 } logfile_t;
91 
92 static void log_free_(logfile_t *victim);
93 #define log_free(lg) \
94  FREE_AND_NULL(logfile_t, log_free_, (lg))
95 
97 static inline const char *
98 sev_to_string(int severity)
99 {
100  switch (severity) {
101  case LOG_DEBUG: return "debug";
102  case LOG_INFO: return "info";
103  case LOG_NOTICE: return "notice";
104  case LOG_WARN: return "warn";
105  case LOG_ERR: return "err";
106  default: /* Call raw_assert, not tor_assert, since tor_assert
107  * calls log on failure. */
108  raw_assert_unreached(); return "UNKNOWN"; // LCOV_EXCL_LINE
109  }
110 }
111 
113 static inline int
115 {
116  switch (severity) {
117  case LOG_DEBUG:
118  case LOG_INFO:
119  /* All debugging messages occur in interesting places. */
120  return (domain & LD_NOFUNCNAME) == 0;
121  case LOG_NOTICE:
122  case LOG_WARN:
123  case LOG_ERR:
124  /* We care about places where bugs occur. */
125  return (domain & (LD_BUG|LD_NOFUNCNAME)) == LD_BUG;
126  default:
127  /* Call raw_assert, not tor_assert, since tor_assert calls
128  * log on failure. */
129  raw_assert(0); return 0; // LCOV_EXCL_LINE
130  }
131 }
132 
133 #ifdef HAVE_ANDROID_LOG_H
134 
137 static int
138 severity_to_android_log_priority(int severity)
139 {
140  switch (severity) {
141  case LOG_DEBUG:
142  return ANDROID_LOG_VERBOSE;
143  case LOG_INFO:
144  return ANDROID_LOG_DEBUG;
145  case LOG_NOTICE:
146  return ANDROID_LOG_INFO;
147  case LOG_WARN:
148  return ANDROID_LOG_WARN;
149  case LOG_ERR:
150  return ANDROID_LOG_ERROR;
151  default:
152  // LCOV_EXCL_START
153  raw_assert(0);
154  return 0;
155  // LCOV_EXCL_STOP
156  }
157 }
158 #endif /* defined(HAVE_ANDROID_LOG_H) */
159 
163 static int log_mutex_initialized = 0;
164 
166 static logfile_t *logfiles = NULL;
168 static int log_domains_are_logged = 0;
169 
170 #ifdef HAVE_SYSLOG_H
171 
173 static int syslog_count = 0;
174 #endif
175 
178 typedef struct pending_log_message_t {
179  int severity;
181  char *fullmsg;
182  char *msg;
184 
187 
189 static pending_callback_callback pending_cb_cb = NULL;
190 
194 
199 
202 static int queue_startup_messages = 1;
203 
205 static int pretty_fn_has_parens = 0;
206 
209 #define MAX_STARTUP_MSG_LEN (1<<16)
210 
212 #define LOCK_LOGS() STMT_BEGIN \
213  raw_assert(log_mutex_initialized); \
214  tor_mutex_acquire(&log_mutex); \
215  STMT_END
216 
217 #define UNLOCK_LOGS() STMT_BEGIN \
218  raw_assert(log_mutex_initialized); \
219  tor_mutex_release(&log_mutex); \
220  STMT_END
221 
225 
226 static void delete_log(logfile_t *victim);
227 static void close_log(logfile_t *victim);
228 static void close_log_sigsafe(logfile_t *victim);
229 
230 static char *domain_to_string(log_domain_mask_t domain,
231  char *buf, size_t buflen);
232 static inline char *format_msg(char *buf, size_t buf_len,
233  log_domain_mask_t domain, int severity, const char *funcname,
234  const char *suffix,
235  const char *format, va_list ap, size_t *msg_len_out)
236  CHECK_PRINTF(7,0);
237 
240 static char *appname = NULL;
241 
247 void
248 log_set_application_name(const char *name)
249 {
250  tor_free(appname);
251  appname = name ? tor_strdup(name) : NULL;
252 }
253 
258 int
260 {
261  (void) domain;
262  return (severity <= log_global_min_severity_);
263 }
264 
271 void
272 tor_log_string(int severity, log_domain_mask_t domain,
273  const char *function, const char *string)
274 {
275  log_fn_(severity, domain, function, "%s", string);
276 }
277 
279 static int log_time_granularity = 1;
280 
283 void
284 set_log_time_granularity(int granularity_msec)
285 {
286  log_time_granularity = granularity_msec;
287  tor_log_sigsafe_err_set_granularity(granularity_msec);
288 }
289 
293 static inline size_t
294 log_prefix_(char *buf, size_t buf_len, int severity)
295 {
296  time_t t;
297  struct timeval now;
298  struct tm tm;
299  size_t n;
300  int r, ms;
301 
302  tor_gettimeofday(&now);
303  t = (time_t)now.tv_sec;
304  ms = (int)now.tv_usec / 1000;
305  if (log_time_granularity >= 1000) {
306  t -= t % (log_time_granularity / 1000);
307  ms = 0;
308  } else {
309  ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
310  }
311 
312  n = strftime(buf, buf_len, "%b %d %H:%M:%S",
313  tor_localtime_r_msg(&t, &tm, NULL));
314  r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
315  sev_to_string(severity));
316 
317  if (r<0)
318  return buf_len-1;
319  else
320  return n+r;
321 }
322 
328 static int
329 log_tor_version(logfile_t *lf, int reset)
330 {
331  char buf[256];
332  size_t n;
333  int is_new;
334 
335  if (!lf->needs_close)
336  /* If it doesn't get closed, it isn't really a file. */
337  return 0;
338  if (lf->is_temporary)
339  /* If it's temporary, it isn't really a file. */
340  return 0;
341 
342  is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
343 
344  if (reset && !is_new)
345  /* We are resetting, but we aren't at the start of the file; no
346  * need to log again. */
347  return 0;
348  n = log_prefix_(buf, sizeof(buf), LOG_NOTICE);
349  if (appname) {
350  tor_snprintf(buf+n, sizeof(buf)-n,
351  "%s opening %slog file.\n", appname, is_new?"new ":"");
352  } else {
353  tor_snprintf(buf+n, sizeof(buf)-n,
354  "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
355  }
356  if (write_all_to_fd_minimal(lf->fd, buf, strlen(buf)) < 0) /* error */
357  return -1; /* failed */
358  return 0;
359 }
360 
366 static inline char *
367 format_msg(char *buf, size_t buf_len,
368  log_domain_mask_t domain, int severity, const char *funcname,
369  const char *suffix,
370  const char *format, va_list ap, size_t *msg_len_out)
371 {
372  size_t n;
373  int r;
374  char *end_of_prefix;
375  char *buf_end;
376 
377  raw_assert(buf_len >= 16); /* prevent integer underflow and stupidity */
378  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
379  buf_end = buf+buf_len; /* point *after* the last char we can write to */
380 
381  n = log_prefix_(buf, buf_len, severity);
382  end_of_prefix = buf+n;
383 
385  char *cp = buf+n;
386  if (cp == buf_end) goto format_msg_no_room_for_domains;
387  *cp++ = '{';
388  if (cp == buf_end) goto format_msg_no_room_for_domains;
389  cp = domain_to_string(domain, cp, (buf+buf_len-cp));
390  if (cp == buf_end) goto format_msg_no_room_for_domains;
391  *cp++ = '}';
392  if (cp == buf_end) goto format_msg_no_room_for_domains;
393  *cp++ = ' ';
394  if (cp == buf_end) goto format_msg_no_room_for_domains;
395  end_of_prefix = cp;
396  n = cp-buf;
397  format_msg_no_room_for_domains:
398  /* This will leave end_of_prefix and n unchanged, and thus cause
399  * whatever log domain string we had written to be clobbered. */
400  ;
401  }
402 
403  if (funcname && should_log_function_name(domain, severity)) {
404  r = tor_snprintf(buf+n, buf_len-n,
405  pretty_fn_has_parens ? "%s: " : "%s(): ",
406  funcname);
407  if (r<0)
408  n = strlen(buf);
409  else
410  n += r;
411  }
412 
413  if (domain == LD_BUG && buf_len-n > 6) {
414  memcpy(buf+n, "Bug: ", 6);
415  n += 5;
416  }
417 
418  r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
419  if (r < 0) {
420  /* The message was too long; overwrite the end of the buffer with
421  * "[...truncated]" */
422  if (buf_len >= TRUNCATED_STR_LEN) {
423  size_t offset = buf_len-TRUNCATED_STR_LEN;
424  /* We have an extra 2 characters after buf_len to hold the \n\0,
425  * so it's safe to add 1 to the size here. */
426  strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
427  }
428  /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
429  * Since we already subtracted 2 from buf_len, this is safe.*/
430  n = buf_len;
431  } else {
432  n += r;
433  if (suffix) {
434  size_t suffix_len = strlen(suffix);
435  if (buf_len-n >= suffix_len) {
436  memcpy(buf+n, suffix, suffix_len);
437  n += suffix_len;
438  }
439  }
440  }
441 
442  if (domain == LD_BUG &&
443  buf_len - n > strlen(tor_bug_suffix)+1) {
444  memcpy(buf+n, tor_bug_suffix, strlen(tor_bug_suffix));
445  n += strlen(tor_bug_suffix);
446  }
447 
448  buf[n]='\n';
449  buf[n+1]='\0';
450  *msg_len_out = n+1;
451  return end_of_prefix;
452 }
453 
454 /* Create a new pending_log_message_t with appropriate values */
455 static pending_log_message_t *
456 pending_log_message_new(int severity, log_domain_mask_t domain,
457  const char *fullmsg, const char *shortmsg)
458 {
459  pending_log_message_t *m = tor_malloc(sizeof(pending_log_message_t));
460  m->severity = severity;
461  m->domain = domain;
462  m->fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
463  m->msg = tor_strdup(shortmsg);
464  return m;
465 }
466 
467 #define pending_log_message_free(msg) \
468  FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
469 
471 static void
473 {
474  if (!msg)
475  return;
476  tor_free(msg->msg);
477  tor_free(msg->fullmsg);
478  tor_free(msg);
479 }
480 
484 static inline int
486 {
487  raw_assert(lf);
488  return lf->is_syslog || lf->is_android || lf->callback;
489 }
490 
494 static inline int
495 logfile_wants_message(const logfile_t *lf, int severity,
496  log_domain_mask_t domain)
497 {
498  if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
499  return 0;
500  }
501  if (! (lf->fd >= 0 || logfile_is_external(lf))) {
502  return 0;
503  }
504  if (lf->seems_dead) {
505  return 0;
506  }
507 
508  return 1;
509 }
510 
517 static inline void
518 logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
519  const char *msg_after_prefix, log_domain_mask_t domain,
520  int severity, int *callbacks_deferred)
521 {
522 
523  if (lf->is_syslog) {
524 #ifdef HAVE_SYSLOG_H
525 #ifdef MAXLINE
526  /* Some syslog implementations have limits on the length of what you can
527  * pass them, and some very old ones do not detect overflow so well.
528  * Regrettably, they call their maximum line length MAXLINE. */
529 #if MAXLINE < 64
530 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
531 #endif
532  char *m = msg_after_prefix;
533  if (msg_len >= MAXLINE)
534  m = tor_strndup(msg_after_prefix, MAXLINE-1);
535  syslog(severity, "%s", m);
536  if (m != msg_after_prefix) {
537  tor_free(m);
538  }
539 #else /* !(defined(MAXLINE)) */
540  /* We have syslog but not MAXLINE. That's promising! */
541  syslog(severity, "%s", msg_after_prefix);
542 #endif /* defined(MAXLINE) */
543 #endif /* defined(HAVE_SYSLOG_H) */
544  } else if (lf->is_android) {
545 #ifdef HAVE_ANDROID_LOG_H
546  int priority = severity_to_android_log_priority(severity);
547  __android_log_write(priority, lf->android_tag, msg_after_prefix);
548 #endif // HAVE_ANDROID_LOG_H.
549  } else if (lf->callback) {
550  if (domain & LD_NOCB) {
551  if (!*callbacks_deferred && pending_cb_messages) {
553  pending_log_message_new(severity,domain,NULL,msg_after_prefix));
554  *callbacks_deferred = 1;
555  if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
556  pending_cb_cb();
557  }
558  }
559  } else {
560  lf->callback(severity, domain, msg_after_prefix);
561  }
562  } else {
563  if (write_all_to_fd_minimal(lf->fd, buf, msg_len) < 0) { /* error */
564  /* don't log the error! mark this log entry to be blown away, and
565  * continue. */
566  lf->seems_dead = 1;
567  }
568  }
569 }
570 
575 MOCK_IMPL(STATIC void,
576 logv,(int severity, log_domain_mask_t domain, const char *funcname,
577  const char *suffix, const char *format, va_list ap))
578 {
579  char buf[10240];
580  size_t msg_len = 0;
581  int formatted = 0;
582  logfile_t *lf;
583  char *end_of_prefix=NULL;
584  int callbacks_deferred = 0;
585 
586  /* Call raw_assert, not tor_assert, since tor_assert calls log on failure. */
587  raw_assert(format);
588  /* check that severity is sane. Overrunning the masks array leads to
589  * interesting and hard to diagnose effects */
590  raw_assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
591  /* check that we've initialised the log mutex before we try to lock it */
592  raw_assert(log_mutex_initialized);
593  LOCK_LOGS();
594 
595  if ((! (domain & LD_NOCB)) && pending_cb_messages
596  && smartlist_len(pending_cb_messages))
598 
601  end_of_prefix =
602  format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
603  format, ap, &msg_len);
604  formatted = 1;
605 
607  pending_log_message_new(severity,domain,buf,end_of_prefix));
608  pending_startup_messages_len += msg_len;
609  }
610 
611  for (lf = logfiles; lf; lf = lf->next) {
612  if (! logfile_wants_message(lf, severity, domain))
613  continue;
614 
615  if (!formatted) {
616  end_of_prefix =
617  format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
618  format, ap, &msg_len);
619  formatted = 1;
620  }
621 
622  logfile_deliver(lf, buf, msg_len, end_of_prefix, domain, severity,
623  &callbacks_deferred);
624  }
625  UNLOCK_LOGS();
626 }
627 
632 void
633 tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
634 {
635  va_list ap;
636  if (severity > log_global_min_severity_)
637  return;
638  va_start(ap,format);
639 #ifdef TOR_UNIT_TESTS
640  if (domain & LD_NO_MOCK)
641  logv__real(severity, domain, NULL, NULL, format, ap);
642  else
643 #endif
644  logv(severity, domain, NULL, NULL, format, ap);
645  va_end(ap);
646 }
647 
650 static int
651 int_array_contains(const int *array, int n, int item)
652 {
653  int j;
654  for (j = 0; j < n; ++j) {
655  if (array[j] == item)
656  return 1;
657  }
658  return 0;
659 }
660 
663 void
665 {
666  const logfile_t *lf;
667  int found_real_stderr = 0;
668 
669  /* log_fds and err_fds contain matching entries: log_fds are the fds used by
670  * the log module, and err_fds are the fds used by the err module.
671  * For stdio logs, the log_fd and err_fd values are identical,
672  * and the err module closes the fd on shutdown.
673  * For file logs, the err_fd is a dup() of the log_fd,
674  * and the log and err modules both close their respective fds on shutdown.
675  * (Once all fds representing a file are closed, the underlying file is
676  * closed.)
677  */
678  int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
679  int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
680  int n_fds;
681 
682  LOCK_LOGS();
683  /* Reserve the first one for stderr. This is safe because when we daemonize,
684  * we dup2 /dev/null to stderr.
685  * For stderr, log_fds and err_fds are the same. */
686  log_fds[0] = err_fds[0] = STDERR_FILENO;
687  n_fds = 1;
688 
689  for (lf = logfiles; lf; lf = lf->next) {
690  /* Don't try callback to the control port, or syslogs: We can't
691  * do them from a signal handler. Don't try stdout: we always do stderr.
692  */
693  if (lf->is_temporary || logfile_is_external(lf)
694  || lf->seems_dead || lf->fd < 0)
695  continue;
697  (LD_BUG|LD_GENERAL)) {
698  if (lf->fd == STDERR_FILENO)
699  found_real_stderr = 1;
700  /* Avoid duplicates by checking the log module fd against log_fds */
701  if (int_array_contains(log_fds, n_fds, lf->fd))
702  continue;
703  /* Update log_fds using the log module's fd */
704  log_fds[n_fds] = lf->fd;
705  if (lf->needs_close) {
706  /* File log fds are duplicated, because close_log() closes the log
707  * module's fd, and tor_log_close_sigsafe_err_fds() closes the err
708  * module's fd. Both refer to the same file. */
709  err_fds[n_fds] = dup(lf->fd);
710  } else {
711  /* stdio log fds are not closed by the log module.
712  * tor_log_close_sigsafe_err_fds() closes stdio logs. */
713  err_fds[n_fds] = lf->fd;
714  }
715  n_fds++;
716  if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
717  break;
718  }
719  }
720 
721  if (!found_real_stderr &&
722  int_array_contains(log_fds, n_fds, STDOUT_FILENO)) {
723  /* Don't use a virtual stderr when we're also logging to stdout. */
724  raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
725  --n_fds;
726  log_fds[0] = log_fds[n_fds];
727  err_fds[0] = err_fds[n_fds];
728  }
729 
730  UNLOCK_LOGS();
731 
732  tor_log_set_sigsafe_err_fds(err_fds, n_fds);
733 }
734 
737 void
739 {
740  logfile_t *lf;
741  raw_assert(out);
742 
743  LOCK_LOGS();
744 
745  for (lf = logfiles; lf; lf = lf->next) {
746  if (lf->is_temporary || logfile_is_external(lf))
747  continue;
748  if (lf->filename == NULL)
749  continue;
750  smartlist_add_strdup(out, lf->filename);
751  }
752 
753  UNLOCK_LOGS();
754 }
755 
759 void
760 log_fn_(int severity, log_domain_mask_t domain, const char *fn,
761  const char *format, ...)
762 {
763  va_list ap;
764  if (severity > log_global_min_severity_)
765  return;
766  va_start(ap,format);
767  logv(severity, domain, fn, NULL, format, ap);
768  va_end(ap);
769 }
770 void
771 log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
772  const char *fn, const char *format, ...)
773 {
774  va_list ap;
775  char *m;
776  if (severity > log_global_min_severity_)
777  return;
778  m = rate_limit_log(ratelim, approx_time());
779  if (m == NULL)
780  return;
781  va_start(ap, format);
782  logv(severity, domain, fn, m, format, ap);
783  va_end(ap);
784  tor_free(m);
785 }
786 
788 static void
790 {
791  if (!victim)
792  return;
793  tor_free(victim->severities);
794  tor_free(victim->filename);
795  tor_free(victim->android_tag);
796  tor_free(victim);
797 }
798 
800 void
802 {
803  logfile_t *victim, *next;
804  smartlist_t *messages, *messages2;
805  LOCK_LOGS();
806  next = logfiles;
807  logfiles = NULL;
808  messages = pending_cb_messages;
809  pending_cb_messages = NULL;
810  pending_cb_cb = NULL;
811  messages2 = pending_startup_messages;
813  UNLOCK_LOGS();
814  while (next) {
815  victim = next;
816  next = next->next;
817  close_log(victim);
818  log_free(victim);
819  }
820  tor_free(appname);
821 
822  SMARTLIST_FOREACH(messages, pending_log_message_t *, msg, {
823  pending_log_message_free(msg);
824  });
825  smartlist_free(messages);
826 
827  if (messages2) {
828  SMARTLIST_FOREACH(messages2, pending_log_message_t *, msg, {
829  pending_log_message_free(msg);
830  });
831  smartlist_free(messages2);
832  }
833 
834  /* We _could_ destroy the log mutex here, but that would screw up any logs
835  * that happened between here and the end of execution. */
836 }
837 
845 void
847 {
848  logfile_t *victim, *next;
849  /* We can't LOCK_LOGS() in a signal handler, because it may call
850  * signal-unsafe functions. And we can't deallocate memory, either. */
851  next = logfiles;
852  logfiles = NULL;
853  while (next) {
854  victim = next;
855  next = next->next;
856  if (victim->needs_close) {
857  close_log_sigsafe(victim);
858  }
859  }
860 }
861 
870 static void
872 {
873  logfile_t *tmpl;
874  if (victim == logfiles)
875  logfiles = victim->next;
876  else {
877  for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
878 // raw_assert(tmpl);
879 // raw_assert(tmpl->next == victim);
880  if (!tmpl)
881  return;
882  tmpl->next = victim->next;
883  }
884  log_free(victim);
885 }
886 
890 static void
892 {
893  if (victim->needs_close && victim->fd >= 0) {
894  /* We can't do anything useful here if close() fails: we're shutting
895  * down logging, and the err module only does fatal errors. */
896  close(victim->fd);
897  victim->fd = -1;
898  }
899 }
900 
903 static void
905 {
906  if (victim->needs_close) {
907  close_log_sigsafe(victim);
908  } else if (victim->is_syslog) {
909 #ifdef HAVE_SYSLOG_H
910  if (--syslog_count == 0) {
911  /* There are no other syslogs; close the logging facility. */
912  closelog();
913  }
914 #endif /* defined(HAVE_SYSLOG_H) */
915  }
916 }
917 
921 void
922 set_log_severity_config(int loglevelMin, int loglevelMax,
923  log_severity_list_t *severity_out)
924 {
925  int i;
926  raw_assert(loglevelMin >= loglevelMax);
927  raw_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
928  raw_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
929  memset(severity_out, 0, sizeof(log_severity_list_t));
930  for (i = loglevelMin; i >= loglevelMax; --i) {
931  severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
932  }
933 }
934 
937 static void
939  const char *name, int fd)
940 {
941  logfile_t *lf;
942  lf = tor_malloc_zero(sizeof(logfile_t));
943  lf->fd = fd;
944  lf->filename = tor_strdup(name);
945  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
946  lf->next = logfiles;
947 
948  logfiles = lf;
950 }
951 
955 void
956 add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
957 {
958  LOCK_LOGS();
959  add_stream_log_impl(severity, name, fd);
960  UNLOCK_LOGS();
961 }
962 
964 void
965 init_logging(int disable_startup_queue)
966 {
967  if (!log_mutex_initialized) {
970  }
971 #ifdef __GNUC__
972  if (strchr(__PRETTY_FUNCTION__, '(')) {
974  }
975 #endif
976  if (pending_cb_messages == NULL)
977  pending_cb_messages = smartlist_new();
978  if (disable_startup_queue)
981  pending_startup_messages = smartlist_new();
982  }
983 }
984 
987 void
989 {
990  LOCK_LOGS();
991  log_domains_are_logged = enabled;
992  UNLOCK_LOGS();
993 }
994 
998 void
999 add_temp_log(int min_severity)
1000 {
1001  log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
1002  set_log_severity_config(min_severity, LOG_ERR, s);
1003  LOCK_LOGS();
1004  add_stream_log_impl(s, "<temp>", fileno(stdout));
1005  tor_free(s);
1006  logfiles->is_temporary = 1;
1007  UNLOCK_LOGS();
1008 }
1009 
1022 void
1023 logs_set_pending_callback_callback(pending_callback_callback cb)
1024 {
1025  pending_cb_cb = cb;
1026 }
1027 
1032 int
1034 {
1035  logfile_t *lf;
1036  lf = tor_malloc_zero(sizeof(logfile_t));
1037  lf->fd = -1;
1038  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1039  lf->filename = tor_strdup("<callback>");
1040  lf->callback = cb;
1041  lf->next = logfiles;
1042 
1043  LOCK_LOGS();
1044  logfiles = lf;
1046  UNLOCK_LOGS();
1047  return 0;
1048 }
1049 
1052 void
1053 change_callback_log_severity(int loglevelMin, int loglevelMax,
1054  log_callback cb)
1055 {
1056  logfile_t *lf;
1057  log_severity_list_t severities;
1058  set_log_severity_config(loglevelMin, loglevelMax, &severities);
1059  LOCK_LOGS();
1060  for (lf = logfiles; lf; lf = lf->next) {
1061  if (lf->callback == cb) {
1062  memcpy(lf->severities, &severities, sizeof(severities));
1063  }
1064  }
1066  UNLOCK_LOGS();
1067 }
1068 
1071 void
1073 {
1074  logfile_t *lf;
1075  smartlist_t *messages, *messages_tmp;
1076 
1077  LOCK_LOGS();
1078  if (!pending_cb_messages || 0 == smartlist_len(pending_cb_messages)) {
1079  UNLOCK_LOGS();
1080  return;
1081  }
1082 
1083  messages = pending_cb_messages;
1084  pending_cb_messages = smartlist_new();
1085  do {
1087  const int severity = msg->severity;
1088  const log_domain_mask_t domain = msg->domain;
1089  for (lf = logfiles; lf; lf = lf->next) {
1090  if (! lf->callback || lf->seems_dead ||
1091  ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
1092  continue;
1093  }
1094  lf->callback(severity, domain, msg->msg);
1095  }
1096  pending_log_message_free(msg);
1097  } SMARTLIST_FOREACH_END(msg);
1098  smartlist_clear(messages);
1099 
1100  messages_tmp = pending_cb_messages;
1101  pending_cb_messages = messages;
1102  messages = messages_tmp;
1103  } while (smartlist_len(messages));
1104 
1105  smartlist_free(messages);
1106 
1107  UNLOCK_LOGS();
1108 }
1109 
1113 void
1115 {
1116  logfile_t *lf;
1117 
1118  LOCK_LOGS();
1122  goto out;
1123 
1125  msg) {
1126  int callbacks_deferred = 0;
1127  for (lf = logfiles; lf; lf = lf->next) {
1128  if (! logfile_wants_message(lf, msg->severity, msg->domain))
1129  continue;
1130 
1131  /* We configure a temporary startup log that goes to stdout, so we
1132  * shouldn't replay to stdout/stderr*/
1133  if (lf->fd == STDOUT_FILENO || lf->fd == STDERR_FILENO) {
1134  continue;
1135  }
1136 
1137  logfile_deliver(lf, msg->fullmsg, strlen(msg->fullmsg), msg->msg,
1138  msg->domain, msg->severity, &callbacks_deferred);
1139  }
1140  pending_log_message_free(msg);
1141  } SMARTLIST_FOREACH_END(msg);
1142  smartlist_free(pending_startup_messages);
1143  pending_startup_messages = NULL;
1144 
1145  out:
1146  UNLOCK_LOGS();
1147 }
1148 
1151 void
1153 {
1154  logfile_t *lf, **p;
1155 
1156  LOCK_LOGS();
1157  for (p = &logfiles; *p; ) {
1158  if ((*p)->is_temporary) {
1159  lf = *p;
1160  /* we use *p here to handle the edge case of the head of the list */
1161  *p = (*p)->next;
1162  close_log(lf);
1163  log_free(lf);
1164  } else {
1165  p = &((*p)->next);
1166  }
1167  }
1168 
1170  UNLOCK_LOGS();
1171 }
1172 
1175 void
1177 {
1178  logfile_t *lf;
1179  LOCK_LOGS();
1180  for (lf = logfiles; lf; lf = lf->next)
1181  lf->is_temporary = ! lf->is_temporary;
1182  UNLOCK_LOGS();
1183  close_temp_logs();
1184 }
1185 
1187 void
1189 {
1190  logfile_t *lf;
1191  LOCK_LOGS();
1192  for (lf = logfiles; lf; lf = lf->next)
1193  lf->is_temporary = 1;
1194  UNLOCK_LOGS();
1195 }
1196 
1202 int
1204  const char *filename,
1205  int fd)
1206 {
1207  logfile_t *lf;
1208 
1209  if (fd<0)
1210  return -1;
1211  if (tor_fd_seekend(fd)<0) {
1212  close(fd);
1213  return -1;
1214  }
1215 
1216  LOCK_LOGS();
1217  add_stream_log_impl(severity, filename, fd);
1218  logfiles->needs_close = 1;
1219  lf = logfiles;
1221 
1222  if (log_tor_version(lf, 0) < 0) {
1223  delete_log(lf);
1224  }
1225  UNLOCK_LOGS();
1226 
1227  return 0;
1228 }
1229 
1230 #ifdef HAVE_SYSLOG_H
1231 
1237 int
1238 add_syslog_log(const log_severity_list_t *severity,
1239  const char* syslog_identity_tag)
1240 {
1241  logfile_t *lf;
1242  if (syslog_count++ == 0) {
1243  /* This is the first syslog. */
1244  static char buf[256];
1245  if (syslog_identity_tag) {
1246  tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
1247  } else {
1248  tor_snprintf(buf, sizeof(buf), "Tor");
1249  }
1250  openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1251  }
1252 
1253  lf = tor_malloc_zero(sizeof(logfile_t));
1254  lf->fd = -1;
1255  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1256  lf->filename = tor_strdup("<syslog>");
1257  lf->is_syslog = 1;
1258 
1259  LOCK_LOGS();
1260  lf->next = logfiles;
1261  logfiles = lf;
1263  UNLOCK_LOGS();
1264  return 0;
1265 }
1266 #endif /* defined(HAVE_SYSLOG_H) */
1267 
1268 #ifdef HAVE_ANDROID_LOG_H
1269 
1272 int
1273 add_android_log(const log_severity_list_t *severity,
1274  const char *android_tag)
1275 {
1276  logfile_t *lf = NULL;
1277 
1278  lf = tor_malloc_zero(sizeof(logfile_t));
1279  lf->fd = -1;
1280  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1281  lf->filename = tor_strdup("<android>");
1282  lf->is_android = 1;
1283 
1284  if (android_tag == NULL)
1285  lf->android_tag = tor_strdup("Tor");
1286  else {
1287  char buf[256];
1288  tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
1289  lf->android_tag = tor_strdup(buf);
1290  }
1291 
1292  LOCK_LOGS();
1293  lf->next = logfiles;
1294  logfiles = lf;
1296  UNLOCK_LOGS();
1297  return 0;
1298 }
1299 #endif /* defined(HAVE_ANDROID_LOG_H) */
1300 
1303 int
1304 parse_log_level(const char *level)
1305 {
1306  if (!strcasecmp(level, "err"))
1307  return LOG_ERR;
1308  if (!strcasecmp(level, "warn"))
1309  return LOG_WARN;
1310  if (!strcasecmp(level, "notice"))
1311  return LOG_NOTICE;
1312  if (!strcasecmp(level, "info"))
1313  return LOG_INFO;
1314  if (!strcasecmp(level, "debug"))
1315  return LOG_DEBUG;
1316  return -1;
1317 }
1318 
1320 const char *
1322 {
1323  return sev_to_string(level);
1324 }
1325 
1331 static const char *domain_list[] = {
1332  "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
1333  "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
1334  "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
1335  "SCHED", "GUARD", "CONSDIFF", "DOS", "PROCESS", "PT", "BTRACK", "MESG",
1336  NULL
1337 };
1338 
1339 CTASSERT(ARRAY_LENGTH(domain_list) == N_LOGGING_DOMAINS + 1);
1340 
1341 CTASSERT((UINT64_C(1)<<(N_LOGGING_DOMAINS-1)) < LOWEST_RESERVED_LD_FLAG_);
1342 
1345 static log_domain_mask_t
1346 parse_log_domain(const char *domain)
1347 {
1348  int i;
1349  for (i=0; domain_list[i]; ++i) {
1350  if (!strcasecmp(domain, domain_list[i]))
1351  return (UINT64_C(1)<<i);
1352  }
1353  return 0;
1354 }
1355 
1357 static char *
1358 domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
1359 {
1360  char *cp = buf;
1361  char *eos = buf+buflen;
1362 
1363  buf[0] = '\0';
1364  if (! domain)
1365  return buf;
1366  while (1) {
1367  const char *d;
1368  int bit = tor_log2(domain);
1369  size_t n;
1370  if ((unsigned)bit >= ARRAY_LENGTH(domain_list)-1 ||
1371  bit >= N_LOGGING_DOMAINS) {
1372  tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
1373  return buf+strlen(buf);
1374  }
1375  d = domain_list[bit];
1376  n = strlcpy(cp, d, eos-cp);
1377  if (n >= buflen) {
1378  tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
1379  return buf+strlen(buf);
1380  }
1381  cp += n;
1382  domain &= ~(1<<bit);
1383 
1384  if (domain == 0 || (eos-cp) < 2)
1385  return cp;
1386 
1387  memcpy(cp, ",", 2); /*Nul-terminated ,"*/
1388  cp++;
1389  }
1390 }
1391 
1409 int
1410 parse_log_severity_config(const char **cfg_ptr,
1411  log_severity_list_t *severity_out)
1412 {
1413  const char *cfg = *cfg_ptr;
1414  int got_anything = 0;
1415  int got_an_unqualified_range = 0;
1416  memset(severity_out, 0, sizeof(*severity_out));
1417 
1418  cfg = eat_whitespace(cfg);
1419  while (*cfg) {
1420  const char *dash, *space;
1421  char *sev_lo, *sev_hi;
1422  int low, high, i;
1423  log_domain_mask_t domains = ~0u;
1424 
1425  if (*cfg == '[') {
1426  int err = 0;
1427  char *domains_str;
1428  smartlist_t *domains_list;
1429  log_domain_mask_t neg_domains = 0;
1430  const char *closebracket = strchr(cfg, ']');
1431  if (!closebracket)
1432  return -1;
1433  domains = 0;
1434  domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1435  domains_list = smartlist_new();
1436  smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
1437  -1);
1438  tor_free(domains_str);
1439  SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
1440  if (!strcmp(domain, "*")) {
1441  domains = ~0u;
1442  } else {
1444  int negate=0;
1445  if (*domain == '~') {
1446  negate = 1;
1447  ++domain;
1448  }
1449  d = parse_log_domain(domain);
1450  if (!d) {
1451  log_warn(LD_CONFIG, "No such logging domain as %s", domain);
1452  err = 1;
1453  } else {
1454  if (negate)
1455  neg_domains |= d;
1456  else
1457  domains |= d;
1458  }
1459  }
1460  } SMARTLIST_FOREACH_END(domain);
1461  SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
1462  smartlist_free(domains_list);
1463  if (err)
1464  return -1;
1465  if (domains == 0 && neg_domains)
1466  domains = ~neg_domains;
1467  else
1468  domains &= ~neg_domains;
1469  cfg = eat_whitespace(closebracket+1);
1470  } else {
1471  ++got_an_unqualified_range;
1472  }
1473  if (!strcasecmpstart(cfg, "file") ||
1474  !strcasecmpstart(cfg, "stderr") ||
1475  !strcasecmpstart(cfg, "stdout") ||
1476  !strcasecmpstart(cfg, "syslog") ||
1477  !strcasecmpstart(cfg, "android")) {
1478  goto done;
1479  }
1480  if (got_an_unqualified_range > 1)
1481  return -1;
1482 
1483  space = find_whitespace(cfg);
1484  dash = strchr(cfg, '-');
1485  if (dash && dash < space) {
1486  sev_lo = tor_strndup(cfg, dash-cfg);
1487  sev_hi = tor_strndup(dash+1, space-(dash+1));
1488  } else {
1489  sev_lo = tor_strndup(cfg, space-cfg);
1490  sev_hi = tor_strdup("ERR");
1491  }
1492  low = parse_log_level(sev_lo);
1493  high = parse_log_level(sev_hi);
1494  tor_free(sev_lo);
1495  tor_free(sev_hi);
1496  if (low == -1)
1497  return -1;
1498  if (high == -1)
1499  return -1;
1500 
1501  got_anything = 1;
1502  for (i=low; i >= high; --i)
1503  severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
1504 
1505  cfg = eat_whitespace(space);
1506  }
1507 
1508  done:
1509  *cfg_ptr = cfg;
1510  return got_anything ? 0 : -1;
1511 }
1512 
1514 int
1516 {
1517  logfile_t *lf;
1518  int i;
1519  int min = LOG_ERR;
1520  for (lf = logfiles; lf; lf = lf->next) {
1521  for (i = LOG_DEBUG; i > min; --i)
1522  if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
1523  min = i;
1524  }
1525  return min;
1526 }
1527 
1529 void
1531 {
1532  logfile_t *lf;
1533  int i;
1534  LOCK_LOGS();
1535  for (lf = logfiles; lf; lf=lf->next) {
1536  for (i = LOG_DEBUG; i >= LOG_ERR; --i)
1537  lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
1538  }
1540  UNLOCK_LOGS();
1541 }
1542 
1544 void
1546 {
1547  logfile_t *lf;
1548  for (lf = logfiles; lf; lf = lf->next) {
1549  if (lf->fd >= 0) {
1550  tor_ftruncate(lf->fd);
1551  }
1552  }
1553 }
static const char * domain_list[]
Definition: log.c:1331
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:518
log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1]
Definition: log.h:141
char * filename
Definition: log.c:79
int add_file_log(const log_severity_list_t *severity, const char *filename, int fd)
Definition: log.c:1203
int write_all_to_fd_minimal(int fd, const char *buf, size_t count)
Definition: fdio.c:107
void init_logging(int disable_startup_queue)
Definition: log.c:965
Header for printf.c.
static void delete_log(logfile_t *victim)
Definition: log.c:871
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
void logs_free_all(void)
Definition: log.c:801
char * fullmsg
Definition: log.c:181
static int queue_startup_messages
Definition: log.c:202
int tor_fd_seekend(int fd)
Definition: fdio.c:60
void rollback_log_changes(void)
Definition: log.c:1176
int add_callback_log(const log_severity_list_t *severity, log_callback cb)
Definition: log.c:1033
Summarize similar messages that would otherwise flood the logs.
static int pretty_fn_has_parens
Definition: log.c:205
Definition: log.c:77
Definitions for timing-related constants.
#define CTASSERT(x)
Definition: ctassert.h:44
const int LOG_WARN_
Definition: log.c:71
int needs_close
Definition: log.c:82
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
#define LD_GENERAL
Definition: log.h:60
void tor_log_sigsafe_err_set_granularity(int ms)
Definition: torerr.c:184
static void close_log(logfile_t *victim)
Definition: log.c:904
#define LOG_INFO
Definition: log.h:43
Header for fdio.c.
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:633
void smartlist_add(smartlist_t *sl, void *element)
static const char * sev_to_string(int severity)
Definition: log.c:98
struct pending_log_message_t pending_log_message_t
static int should_log_function_name(log_domain_mask_t domain, int severity)
Definition: log.c:114
int get_min_log_level(void)
Definition: log.c:1515
struct tm * tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
Definition: time_to_tm.c:133
char * rate_limit_log(ratelim_t *lim, time_t now)
Definition: ratelim.c:41
void tor_log_get_logfile_names(smartlist_t *out)
Definition: log.c:738
void tor_log_string(int severity, log_domain_mask_t domain, const char *function, const char *string)
Definition: log.c:272
#define SEVERITY_MASK_IDX(sev)
Definition: log.c:60
Header for smartlist_split.c.
const char * find_whitespace(const char *s)
Definition: util_string.c:344
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
Definition: torerr.c:123
off_t tor_fd_getpos(int fd)
Definition: fdio.c:47
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) CHECK_PRINTF(7
Definition: log.c:367
int log_global_min_severity_
Definition: log.c:224
void set_log_time_granularity(int granularity_msec)
Definition: log.c:284
void logs_set_pending_callback_callback(pending_callback_callback cb)
Definition: log.c:1023
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
static size_t pending_startup_messages_len
Definition: log.c:198
#define LOG_NOTICE
Definition: log.h:48
Header for time_to_tm.c.
static char * domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
Definition: log.c:1358
void add_temp_log(int min_severity)
Definition: log.c:999
static char static char * appname
Definition: log.c:240
Headers for util_malloc.c.
Top-level declarations for the smartlist_t dynamic array type.
static int log_time_granularity
Definition: log.c:279
void(* log_callback)(int severity, log_domain_mask_t domain, const char *msg)
Definition: log.h:145
void tor_log_update_sigsafe_err_fds(void)
Definition: log.c:664
#define MAX_STARTUP_MSG_LEN
Definition: log.c:209
static int logfile_is_external(const logfile_t *lf)
Definition: log.c:485
static int log_tor_version(logfile_t *lf, int reset)
Definition: log.c:329
static smartlist_t * pending_startup_messages
Definition: log.c:193
#define LD_NOFUNCNAME
Definition: log.h:134
Macros for iterating over the elements of a smartlist_t.
void flush_pending_log_callbacks(void)
Definition: log.c:1072
void mark_logs_temp(void)
Definition: log.c:1188
static logfile_t * logfiles
Definition: log.c:166
struct logfile_t logfile_t
int tor_ftruncate(int fd)
Definition: fdio.c:91
void log_set_application_name(const char *name)
Definition: log.c:248
MOCK_IMPL(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:575
#define TOR_SIGSAFE_LOG_MAX_FDS
Definition: torerr.h:37
static log_domain_mask_t parse_log_domain(const char *domain)
Definition: log.c:1346
#define LD_NOCB
Definition: log.h:131
void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb)
Definition: log.c:1053
const char * eat_whitespace(const char *s)
Definition: util_string.c:268
struct logfile_t * next
Definition: log.c:78
Declare subsystem object for the logging module.
void tor_mutex_init(tor_mutex_t *m)
#define LOG_WARN
Definition: log.h:51
log_severity_list_t * severities
Definition: log.c:88
void log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format,...)
Definition: log.c:760
Header for approx_time.c.
void logs_close_sigsafe(void)
Definition: log.c:846
void flush_log_messages_from_startup(void)
Definition: log.c:1114
int parse_log_severity_config(const char **cfg_ptr, log_severity_list_t *severity_out)
Definition: log.c:1410
void truncate_logs(void)
Definition: log.c:1545
void logs_set_domain_logging(int enabled)
Definition: log.c:988
char * android_tag
Definition: log.c:86
static tor_mutex_t log_mutex
Definition: log.c:161
int tor_log2(uint64_t u64)
Definition: bits.c:16
#define LOG_ERR
Definition: log.h:54
static int log_domains_are_logged
Definition: log.c:168
log_domain_mask_t domain
Definition: log.c:180
log_callback callback
Definition: log.c:87
Compile-time assertions: CTASSERT(expression).
static size_t log_prefix_(char *buf, size_t buf_len, int severity)
Definition: log.c:294
static pending_callback_callback pending_cb_cb
Definition: log.c:189
int seems_dead
Definition: log.c:81
int parse_log_level(const char *level)
Definition: log.c:1304
#define LOCK_LOGS()
Definition: log.c:212
#define TRUNCATED_STR
Definition: log.c:65
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
static void add_stream_log_impl(const log_severity_list_t *severity, const char *name, int fd)
Definition: log.c:938
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Header for compat_mutex.c.
uint64_t log_domain_mask_t
Definition: logging_types.h:21
void close_temp_logs(void)
Definition: log.c:1152
int log_message_is_interesting(int severity, log_domain_mask_t domain)
Definition: log.c:259
#define ARRAY_LENGTH(x)
void add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
Definition: log.c:956
void switch_logs_debug(void)
Definition: log.c:1530
static int log_mutex_initialized
Definition: log.c:163
int fd
Definition: log.c:80
Header for bits.c.
const char * log_level_to_string(int level)
Definition: log.c:1321
#define UNLOCK_LOGS()
Definition: log.c:217
void set_log_severity_config(int loglevelMin, int loglevelMax, log_severity_list_t *severity_out)
Definition: log.c:922
Header for compat_string.c.
Headers for torerr.c.
time_t approx_time(void)
Definition: approx_time.c:32
int is_syslog
Definition: log.c:84
int is_temporary
Definition: log.c:83
#define LOG_DEBUG
Definition: log.h:40
#define LD_NET
Definition: log.h:64
static void close_log_sigsafe(logfile_t *victim)
Definition: log.c:891
Headers for log.c.
int is_android
Definition: log.c:85
Header for tor_gettimeofday.c.
void smartlist_clear(smartlist_t *sl)
static smartlist_t * pending_cb_messages
Definition: log.c:186
int strcasecmpstart(const char *s1, const char *s2)
Definition: util_string.c:216
int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
Definition: printf.c:41
static void log_free_(logfile_t *victim)
Definition: log.c:789
#define LOWEST_RESERVED_LD_FLAG_
Definition: log.h:123
#define LD_BUG
Definition: log.h:84
#define LD_CONFIG
Definition: log.h:66
static int int_array_contains(const int *array, int n, int item)
Definition: log.c:651
static void pending_log_message_free_(pending_log_message_t *msg)
Definition: log.c:472
static int logfile_wants_message(const logfile_t *lf, int severity, log_domain_mask_t domain)
Definition: log.c:495
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)