tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

log.c (43069B)


      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"
     37 #include "lib/version/git_revision.h"
     38 #include "lib/log/ratelim.h"
     39 #include "lib/lock/compat_mutex.h"
     40 #include "lib/smartlist_core/smartlist_core.h"
     41 #include "lib/smartlist_core/smartlist_foreach.h"
     42 #include "lib/smartlist_core/smartlist_split.h"
     43 #include "lib/err/torerr.h"
     44 #include "lib/intmath/bits.h"
     45 #include "lib/string/compat_string.h"
     46 #include "lib/string/printf.h"
     47 #include "lib/malloc/malloc.h"
     48 #include "lib/string/util_string.h"
     49 #include "lib/wallclock/tor_gettimeofday.h"
     50 #include "lib/wallclock/approx_time.h"
     51 #include "lib/wallclock/time_to_tm.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) */
     64 const int LOG_WARN_ = LOG_WARN;
     65 const int LOG_NOTICE_ = LOG_NOTICE;
     66 const log_domain_mask_t LD_GENERAL_ = LD_GENERAL;
     67 const log_domain_mask_t LD_NET_ = LD_NET;
     68 
     69 /** Information for a single logfile; only used in log.c */
     70 typedef 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 
     83 static 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. */
     88 static inline const char *
     89 sev_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. */
    104 static inline int
    105 should_log_function_name(log_domain_mask_t domain, int severity)
    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. */
    125 static tor_mutex_t log_mutex;
    126 /** True iff we have initialized log_mutex */
    127 static int log_mutex_initialized = 0;
    128 
    129 /** Linked list of logfile_t. */
    130 static logfile_t *logfiles = NULL;
    131 /** Boolean: do we report logging domains? */
    132 static int log_domains_are_logged = 0;
    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. */
    137 static 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. */
    142 typedef 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 */
    147 } pending_log_message_t;
    148 
    149 /** Log messages waiting to be replayed onto callback-based logs */
    150 static smartlist_t *pending_cb_messages = NULL;
    151 
    152 /** Callback to invoke when pending_cb_messages becomes nonempty. */
    153 static pending_callback_callback pending_cb_cb = NULL;
    154 
    155 /** Log messages waiting to be replayed once the logging system is initialized.
    156 */
    157 static smartlist_t *pending_startup_messages = NULL;
    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.) */
    162 static size_t pending_startup_messages_len;
    163 
    164 /** True iff we should store messages while waiting for the logs to get
    165 * configured. */
    166 static int queue_startup_messages = 1;
    167 
    168 /** True iff __PRETTY_FUNCTION__ includes parenthesized arguments. */
    169 static 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.  */
    188 int log_global_min_severity_ = LOG_NOTICE;
    189 
    190 static void delete_log(logfile_t *victim);
    191 static void close_log(logfile_t *victim);
    192 static void close_log_sigsafe(logfile_t *victim);
    193 
    194 static char *domain_to_string(log_domain_mask_t domain,
    195                             char *buf, size_t buflen);
    196 static 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. */
    204 static 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. */
    211 void
    212 log_set_application_name(const char *name)
    213 {
    214  tor_free(appname);
    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. */
    222 int
    223 log_message_is_interesting(int severity, log_domain_mask_t domain)
    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 */
    235 void
    236 tor_log_string(int severity, log_domain_mask_t domain,
    237               const char *function, const char *string)
    238 {
    239  log_fn_(severity, domain, function, "%s", string);
    240 }
    241 
    242 /** Log time granularity in milliseconds. */
    243 static int log_time_granularity = 1;
    244 
    245 /** Define log time granularity for all logs to be <b>granularity_msec</b>
    246 * milliseconds. */
    247 MOCK_IMPL(void,
    248 set_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 */
    257 static inline size_t
    258 log_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 */
    292 static int
    293 log_tor_version(logfile_t *lf, int reset)
    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 */
    330 static inline char *
    331 format_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 
    348  if (log_domains_are_logged) {
    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 */
    419 static pending_log_message_t *
    420 pending_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>. */
    435 static void
    436 pending_log_message_free_(pending_log_message_t *msg)
    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. */
    448 static inline int
    449 logfile_is_external(const logfile_t *lf)
    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 */
    458 static inline int
    459 logfile_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. */
    481 static inline void
    482 logfile_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) {
    511        smartlist_add(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) {
    515          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 */
    534 MOCK_IMPL(STATIC void,
    535 logv,(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))
    555    flush_pending_log_callbacks();
    556 
    557  if (queue_startup_messages &&
    558      pending_startup_messages_len < MAX_STARTUP_MSG_LEN) {
    559    end_of_prefix =
    560      format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
    561      format, ap, &msg_len);
    562    formatted = 1;
    563 
    564    smartlist_add(pending_startup_messages,
    565      pending_log_message_new(severity,domain,buf,end_of_prefix));
    566    pending_startup_messages_len += msg_len;
    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 * */
    590 void
    591 tor_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>. */
    612 static int
    613 int_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. */
    625 void
    626 tor_log_update_sigsafe_err_fds(void)
    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. */
    633  int fds[TOR_SIGSAFE_LOG_MAX_FDS];
    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. */
    683 void
    684 tor_log_get_logfile_names(smartlist_t *out)
    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;
    696    smartlist_add_strdup(out, lf->filename);
    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. */
    705 void
    706 log_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) && (severity >= LOG_WARN))
    711    tor_bug_increment_count_();
    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 }
    718 void
    719 log_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) && (severity >= LOG_WARN))
    725    tor_bug_increment_count_();
    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>. */
    738 static void
    739 log_free_(logfile_t *victim)
    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. */
    749 void
    750 logs_free_all(void)
    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;
    761  pending_startup_messages = NULL;
    762  UNLOCK_LOGS();
    763  while (next) {
    764    victim = next;
    765    next = next->next;
    766    close_log(victim);
    767    log_free(victim);
    768  }
    769  tor_free(appname);
    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 */
    795 void
    796 logs_flush_sigsafe(void)
    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 */
    821 static void
    822 delete_log(logfile_t *victim)
    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. */
    841 static void
    842 close_log_sigsafe(logfile_t *victim)
    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. */
    854 static void
    855 close_log(logfile_t *victim)
    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 */
    872 void
    873 set_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. */
    888 MOCK_IMPL(STATIC void,
    889 add_stream_log_impl,(const log_severity_list_t *severity,
    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;
    900  log_global_min_severity_ = get_min_log_level();
    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. */
    906 void
    907 add_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 */
    915 void
    916 init_logging(int disable_startup_queue)
    917 {
    918  if (!log_mutex_initialized) {
    919    tor_mutex_init(&log_mutex);
    920    tor_bug_init_counter();
    921    log_mutex_initialized = 1;
    922  }
    923 #ifdef __GNUC__
    924  if (strchr(__PRETTY_FUNCTION__, '(')) {
    925    pretty_fn_has_parens = 1;
    926  }
    927 #endif
    928  if (pending_cb_messages == NULL)
    929    pending_cb_messages = smartlist_new();
    930  if (disable_startup_queue)
    931    queue_startup_messages = 0;
    932  if (pending_startup_messages == NULL && queue_startup_messages) {
    933    pending_startup_messages = smartlist_new();
    934  }
    935 }
    936 
    937 /** Set whether we report logging domains as a part of our log messages.
    938 */
    939 void
    940 logs_set_domain_logging(int enabled)
    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 */
    949 void
    950 add_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 **/
    972 void
    973 logs_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 */
    982 int
    983 add_callback_log(const log_severity_list_t *severity, log_callback cb)
    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;
    995  log_global_min_severity_ = get_min_log_level();
    996  UNLOCK_LOGS();
    997  return 0;
    998 }
    999 
   1000 /** Adjust the configured severity of any logs whose callback function is
   1001 * <b>cb</b>. */
   1002 void
   1003 change_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  }
   1015  log_global_min_severity_ = get_min_log_level();
   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. */
   1021 void
   1022 flush_pending_log_callbacks(void)
   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;
   1034  pending_cb_messages = smartlist_new();
   1035  do {
   1036    SMARTLIST_FOREACH_BEGIN(messages, pending_log_message_t *, msg) {
   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 */
   1063 void
   1064 flush_log_messages_from_startup(void)
   1065 {
   1066  logfile_t *lf;
   1067 
   1068  LOCK_LOGS();
   1069  queue_startup_messages = 0;
   1070  pending_startup_messages_len = 0;
   1071  if (! pending_startup_messages)
   1072    goto out;
   1073 
   1074  SMARTLIST_FOREACH_BEGIN(pending_startup_messages, pending_log_message_t *,
   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);
   1093  pending_startup_messages = NULL;
   1094 
   1095 out:
   1096  UNLOCK_LOGS();
   1097 }
   1098 
   1099 /** Close any log handlers marked by mark_logs_temp(). */
   1100 void
   1101 close_temp_logs(void)
   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 
   1118  log_global_min_severity_ = get_min_log_level();
   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. */
   1124 void
   1125 rollback_log_changes(void)
   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();
   1132  close_temp_logs();
   1133 }
   1134 
   1135 /** Configure all log handles to be closed by close_temp_logs(). */
   1136 void
   1137 mark_logs_temp(void)
   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 */
   1151 MOCK_IMPL(int,
   1152 add_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;
   1169  log_global_min_severity_ = get_min_log_level();
   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 */
   1186 int
   1187 add_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;
   1211  log_global_min_severity_ = get_min_log_level();
   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. */
   1219 int
   1220 parse_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. */
   1236 const char *
   1237 log_level_to_string(int level)
   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 * */
   1247 static 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 
   1255 CTASSERT(ARRAY_LENGTH(domain_list) == N_LOGGING_DOMAINS + 1);
   1256 
   1257 CTASSERT(HIGHEST_RESERVED_LD_DOMAIN_ < LD_ALL_DOMAINS);
   1258 CTASSERT(LD_ALL_DOMAINS < LOWEST_RESERVED_LD_FLAG_);
   1259 CTASSERT(LOWEST_RESERVED_LD_FLAG_ < LD_ALL_FLAGS);
   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. */
   1263 static log_domain_mask_t
   1264 parse_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. */
   1275 static char *
   1276 domain_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 */
   1327 int
   1328 parse_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;
   1341    log_domain_mask_t domains = LD_ALL_DOMAINS;
   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 {
   1361              log_domain_mask_t d;
   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. */
   1431 int
   1432 get_min_log_level(void)
   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. */
   1446 void
   1447 switch_logs_debug(void)
   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  }
   1456  log_global_min_severity_ = get_min_log_level();
   1457  UNLOCK_LOGS();
   1458 }
   1459 
   1460 /** Truncate all the log files. */
   1461 void
   1462 truncate_logs(void)
   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 }