LCOV - code coverage report
Current view: top level - lib/log - log.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 461 632 72.9 %
Date: 2021-11-24 03:28:48 Functions: 40 51 78.4 %

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

Generated by: LCOV version 1.14