tor  0.4.1.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 
53 #ifdef HAVE_ANDROID_LOG_H
54 #include <android/log.h>
55 #endif // HAVE_ANDROID_LOG_H.
56 
59 #define SEVERITY_MASK_IDX(sev) ((sev) - LOG_ERR)
60 
64 #define TRUNCATED_STR "[...truncated]"
65 #define TRUNCATED_STR_LEN 14
66 
70 const int LOG_WARN_ = LOG_WARN;
71 const int LOG_NOTICE_ = LOG_NOTICE;
72 const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
73 const log_domain_mask_t LD_NET_ = LD_NET;
74 
76 typedef struct logfile_t {
77  struct logfile_t *next;
78  char *filename;
79  int fd;
80  int seems_dead;
83  int is_syslog;
84  int is_android;
85  char *android_tag;
89 } logfile_t;
90 
91 static void log_free_(logfile_t *victim);
92 #define log_free(lg) \
93  FREE_AND_NULL(logfile_t, log_free_, (lg))
94 
96 static inline const char *
97 sev_to_string(int severity)
98 {
99  switch (severity) {
100  case LOG_DEBUG: return "debug";
101  case LOG_INFO: return "info";
102  case LOG_NOTICE: return "notice";
103  case LOG_WARN: return "warn";
104  case LOG_ERR: return "err";
105  default: /* Call raw_assert, not tor_assert, since tor_assert
106  * calls log on failure. */
107  raw_assert_unreached(); return "UNKNOWN"; // LCOV_EXCL_LINE
108  }
109 }
110 
112 static inline int
114 {
115  switch (severity) {
116  case LOG_DEBUG:
117  case LOG_INFO:
118  /* All debugging messages occur in interesting places. */
119  return (domain & LD_NOFUNCNAME) == 0;
120  case LOG_NOTICE:
121  case LOG_WARN:
122  case LOG_ERR:
123  /* We care about places where bugs occur. */
124  return (domain & (LD_BUG|LD_NOFUNCNAME)) == LD_BUG;
125  default:
126  /* Call raw_assert, not tor_assert, since tor_assert calls
127  * log on failure. */
128  raw_assert(0); return 0; // LCOV_EXCL_LINE
129  }
130 }
131 
132 #ifdef HAVE_ANDROID_LOG_H
133 
136 static int
137 severity_to_android_log_priority(int severity)
138 {
139  switch (severity) {
140  case LOG_DEBUG:
141  return ANDROID_LOG_VERBOSE;
142  case LOG_INFO:
143  return ANDROID_LOG_DEBUG;
144  case LOG_NOTICE:
145  return ANDROID_LOG_INFO;
146  case LOG_WARN:
147  return ANDROID_LOG_WARN;
148  case LOG_ERR:
149  return ANDROID_LOG_ERROR;
150  default:
151  // LCOV_EXCL_START
152  raw_assert(0);
153  return 0;
154  // LCOV_EXCL_STOP
155  }
156 }
157 #endif // HAVE_ANDROID_LOG_H.
158 
162 static int log_mutex_initialized = 0;
163 
165 static logfile_t *logfiles = NULL;
167 static int log_domains_are_logged = 0;
168 
169 #ifdef HAVE_SYSLOG_H
170 
172 static int syslog_count = 0;
173 #endif
174 
177 typedef struct pending_log_message_t {
178  int severity;
180  char *fullmsg;
181  char *msg;
183 
186 
188 static pending_callback_callback pending_cb_cb = NULL;
189 
193 
198 
201 static int queue_startup_messages = 1;
202 
204 static int pretty_fn_has_parens = 0;
205 
208 #define MAX_STARTUP_MSG_LEN (1<<16)
209 
211 #define LOCK_LOGS() STMT_BEGIN \
212  raw_assert(log_mutex_initialized); \
213  tor_mutex_acquire(&log_mutex); \
214  STMT_END
215 
216 #define UNLOCK_LOGS() STMT_BEGIN \
217  raw_assert(log_mutex_initialized); \
218  tor_mutex_release(&log_mutex); \
219  STMT_END
220 
224 
225 static void delete_log(logfile_t *victim);
226 static void close_log(logfile_t *victim);
227 
228 static char *domain_to_string(log_domain_mask_t domain,
229  char *buf, size_t buflen);
230 static inline char *format_msg(char *buf, size_t buf_len,
231  log_domain_mask_t domain, int severity, const char *funcname,
232  const char *suffix,
233  const char *format, va_list ap, size_t *msg_len_out)
234  CHECK_PRINTF(7,0);
235 
238 static char *appname = NULL;
239 
245 void
246 log_set_application_name(const char *name)
247 {
248  tor_free(appname);
249  appname = name ? tor_strdup(name) : NULL;
250 }
251 
256 int
258 {
259  (void) domain;
260  return (severity <= log_global_min_severity_);
261 }
262 
269 void
270 tor_log_string(int severity, log_domain_mask_t domain,
271  const char *function, const char *string)
272 {
273  log_fn_(severity, domain, function, "%s", string);
274 }
275 
277 static int log_time_granularity = 1;
278 
281 void
282 set_log_time_granularity(int granularity_msec)
283 {
284  log_time_granularity = granularity_msec;
285  tor_log_sigsafe_err_set_granularity(granularity_msec);
286 }
287 
291 static inline size_t
292 log_prefix_(char *buf, size_t buf_len, int severity)
293 {
294  time_t t;
295  struct timeval now;
296  struct tm tm;
297  size_t n;
298  int r, ms;
299 
300  tor_gettimeofday(&now);
301  t = (time_t)now.tv_sec;
302  ms = (int)now.tv_usec / 1000;
303  if (log_time_granularity >= 1000) {
304  t -= t % (log_time_granularity / 1000);
305  ms = 0;
306  } else {
307  ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
308  }
309 
310  n = strftime(buf, buf_len, "%b %d %H:%M:%S",
311  tor_localtime_r_msg(&t, &tm, NULL));
312  r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
313  sev_to_string(severity));
314 
315  if (r<0)
316  return buf_len-1;
317  else
318  return n+r;
319 }
320 
326 static int
327 log_tor_version(logfile_t *lf, int reset)
328 {
329  char buf[256];
330  size_t n;
331  int is_new;
332 
333  if (!lf->needs_close)
334  /* If it doesn't get closed, it isn't really a file. */
335  return 0;
336  if (lf->is_temporary)
337  /* If it's temporary, it isn't really a file. */
338  return 0;
339 
340  is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;
341 
342  if (reset && !is_new)
343  /* We are resetting, but we aren't at the start of the file; no
344  * need to log again. */
345  return 0;
346  n = log_prefix_(buf, sizeof(buf), LOG_NOTICE);
347  if (appname) {
348  tor_snprintf(buf+n, sizeof(buf)-n,
349  "%s opening %slog file.\n", appname, is_new?"new ":"");
350  } else {
351  tor_snprintf(buf+n, sizeof(buf)-n,
352  "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
353  }
354  if (write_all_to_fd_minimal(lf->fd, buf, strlen(buf)) < 0) /* error */
355  return -1; /* failed */
356  return 0;
357 }
358 
364 static inline char *
365 format_msg(char *buf, size_t buf_len,
366  log_domain_mask_t domain, int severity, const char *funcname,
367  const char *suffix,
368  const char *format, va_list ap, size_t *msg_len_out)
369 {
370  size_t n;
371  int r;
372  char *end_of_prefix;
373  char *buf_end;
374 
375  raw_assert(buf_len >= 16); /* prevent integer underflow and stupidity */
376  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
377  buf_end = buf+buf_len; /* point *after* the last char we can write to */
378 
379  n = log_prefix_(buf, buf_len, severity);
380  end_of_prefix = buf+n;
381 
383  char *cp = buf+n;
384  if (cp == buf_end) goto format_msg_no_room_for_domains;
385  *cp++ = '{';
386  if (cp == buf_end) goto format_msg_no_room_for_domains;
387  cp = domain_to_string(domain, cp, (buf+buf_len-cp));
388  if (cp == buf_end) goto format_msg_no_room_for_domains;
389  *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  end_of_prefix = cp;
394  n = cp-buf;
395  format_msg_no_room_for_domains:
396  /* This will leave end_of_prefix and n unchanged, and thus cause
397  * whatever log domain string we had written to be clobbered. */
398  ;
399  }
400 
401  if (funcname && should_log_function_name(domain, severity)) {
402  r = tor_snprintf(buf+n, buf_len-n,
403  pretty_fn_has_parens ? "%s: " : "%s(): ",
404  funcname);
405  if (r<0)
406  n = strlen(buf);
407  else
408  n += r;
409  }
410 
411  if (domain == LD_BUG && buf_len-n > 6) {
412  memcpy(buf+n, "Bug: ", 6);
413  n += 5;
414  }
415 
416  r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
417  if (r < 0) {
418  /* The message was too long; overwrite the end of the buffer with
419  * "[...truncated]" */
420  if (buf_len >= TRUNCATED_STR_LEN) {
421  size_t offset = buf_len-TRUNCATED_STR_LEN;
422  /* We have an extra 2 characters after buf_len to hold the \n\0,
423  * so it's safe to add 1 to the size here. */
424  strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
425  }
426  /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
427  * Since we already subtracted 2 from buf_len, this is safe.*/
428  n = buf_len;
429  } else {
430  n += r;
431  if (suffix) {
432  size_t suffix_len = strlen(suffix);
433  if (buf_len-n >= suffix_len) {
434  memcpy(buf+n, suffix, suffix_len);
435  n += suffix_len;
436  }
437  }
438  }
439 
440  if (domain == LD_BUG &&
441  buf_len - n > strlen(tor_bug_suffix)+1) {
442  memcpy(buf+n, tor_bug_suffix, strlen(tor_bug_suffix));
443  n += strlen(tor_bug_suffix);
444  }
445 
446  buf[n]='\n';
447  buf[n+1]='\0';
448  *msg_len_out = n+1;
449  return end_of_prefix;
450 }
451 
452 /* Create a new pending_log_message_t with appropriate values */
453 static pending_log_message_t *
454 pending_log_message_new(int severity, log_domain_mask_t domain,
455  const char *fullmsg, const char *shortmsg)
456 {
457  pending_log_message_t *m = tor_malloc(sizeof(pending_log_message_t));
458  m->severity = severity;
459  m->domain = domain;
460  m->fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
461  m->msg = tor_strdup(shortmsg);
462  return m;
463 }
464 
465 #define pending_log_message_free(msg) \
466  FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
467 
469 static void
471 {
472  if (!msg)
473  return;
474  tor_free(msg->msg);
475  tor_free(msg->fullmsg);
476  tor_free(msg);
477 }
478 
482 static inline int
484 {
485  raw_assert(lf);
486  return lf->is_syslog || lf->is_android || lf->callback;
487 }
488 
492 static inline int
493 logfile_wants_message(const logfile_t *lf, int severity,
494  log_domain_mask_t domain)
495 {
496  if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
497  return 0;
498  }
499  if (! (lf->fd >= 0 || logfile_is_external(lf))) {
500  return 0;
501  }
502  if (lf->seems_dead) {
503  return 0;
504  }
505 
506  return 1;
507 }
508 
515 static inline void
516 logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len,
517  const char *msg_after_prefix, log_domain_mask_t domain,
518  int severity, int *callbacks_deferred)
519 {
520 
521  if (lf->is_syslog) {
522 #ifdef HAVE_SYSLOG_H
523 #ifdef MAXLINE
524  /* Some syslog implementations have limits on the length of what you can
525  * pass them, and some very old ones do not detect overflow so well.
526  * Regrettably, they call their maximum line length MAXLINE. */
527 #if MAXLINE < 64
528 #warn "MAXLINE is a very low number; it might not be from syslog.h after all"
529 #endif
530  char *m = msg_after_prefix;
531  if (msg_len >= MAXLINE)
532  m = tor_strndup(msg_after_prefix, MAXLINE-1);
533  syslog(severity, "%s", m);
534  if (m != msg_after_prefix) {
535  tor_free(m);
536  }
537 #else /* !(defined(MAXLINE)) */
538  /* We have syslog but not MAXLINE. That's promising! */
539  syslog(severity, "%s", msg_after_prefix);
540 #endif /* defined(MAXLINE) */
541 #endif /* defined(HAVE_SYSLOG_H) */
542  } else if (lf->is_android) {
543 #ifdef HAVE_ANDROID_LOG_H
544  int priority = severity_to_android_log_priority(severity);
545  __android_log_write(priority, lf->android_tag, msg_after_prefix);
546 #endif // HAVE_ANDROID_LOG_H.
547  } else if (lf->callback) {
548  if (domain & LD_NOCB) {
549  if (!*callbacks_deferred && pending_cb_messages) {
551  pending_log_message_new(severity,domain,NULL,msg_after_prefix));
552  *callbacks_deferred = 1;
553  if (smartlist_len(pending_cb_messages) == 1 && pending_cb_cb) {
554  pending_cb_cb();
555  }
556  }
557  } else {
558  lf->callback(severity, domain, msg_after_prefix);
559  }
560  } else {
561  if (write_all_to_fd_minimal(lf->fd, buf, msg_len) < 0) { /* error */
562  /* don't log the error! mark this log entry to be blown away, and
563  * continue. */
564  lf->seems_dead = 1;
565  }
566  }
567 }
568 
573 MOCK_IMPL(STATIC void,
574 logv,(int severity, log_domain_mask_t domain, const char *funcname,
575  const char *suffix, const char *format, va_list ap))
576 {
577  char buf[10240];
578  size_t msg_len = 0;
579  int formatted = 0;
580  logfile_t *lf;
581  char *end_of_prefix=NULL;
582  int callbacks_deferred = 0;
583 
584  /* Call raw_assert, not tor_assert, since tor_assert calls log on failure. */
585  raw_assert(format);
586  /* check that severity is sane. Overrunning the masks array leads to
587  * interesting and hard to diagnose effects */
588  raw_assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
589  /* check that we've initialised the log mutex before we try to lock it */
590  raw_assert(log_mutex_initialized);
591  LOCK_LOGS();
592 
593  if ((! (domain & LD_NOCB)) && pending_cb_messages
594  && smartlist_len(pending_cb_messages))
596 
599  end_of_prefix =
600  format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
601  format, ap, &msg_len);
602  formatted = 1;
603 
605  pending_log_message_new(severity,domain,buf,end_of_prefix));
606  pending_startup_messages_len += msg_len;
607  }
608 
609  for (lf = logfiles; lf; lf = lf->next) {
610  if (! logfile_wants_message(lf, severity, domain))
611  continue;
612 
613  if (!formatted) {
614  end_of_prefix =
615  format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
616  format, ap, &msg_len);
617  formatted = 1;
618  }
619 
620  logfile_deliver(lf, buf, msg_len, end_of_prefix, domain, severity,
621  &callbacks_deferred);
622  }
623  UNLOCK_LOGS();
624 }
625 
630 void
631 tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
632 {
633  va_list ap;
634  if (severity > log_global_min_severity_)
635  return;
636  va_start(ap,format);
637 #ifdef TOR_UNIT_TESTS
638  if (domain & LD_NO_MOCK)
639  logv__real(severity, domain, NULL, NULL, format, ap);
640  else
641 #endif
642  logv(severity, domain, NULL, NULL, format, ap);
643  va_end(ap);
644 }
645 
648 static int
649 int_array_contains(const int *array, int n, int item)
650 {
651  int j;
652  for (j = 0; j < n; ++j) {
653  if (array[j] == item)
654  return 1;
655  }
656  return 0;
657 }
658 
661 void
663 {
664  const logfile_t *lf;
665  int found_real_stderr = 0;
666 
667  int fds[TOR_SIGSAFE_LOG_MAX_FDS];
668  int n_fds;
669 
670  LOCK_LOGS();
671  /* Reserve the first one for stderr. This is safe because when we daemonize,
672  * we dup2 /dev/null to stderr, */
673  fds[0] = STDERR_FILENO;
674  n_fds = 1;
675 
676  for (lf = logfiles; lf; lf = lf->next) {
677  /* Don't try callback to the control port, or syslogs: We can't
678  * do them from a signal handler. Don't try stdout: we always do stderr.
679  */
680  if (lf->is_temporary || logfile_is_external(lf)
681  || lf->seems_dead || lf->fd < 0)
682  continue;
684  (LD_BUG|LD_GENERAL)) {
685  if (lf->fd == STDERR_FILENO)
686  found_real_stderr = 1;
687  /* Avoid duplicates */
688  if (int_array_contains(fds, n_fds, lf->fd))
689  continue;
690  fds[n_fds++] = lf->fd;
691  if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
692  break;
693  }
694  }
695 
696  if (!found_real_stderr &&
697  int_array_contains(fds, n_fds, STDOUT_FILENO)) {
698  /* Don't use a virtual stderr when we're also logging to stdout. */
699  raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
700  fds[0] = fds[--n_fds];
701  }
702 
703  UNLOCK_LOGS();
704 
705  tor_log_set_sigsafe_err_fds(fds, n_fds);
706 }
707 
710 void
712 {
713  logfile_t *lf;
714  raw_assert(out);
715 
716  LOCK_LOGS();
717 
718  for (lf = logfiles; lf; lf = lf->next) {
719  if (lf->is_temporary || logfile_is_external(lf))
720  continue;
721  if (lf->filename == NULL)
722  continue;
723  smartlist_add_strdup(out, lf->filename);
724  }
725 
726  UNLOCK_LOGS();
727 }
728 
732 void
733 log_fn_(int severity, log_domain_mask_t domain, const char *fn,
734  const char *format, ...)
735 {
736  va_list ap;
737  if (severity > log_global_min_severity_)
738  return;
739  va_start(ap,format);
740  logv(severity, domain, fn, NULL, format, ap);
741  va_end(ap);
742 }
743 void
744 log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
745  const char *fn, const char *format, ...)
746 {
747  va_list ap;
748  char *m;
749  if (severity > log_global_min_severity_)
750  return;
751  m = rate_limit_log(ratelim, approx_time());
752  if (m == NULL)
753  return;
754  va_start(ap, format);
755  logv(severity, domain, fn, m, format, ap);
756  va_end(ap);
757  tor_free(m);
758 }
759 
761 static void
763 {
764  if (!victim)
765  return;
766  tor_free(victim->severities);
767  tor_free(victim->filename);
768  tor_free(victim->android_tag);
769  tor_free(victim);
770 }
771 
773 void
775 {
776  logfile_t *victim, *next;
777  smartlist_t *messages, *messages2;
778  LOCK_LOGS();
779  next = logfiles;
780  logfiles = NULL;
781  messages = pending_cb_messages;
782  pending_cb_messages = NULL;
783  pending_cb_cb = NULL;
784  messages2 = pending_startup_messages;
786  UNLOCK_LOGS();
787  while (next) {
788  victim = next;
789  next = next->next;
790  close_log(victim);
791  log_free(victim);
792  }
793  tor_free(appname);
794 
795  SMARTLIST_FOREACH(messages, pending_log_message_t *, msg, {
796  pending_log_message_free(msg);
797  });
798  smartlist_free(messages);
799 
800  if (messages2) {
801  SMARTLIST_FOREACH(messages2, pending_log_message_t *, msg, {
802  pending_log_message_free(msg);
803  });
804  smartlist_free(messages2);
805  }
806 
807  /* We _could_ destroy the log mutex here, but that would screw up any logs
808  * that happened between here and the end of execution. */
809 }
810 
819 static void
821 {
822  logfile_t *tmpl;
823  if (victim == logfiles)
824  logfiles = victim->next;
825  else {
826  for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
827 // raw_assert(tmpl);
828 // raw_assert(tmpl->next == victim);
829  if (!tmpl)
830  return;
831  tmpl->next = victim->next;
832  }
833  log_free(victim);
834 }
835 
838 static void
840 {
841  if (victim->needs_close && victim->fd >= 0) {
842  close(victim->fd);
843  victim->fd = -1;
844  } else if (victim->is_syslog) {
845 #ifdef HAVE_SYSLOG_H
846  if (--syslog_count == 0) {
847  /* There are no other syslogs; close the logging facility. */
848  closelog();
849  }
850 #endif /* defined(HAVE_SYSLOG_H) */
851  }
852 }
853 
857 void
858 set_log_severity_config(int loglevelMin, int loglevelMax,
859  log_severity_list_t *severity_out)
860 {
861  int i;
862  raw_assert(loglevelMin >= loglevelMax);
863  raw_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
864  raw_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
865  memset(severity_out, 0, sizeof(log_severity_list_t));
866  for (i = loglevelMin; i >= loglevelMax; --i) {
867  severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
868  }
869 }
870 
873 static void
875  const char *name, int fd)
876 {
877  logfile_t *lf;
878  lf = tor_malloc_zero(sizeof(logfile_t));
879  lf->fd = fd;
880  lf->filename = tor_strdup(name);
881  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
882  lf->next = logfiles;
883 
884  logfiles = lf;
886 }
887 
891 void
892 add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
893 {
894  LOCK_LOGS();
895  add_stream_log_impl(severity, name, fd);
896  UNLOCK_LOGS();
897 }
898 
900 void
901 init_logging(int disable_startup_queue)
902 {
903  if (!log_mutex_initialized) {
906  }
907 #ifdef __GNUC__
908  if (strchr(__PRETTY_FUNCTION__, '(')) {
910  }
911 #endif
912  if (pending_cb_messages == NULL)
913  pending_cb_messages = smartlist_new();
914  if (disable_startup_queue)
917  pending_startup_messages = smartlist_new();
918  }
919 }
920 
923 void
925 {
926  LOCK_LOGS();
927  log_domains_are_logged = enabled;
928  UNLOCK_LOGS();
929 }
930 
934 void
935 add_temp_log(int min_severity)
936 {
937  log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
938  set_log_severity_config(min_severity, LOG_ERR, s);
939  LOCK_LOGS();
940  add_stream_log_impl(s, "<temp>", fileno(stdout));
941  tor_free(s);
942  logfiles->is_temporary = 1;
943  UNLOCK_LOGS();
944 }
945 
958 void
959 logs_set_pending_callback_callback(pending_callback_callback cb)
960 {
961  pending_cb_cb = cb;
962 }
963 
968 int
970 {
971  logfile_t *lf;
972  lf = tor_malloc_zero(sizeof(logfile_t));
973  lf->fd = -1;
974  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
975  lf->filename = tor_strdup("<callback>");
976  lf->callback = cb;
977  lf->next = logfiles;
978 
979  LOCK_LOGS();
980  logfiles = lf;
982  UNLOCK_LOGS();
983  return 0;
984 }
985 
988 void
989 change_callback_log_severity(int loglevelMin, int loglevelMax,
990  log_callback cb)
991 {
992  logfile_t *lf;
993  log_severity_list_t severities;
994  set_log_severity_config(loglevelMin, loglevelMax, &severities);
995  LOCK_LOGS();
996  for (lf = logfiles; lf; lf = lf->next) {
997  if (lf->callback == cb) {
998  memcpy(lf->severities, &severities, sizeof(severities));
999  }
1000  }
1002  UNLOCK_LOGS();
1003 }
1004 
1007 void
1009 {
1010  logfile_t *lf;
1011  smartlist_t *messages, *messages_tmp;
1012 
1013  LOCK_LOGS();
1014  if (!pending_cb_messages || 0 == smartlist_len(pending_cb_messages)) {
1015  UNLOCK_LOGS();
1016  return;
1017  }
1018 
1019  messages = pending_cb_messages;
1020  pending_cb_messages = smartlist_new();
1021  do {
1023  const int severity = msg->severity;
1024  const int domain = msg->domain;
1025  for (lf = logfiles; lf; lf = lf->next) {
1026  if (! lf->callback || lf->seems_dead ||
1027  ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
1028  continue;
1029  }
1030  lf->callback(severity, domain, msg->msg);
1031  }
1032  pending_log_message_free(msg);
1033  } SMARTLIST_FOREACH_END(msg);
1034  smartlist_clear(messages);
1035 
1036  messages_tmp = pending_cb_messages;
1037  pending_cb_messages = messages;
1038  messages = messages_tmp;
1039  } while (smartlist_len(messages));
1040 
1041  smartlist_free(messages);
1042 
1043  UNLOCK_LOGS();
1044 }
1045 
1049 void
1051 {
1052  logfile_t *lf;
1053 
1054  LOCK_LOGS();
1058  goto out;
1059 
1061  msg) {
1062  int callbacks_deferred = 0;
1063  for (lf = logfiles; lf; lf = lf->next) {
1064  if (! logfile_wants_message(lf, msg->severity, msg->domain))
1065  continue;
1066 
1067  /* We configure a temporary startup log that goes to stdout, so we
1068  * shouldn't replay to stdout/stderr*/
1069  if (lf->fd == STDOUT_FILENO || lf->fd == STDERR_FILENO) {
1070  continue;
1071  }
1072 
1073  logfile_deliver(lf, msg->fullmsg, strlen(msg->fullmsg), msg->msg,
1074  msg->domain, msg->severity, &callbacks_deferred);
1075  }
1076  pending_log_message_free(msg);
1077  } SMARTLIST_FOREACH_END(msg);
1078  smartlist_free(pending_startup_messages);
1079  pending_startup_messages = NULL;
1080 
1081  out:
1082  UNLOCK_LOGS();
1083 }
1084 
1087 void
1089 {
1090  logfile_t *lf, **p;
1091 
1092  LOCK_LOGS();
1093  for (p = &logfiles; *p; ) {
1094  if ((*p)->is_temporary) {
1095  lf = *p;
1096  /* we use *p here to handle the edge case of the head of the list */
1097  *p = (*p)->next;
1098  close_log(lf);
1099  log_free(lf);
1100  } else {
1101  p = &((*p)->next);
1102  }
1103  }
1104 
1106  UNLOCK_LOGS();
1107 }
1108 
1111 void
1113 {
1114  logfile_t *lf;
1115  LOCK_LOGS();
1116  for (lf = logfiles; lf; lf = lf->next)
1117  lf->is_temporary = ! lf->is_temporary;
1118  UNLOCK_LOGS();
1119  close_temp_logs();
1120 }
1121 
1123 void
1125 {
1126  logfile_t *lf;
1127  LOCK_LOGS();
1128  for (lf = logfiles; lf; lf = lf->next)
1129  lf->is_temporary = 1;
1130  UNLOCK_LOGS();
1131 }
1132 
1138 int
1140  const char *filename,
1141  int fd)
1142 {
1143  logfile_t *lf;
1144 
1145  if (fd<0)
1146  return -1;
1147  if (tor_fd_seekend(fd)<0) {
1148  close(fd);
1149  return -1;
1150  }
1151 
1152  LOCK_LOGS();
1153  add_stream_log_impl(severity, filename, fd);
1154  logfiles->needs_close = 1;
1155  lf = logfiles;
1157 
1158  if (log_tor_version(lf, 0) < 0) {
1159  delete_log(lf);
1160  }
1161  UNLOCK_LOGS();
1162 
1163  return 0;
1164 }
1165 
1166 #ifdef HAVE_SYSLOG_H
1167 
1173 int
1174 add_syslog_log(const log_severity_list_t *severity,
1175  const char* syslog_identity_tag)
1176 {
1177  logfile_t *lf;
1178  if (syslog_count++ == 0) {
1179  /* This is the first syslog. */
1180  static char buf[256];
1181  if (syslog_identity_tag) {
1182  tor_snprintf(buf, sizeof(buf), "Tor-%s", syslog_identity_tag);
1183  } else {
1184  tor_snprintf(buf, sizeof(buf), "Tor");
1185  }
1186  openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1187  }
1188 
1189  lf = tor_malloc_zero(sizeof(logfile_t));
1190  lf->fd = -1;
1191  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1192  lf->filename = tor_strdup("<syslog>");
1193  lf->is_syslog = 1;
1194 
1195  LOCK_LOGS();
1196  lf->next = logfiles;
1197  logfiles = lf;
1199  UNLOCK_LOGS();
1200  return 0;
1201 }
1202 #endif /* defined(HAVE_SYSLOG_H) */
1203 
1204 #ifdef HAVE_ANDROID_LOG_H
1205 
1208 int
1209 add_android_log(const log_severity_list_t *severity,
1210  const char *android_tag)
1211 {
1212  logfile_t *lf = NULL;
1213 
1214  lf = tor_malloc_zero(sizeof(logfile_t));
1215  lf->fd = -1;
1216  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
1217  lf->filename = tor_strdup("<android>");
1218  lf->is_android = 1;
1219 
1220  if (android_tag == NULL)
1221  lf->android_tag = tor_strdup("Tor");
1222  else {
1223  char buf[256];
1224  tor_snprintf(buf, sizeof(buf), "Tor-%s", android_tag);
1225  lf->android_tag = tor_strdup(buf);
1226  }
1227 
1228  LOCK_LOGS();
1229  lf->next = logfiles;
1230  logfiles = lf;
1232  UNLOCK_LOGS();
1233  return 0;
1234 }
1235 #endif // HAVE_ANDROID_LOG_H.
1236 
1239 int
1240 parse_log_level(const char *level)
1241 {
1242  if (!strcasecmp(level, "err"))
1243  return LOG_ERR;
1244  if (!strcasecmp(level, "warn"))
1245  return LOG_WARN;
1246  if (!strcasecmp(level, "notice"))
1247  return LOG_NOTICE;
1248  if (!strcasecmp(level, "info"))
1249  return LOG_INFO;
1250  if (!strcasecmp(level, "debug"))
1251  return LOG_DEBUG;
1252  return -1;
1253 }
1254 
1256 const char *
1258 {
1259  return sev_to_string(level);
1260 }
1261 
1267 static const char *domain_list[] = {
1268  "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
1269  "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
1270  "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
1271  "SCHED", "GUARD", "CONSDIFF", "DOS", "PROCESS", "PT", "BTRACK", NULL
1272 };
1273 
1276 static log_domain_mask_t
1277 parse_log_domain(const char *domain)
1278 {
1279  int i;
1280  for (i=0; domain_list[i]; ++i) {
1281  if (!strcasecmp(domain, domain_list[i]))
1282  return (1u<<i);
1283  }
1284  return 0;
1285 }
1286 
1288 static char *
1289 domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
1290 {
1291  char *cp = buf;
1292  char *eos = buf+buflen;
1293 
1294  buf[0] = '\0';
1295  if (! domain)
1296  return buf;
1297  while (1) {
1298  const char *d;
1299  int bit = tor_log2(domain);
1300  size_t n;
1301  if ((unsigned)bit >= ARRAY_LENGTH(domain_list)-1 ||
1302  bit >= N_LOGGING_DOMAINS) {
1303  tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
1304  return buf+strlen(buf);
1305  }
1306  d = domain_list[bit];
1307  n = strlcpy(cp, d, eos-cp);
1308  if (n >= buflen) {
1309  tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
1310  return buf+strlen(buf);
1311  }
1312  cp += n;
1313  domain &= ~(1<<bit);
1314 
1315  if (domain == 0 || (eos-cp) < 2)
1316  return cp;
1317 
1318  memcpy(cp, ",", 2); /*Nul-terminated ,"*/
1319  cp++;
1320  }
1321 }
1322 
1340 int
1341 parse_log_severity_config(const char **cfg_ptr,
1342  log_severity_list_t *severity_out)
1343 {
1344  const char *cfg = *cfg_ptr;
1345  int got_anything = 0;
1346  int got_an_unqualified_range = 0;
1347  memset(severity_out, 0, sizeof(*severity_out));
1348 
1349  cfg = eat_whitespace(cfg);
1350  while (*cfg) {
1351  const char *dash, *space;
1352  char *sev_lo, *sev_hi;
1353  int low, high, i;
1354  log_domain_mask_t domains = ~0u;
1355 
1356  if (*cfg == '[') {
1357  int err = 0;
1358  char *domains_str;
1359  smartlist_t *domains_list;
1360  log_domain_mask_t neg_domains = 0;
1361  const char *closebracket = strchr(cfg, ']');
1362  if (!closebracket)
1363  return -1;
1364  domains = 0;
1365  domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1366  domains_list = smartlist_new();
1367  smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
1368  -1);
1369  tor_free(domains_str);
1370  SMARTLIST_FOREACH_BEGIN(domains_list, const char *, domain) {
1371  if (!strcmp(domain, "*")) {
1372  domains = ~0u;
1373  } else {
1374  int d;
1375  int negate=0;
1376  if (*domain == '~') {
1377  negate = 1;
1378  ++domain;
1379  }
1380  d = parse_log_domain(domain);
1381  if (!d) {
1382  log_warn(LD_CONFIG, "No such logging domain as %s", domain);
1383  err = 1;
1384  } else {
1385  if (negate)
1386  neg_domains |= d;
1387  else
1388  domains |= d;
1389  }
1390  }
1391  } SMARTLIST_FOREACH_END(domain);
1392  SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
1393  smartlist_free(domains_list);
1394  if (err)
1395  return -1;
1396  if (domains == 0 && neg_domains)
1397  domains = ~neg_domains;
1398  else
1399  domains &= ~neg_domains;
1400  cfg = eat_whitespace(closebracket+1);
1401  } else {
1402  ++got_an_unqualified_range;
1403  }
1404  if (!strcasecmpstart(cfg, "file") ||
1405  !strcasecmpstart(cfg, "stderr") ||
1406  !strcasecmpstart(cfg, "stdout") ||
1407  !strcasecmpstart(cfg, "syslog") ||
1408  !strcasecmpstart(cfg, "android")) {
1409  goto done;
1410  }
1411  if (got_an_unqualified_range > 1)
1412  return -1;
1413 
1414  space = find_whitespace(cfg);
1415  dash = strchr(cfg, '-');
1416  if (dash && dash < space) {
1417  sev_lo = tor_strndup(cfg, dash-cfg);
1418  sev_hi = tor_strndup(dash+1, space-(dash+1));
1419  } else {
1420  sev_lo = tor_strndup(cfg, space-cfg);
1421  sev_hi = tor_strdup("ERR");
1422  }
1423  low = parse_log_level(sev_lo);
1424  high = parse_log_level(sev_hi);
1425  tor_free(sev_lo);
1426  tor_free(sev_hi);
1427  if (low == -1)
1428  return -1;
1429  if (high == -1)
1430  return -1;
1431 
1432  got_anything = 1;
1433  for (i=low; i >= high; --i)
1434  severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;
1435 
1436  cfg = eat_whitespace(space);
1437  }
1438 
1439  done:
1440  *cfg_ptr = cfg;
1441  return got_anything ? 0 : -1;
1442 }
1443 
1445 int
1447 {
1448  logfile_t *lf;
1449  int i;
1450  int min = LOG_ERR;
1451  for (lf = logfiles; lf; lf = lf->next) {
1452  for (i = LOG_DEBUG; i > min; --i)
1453  if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
1454  min = i;
1455  }
1456  return min;
1457 }
1458 
1460 void
1462 {
1463  logfile_t *lf;
1464  int i;
1465  LOCK_LOGS();
1466  for (lf = logfiles; lf; lf=lf->next) {
1467  for (i = LOG_DEBUG; i >= LOG_ERR; --i)
1468  lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
1469  }
1471  UNLOCK_LOGS();
1472 }
1473 
1475 void
1477 {
1478  logfile_t *lf;
1479  for (lf = logfiles; lf; lf = lf->next) {
1480  if (lf->fd >= 0) {
1481  tor_ftruncate(lf->fd);
1482  }
1483  }
1484 }
static const char * domain_list[]
Definition: log.c:1267
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:516
log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1]
Definition: log.h:139
char * filename
Definition: log.c:78
int add_file_log(const log_severity_list_t *severity, const char *filename, int fd)
Definition: log.c:1139
int write_all_to_fd_minimal(int fd, const char *buf, size_t count)
Definition: fdio.c:103
void init_logging(int disable_startup_queue)
Definition: log.c:901
Header for printf.c.
static void delete_log(logfile_t *victim)
Definition: log.c:820
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
void logs_free_all(void)
Definition: log.c:774
uint32_t log_domain_mask_t
Definition: log.h:132
char * fullmsg
Definition: log.c:180
static int queue_startup_messages
Definition: log.c:201
int tor_fd_seekend(int fd)
Definition: fdio.c:56
void rollback_log_changes(void)
Definition: log.c:1112
int add_callback_log(const log_severity_list_t *severity, log_callback cb)
Definition: log.c:969
Summarize similar messages that would otherwise flood the logs.
static int pretty_fn_has_parens
Definition: log.c:204
Definition: log.c:76
Definitions for timing-related constants.
const int LOG_WARN_
Definition: log.c:70
int needs_close
Definition: log.c:81
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
#define LD_GENERAL
Definition: log.h:58
void(* log_callback)(int severity, uint32_t domain, const char *msg)
Definition: log.h:143
void tor_log_sigsafe_err_set_granularity(int ms)
Definition: torerr.c:140
static void close_log(logfile_t *victim)
Definition: log.c:839
#define LOG_INFO
Definition: log.h:41
Header for fdio.c.
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:631
void smartlist_add(smartlist_t *sl, void *element)
static const char * sev_to_string(int severity)
Definition: log.c:97
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:113
int get_min_log_level(void)
Definition: log.c:1446
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:711
void tor_log_string(int severity, log_domain_mask_t domain, const char *function, const char *string)
Definition: log.c:270
#define SEVERITY_MASK_IDX(sev)
Definition: log.c:59
Header for smartlist_split.c.
const char * find_whitespace(const char *s)
Definition: util_string.c:347
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
Definition: torerr.c:115
off_t tor_fd_getpos(int fd)
Definition: fdio.c:43
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:365
int log_global_min_severity_
Definition: log.c:223
void set_log_time_granularity(int granularity_msec)
Definition: log.c:282
void logs_set_pending_callback_callback(pending_callback_callback cb)
Definition: log.c:959
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
static size_t pending_startup_messages_len
Definition: log.c:197
#define LOG_NOTICE
Definition: log.h:46
Header for time_to_tm.c.
static char * domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
Definition: log.c:1289
void add_temp_log(int min_severity)
Definition: log.c:935
static char static char * appname
Definition: log.c:238
Headers for util_malloc.c.
Top-level declarations for the smartlist_t dynamic array type.
static int log_time_granularity
Definition: log.c:277
void tor_log_update_sigsafe_err_fds(void)
Definition: log.c:662
#define MAX_STARTUP_MSG_LEN
Definition: log.c:208
static int logfile_is_external(const logfile_t *lf)
Definition: log.c:483
static int log_tor_version(logfile_t *lf, int reset)
Definition: log.c:327
static smartlist_t * pending_startup_messages
Definition: log.c:192
#define LD_NOFUNCNAME
Definition: log.h:124
Macros for iterating over the elements of a smartlist_t.
void flush_pending_log_callbacks(void)
Definition: log.c:1008
void mark_logs_temp(void)
Definition: log.c:1124
static logfile_t * logfiles
Definition: log.c:165
struct logfile_t logfile_t
int tor_ftruncate(int fd)
Definition: fdio.c:87
void log_set_application_name(const char *name)
Definition: log.c:246
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:573
#define TOR_SIGSAFE_LOG_MAX_FDS
Definition: torerr.h:37
static log_domain_mask_t parse_log_domain(const char *domain)
Definition: log.c:1277
#define LD_NOCB
Definition: log.h:121
void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb)
Definition: log.c:989
const char * eat_whitespace(const char *s)
Definition: util_string.c:271
struct logfile_t * next
Definition: log.c:77
Declare subsystem object for the logging module.
void tor_mutex_init(tor_mutex_t *m)
#define LOG_WARN
Definition: log.h:49
log_severity_list_t * severities
Definition: log.c:87
void log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format,...)
Definition: log.c:733
Header for approx_time.c.
void flush_log_messages_from_startup(void)
Definition: log.c:1050
int parse_log_severity_config(const char **cfg_ptr, log_severity_list_t *severity_out)
Definition: log.c:1341
void truncate_logs(void)
Definition: log.c:1476
void logs_set_domain_logging(int enabled)
Definition: log.c:924
char * android_tag
Definition: log.c:85
static tor_mutex_t log_mutex
Definition: log.c:160
int tor_log2(uint64_t u64)
Definition: bits.c:16
#define LOG_ERR
Definition: log.h:52
static int log_domains_are_logged
Definition: log.c:167
log_domain_mask_t domain
Definition: log.c:179
log_callback callback
Definition: log.c:86
static size_t log_prefix_(char *buf, size_t buf_len, int severity)
Definition: log.c:292
static pending_callback_callback pending_cb_cb
Definition: log.c:188
int seems_dead
Definition: log.c:80
int parse_log_level(const char *level)
Definition: log.c:1240
#define LOCK_LOGS()
Definition: log.c:211
#define TRUNCATED_STR
Definition: log.c:64
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:874
#define SMARTLIST_FOREACH(sl, type, var, cmd)
Header for compat_mutex.c.
void close_temp_logs(void)
Definition: log.c:1088
int log_message_is_interesting(int severity, log_domain_mask_t domain)
Definition: log.c:257
#define ARRAY_LENGTH(x)
void add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
Definition: log.c:892
void switch_logs_debug(void)
Definition: log.c:1461
static int log_mutex_initialized
Definition: log.c:162
int fd
Definition: log.c:79
Header for bits.c.
const char * log_level_to_string(int level)
Definition: log.c:1257
#define UNLOCK_LOGS()
Definition: log.c:216
void set_log_severity_config(int loglevelMin, int loglevelMax, log_severity_list_t *severity_out)
Definition: log.c:858
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:83
int is_temporary
Definition: log.c:82
#define LOG_DEBUG
Definition: log.h:38
#define N_LOGGING_DOMAINS
Definition: log.h:117
#define LD_NET
Definition: log.h:62
Headers for log.c.
int is_android
Definition: log.c:84
Header for tor_gettimeofday.c.
void smartlist_clear(smartlist_t *sl)
static smartlist_t * pending_cb_messages
Definition: log.c:185
int strcasecmpstart(const char *s1, const char *s2)
Definition: util_string.c:219
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:762
#define LD_BUG
Definition: log.h:82
#define LD_CONFIG
Definition: log.h:64
static int int_array_contains(const int *array, int n, int item)
Definition: log.c:649
static void pending_log_message_free_(pending_log_message_t *msg)
Definition: log.c:470
static int logfile_wants_message(const logfile_t *lf, int severity, log_domain_mask_t domain)
Definition: log.c:493
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)