Back to index

tor  0.2.3.19-rc
Classes | Defines | Typedefs | Functions | Variables
log.c File Reference

Functions to send messages to log files or the console. More...

#include "orconfig.h"
#include <stdarg.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "compat.h"
#include "util.h"
#include "torlog.h"
#include "container.h"

Go to the source code of this file.

Classes

struct  logfile_t
 Information for a single logfile; only used in log.c. More...
struct  pending_cb_message_t
 Represents a log message that we are going to send to callback-driven loggers once we can do so in a non-reentrant way. More...

Defines

#define LOG_PRIVATE
#define LOCK_LOGS()
 Lock the log_mutex to prevent others from changing the logfile_t list.
#define UNLOCK_LOGS()   STMT_BEGIN tor_mutex_release(&log_mutex); STMT_END
 Unlock the log_mutex.
#define TRUNCATED_STR   "[...truncated]"
 The string we stick at the end of a log message when it is too long, and its length.
#define TRUNCATED_STR_LEN   14

Typedefs

typedef struct logfile_t logfile_t
 Information for a single logfile; only used in log.c.
typedef struct pending_cb_message_t pending_cb_message_t
 Represents a log message that we are going to send to callback-driven loggers once we can do so in a non-reentrant way.

Functions

static void log_free (logfile_t *victim)
 Free all storage held by victim.
static INLINE const char * sev_to_string (int severity)
 Helper: map a log severity to descriptive string.
static INLINE int should_log_function_name (log_domain_mask_t domain, int severity)
 Helper: decide whether to include the function name in the log message.
static void delete_log (logfile_t *victim)
 Remove and free the log entry victim from the linked-list logfiles (it is probably present, but it might not be due to thread racing issues).
static void close_log (logfile_t *victim)
 Helper: release system resources (but not memory) held by a single logfile_t.
static char * domain_to_string (log_domain_mask_t domain, char *buf, size_t buflen)
 Translate a bitmask of log domains to a string.
static INLINE char * format_msg (char *buf, size_t buf_len, log_domain_mask_t domain, int severity, const char *funcname, const char *format, va_list ap, size_t *msg_len_out)
 Helper: Format a log message into a fixed-sized buffer.
static INLINE char static void logv (int severity, log_domain_mask_t domain, const char *funcname, const char *format, va_list ap)
 Helper: sends a message to the appropriate logfiles, at loglevel severity.
void log_set_application_name (const char *name)
 Set the "application name" for the logs to name: we'll use this name in the message we write when starting up, and at the start of each new log.
void set_log_time_granularity (int granularity_msec)
 Define log time granularity for all logs to be granularity_msec milliseconds.
static INLINE size_t _log_prefix (char *buf, size_t buf_len, int severity)
 Helper: Write the standard prefix for log lines to a buf_len character buffer in buf.
static int log_tor_version (logfile_t *lf, int reset)
 If lf refers to an actual file that we have just opened, and the file contains no data, log an "opening new logfile" message at the top.
void tor_log (int severity, log_domain_mask_t domain, const char *format,...)
 Output a message to the log.
void logs_free_all (void)
 Close all open log files, and free other static memory.
void set_log_severity_config (int loglevelMin, int loglevelMax, log_severity_list_t *severity_out)
 Adjust a log severity configuration in severity_out to contain every domain between loglevelMin and loglevelMax, inclusive.
static void add_stream_log_impl (const log_severity_list_t *severity, const char *name, int fd)
 Add a log handler named name to send all messages in severity to fd.
void add_stream_log (const log_severity_list_t *severity, const char *name, int fd)
 Add a log handler named name to send all messages in severity to fd.
void init_logging (void)
 Initialize the global logging facility.
void logs_set_domain_logging (int enabled)
 Set whether we report logging domains as a part of our log messages.
void add_temp_log (int min_severity)
 Add a log handler to receive messages during startup (before the real logs are initialized).
int add_callback_log (const log_severity_list_t *severity, log_callback cb)
 Add a log handler to send messages in severity to the function cb.
void change_callback_log_severity (int loglevelMin, int loglevelMax, log_callback cb)
 Adjust the configured severity of any logs whose callback function is cb.
void flush_pending_log_callbacks (void)
 If there are any log messages that were generated with LD_NOCB waiting to be sent to callback-based loggers, send them now.
void close_temp_logs (void)
 Close any log handlers added by add_temp_log() or marked by mark_logs_temp().
void rollback_log_changes (void)
 Make all currently temporary logs (set to be closed by close_temp_logs) live again, and close all non-temporary logs.
void mark_logs_temp (void)
 Configure all log handles to be closed by close_temp_logs().
int add_file_log (const log_severity_list_t *severity, const char *filename)
 Add a log handler to send messages to filename.
int parse_log_level (const char *level)
 If level is a valid log severity, return the corresponding numeric value.
const char * log_level_to_string (int level)
 Return the string equivalent of a given log level.
static log_domain_mask_t parse_log_domain (const char *domain)
 Return a bitmask for the log domain for which domain is the name, or 0 if there is no such name.
int parse_log_severity_config (const char **cfg_ptr, log_severity_list_t *severity_out)
 Parse a log severity pattern in *cfg_ptr.
int get_min_log_level (void)
 Return the least severe log level that any current log is interested in.
void switch_logs_debug (void)
 Switch all logs to output at most verbose level.

Variables

static tor_mutex_t log_mutex
 A mutex to guard changes to logfiles and logging.
static int log_mutex_initialized = 0
 True iff we have initialized log_mutex.
static logfile_tlogfiles = NULL
 Linked list of logfile_t.
static int log_domains_are_logged = 0
 Boolean: do we report logging domains?
static smartlist_tpending_cb_messages = NULL
 Log messages waiting to be replayed onto callback-based logs.
int _log_global_min_severity = LOG_NOTICE
 What's the lowest log level anybody cares about? Checking this lets us bail out early from log_debug if we aren't debugging.
static INLINE char static void
static char * 
appname = NULL
 Name of the application: used to generate the message we write at the start of each new log.
static int log_time_granularity = 1
 Log time granularity in milliseconds.
static const char * domain_list []
 NULL-terminated array of names for log domains such that domain_list[dom] is a description of dom.
const char * _log_fn_function_name = NULL
 Output a message to the log, prefixed with a function name fn.
void _log_fn (int severity, log_domain_mask_t domain, const char *format,...)
void _log_debug (log_domain_mask_t domain, const char *format,...)
void _log_info (log_domain_mask_t domain, const char *format,...)
void _log_notice (log_domain_mask_t domain, const char *format,...)
void _log_warn (log_domain_mask_t domain, const char *format,...)
void _log_err (log_domain_mask_t domain, const char *format,...)

Detailed Description

Functions to send messages to log files or the console.

Definition in file log.c.


Class Documentation

struct logfile_t

Information for a single logfile; only used in log.c.

Definition at line 47 of file log.c.

Collaboration diagram for logfile_t:
Class Members
log_callback callback If not NULL, send messages to this function.
int fd fd to receive log messages, or -1 for none.
char * filename Filename to open.
int is_syslog Boolean: send messages to syslog.
int is_temporary Boolean: close after initializing logging subsystem.
int needs_close Boolean: true if the stream gets closed on shutdown.
struct logfile_t * next Next logfile_t in the linked list.
int seems_dead Boolean: true if the stream seems to be kaput.
log_severity_list_t * severities Which severity of messages should we log for each log domain?
struct pending_cb_message_t

Represents a log message that we are going to send to callback-driven loggers once we can do so in a non-reentrant way.

Definition at line 116 of file log.c.

Class Members
log_domain_mask_t domain The domain of the message.
char * msg The content of the message.
int severity The severity of the message.

Define Documentation

#define LOCK_LOGS ( )
Value:

Lock the log_mutex to prevent others from changing the logfile_t list.

Definition at line 126 of file log.c.

#define LOG_PRIVATE

Definition at line 35 of file log.c.

#define TRUNCATED_STR   "[...truncated]"

The string we stick at the end of a log message when it is too long, and its length.

Definition at line 42 of file log.c.

#define TRUNCATED_STR_LEN   14

Definition at line 43 of file log.c.

Unlock the log_mutex.

Definition at line 130 of file log.c.


Typedef Documentation

typedef struct logfile_t logfile_t

Information for a single logfile; only used in log.c.

Represents a log message that we are going to send to callback-driven loggers once we can do so in a non-reentrant way.


Function Documentation

void _log_debug ( log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 468 of file log.c.

{
  va_list ap;
  /* For GCC we do this check in the macro. */
  if (PREDICT_LIKELY(LOG_DEBUG > _log_global_min_severity))
    return;
  va_start(ap,format);
  logv(LOG_DEBUG, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

void _log_err ( log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 513 of file log.c.

{
  va_list ap;
  if (LOG_ERR > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(LOG_ERR, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

void _log_fn ( int  severity,
log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 457 of file log.c.

{
  va_list ap;
  if (severity > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(severity, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

void _log_info ( log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 480 of file log.c.

{
  va_list ap;
  if (LOG_INFO > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(LOG_INFO, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

void _log_notice ( log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 491 of file log.c.

{
  va_list ap;
  if (LOG_NOTICE > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(LOG_NOTICE, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

static INLINE size_t _log_prefix ( char *  buf,
size_t  buf_len,
int  severity 
) [static]

Helper: Write the standard prefix for log lines to a buf_len character buffer in buf.

Definition at line 180 of file log.c.

{
  time_t t;
  struct timeval now;
  struct tm tm;
  size_t n;
  int r, ms;

  tor_gettimeofday(&now);
  t = (time_t)now.tv_sec;
  ms = (int)now.tv_usec / 1000;
  if (log_time_granularity >= 1000) {
    t -= t % (log_time_granularity / 1000);
    ms = 0;
  } else {
    ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
  }

  n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
  r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
                   sev_to_string(severity));

  if (r<0)
    return buf_len-1;
  else
    return n+r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _log_warn ( log_domain_mask_t  domain,
const char *  format,
  ... 
)

Definition at line 502 of file log.c.

{
  va_list ap;
  if (LOG_WARN > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(LOG_WARN, domain, _log_fn_function_name, format, ap);
  va_end(ap);
  _log_fn_function_name = NULL;
}

Here is the call graph for this function:

int add_callback_log ( const log_severity_list_t severity,
log_callback  cb 
)

Add a log handler to send messages in severity to the function cb.

Definition at line 697 of file log.c.

{
  logfile_t *lf;
  lf = tor_malloc_zero(sizeof(logfile_t));
  lf->fd = -1;
  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
  lf->filename = tor_strdup("<callback>");
  lf->callback = cb;
  lf->next = logfiles;

  LOCK_LOGS();
  logfiles = lf;
  _log_global_min_severity = get_min_log_level();
  UNLOCK_LOGS();
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int add_file_log ( const log_severity_list_t severity,
const char *  filename 
)

Add a log handler to send messages to filename.

If opening the logfile fails, -1 is returned and errno is set appropriately (by open(2)).

Definition at line 828 of file log.c.

{
  int fd;
  logfile_t *lf;

  fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
  if (fd<0)
    return -1;
  if (tor_fd_seekend(fd)<0)
    return -1;

  LOCK_LOGS();
  add_stream_log_impl(severity, filename, fd);
  logfiles->needs_close = 1;
  lf = logfiles;
  _log_global_min_severity = get_min_log_level();

  if (log_tor_version(lf, 0) < 0) {
    delete_log(lf);
  }
  UNLOCK_LOGS();

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void add_stream_log ( const log_severity_list_t severity,
const char *  name,
int  fd 
)

Add a log handler named name to send all messages in severity to fd.

Steals a reference to severity; the caller must not use it after calling this function.

Definition at line 648 of file log.c.

{
  LOCK_LOGS();
  add_stream_log_impl(severity, name, fd);
  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void add_stream_log_impl ( const log_severity_list_t severity,
const char *  name,
int  fd 
) [static]

Add a log handler named name to send all messages in severity to fd.

Copies severity. Helper: does no locking.

Definition at line 630 of file log.c.

{
  logfile_t *lf;
  lf = tor_malloc_zero(sizeof(logfile_t));
  lf->fd = fd;
  lf->filename = tor_strdup(name);
  lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
  lf->next = logfiles;

  logfiles = lf;
  _log_global_min_severity = get_min_log_level();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void add_temp_log ( int  min_severity)

Add a log handler to receive messages during startup (before the real logs are initialized).

Definition at line 681 of file log.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void change_callback_log_severity ( int  loglevelMin,
int  loglevelMax,
log_callback  cb 
)

Adjust the configured severity of any logs whose callback function is cb.

Definition at line 717 of file log.c.

{
  logfile_t *lf;
  log_severity_list_t severities;
  set_log_severity_config(loglevelMin, loglevelMax, &severities);
  LOCK_LOGS();
  for (lf = logfiles; lf; lf = lf->next) {
    if (lf->callback == cb) {
      memcpy(lf->severities, &severities, sizeof(severities));
    }
  }
  _log_global_min_severity = get_min_log_level();
  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void close_log ( logfile_t victim) [static]

Helper: release system resources (but not memory) held by a single logfile_t.

Definition at line 595 of file log.c.

{
  if (victim->needs_close && victim->fd >= 0) {
    close(victim->fd);
    victim->fd = -1;
  } else if (victim->is_syslog) {
#ifdef HAVE_SYSLOG_H
    if (--syslog_count == 0) {
      /* There are no other syslogs; close the logging facility. */
      closelog();
    }
#endif
  }
}

Here is the caller graph for this function:

void close_temp_logs ( void  )

Close any log handlers added by add_temp_log() or marked by mark_logs_temp().

Definition at line 778 of file log.c.

{
  logfile_t *lf, **p;

  LOCK_LOGS();
  for (p = &logfiles; *p; ) {
    if ((*p)->is_temporary) {
      lf = *p;
      /* we use *p here to handle the edge case of the head of the list */
      *p = (*p)->next;
      close_log(lf);
      log_free(lf);
    } else {
      p = &((*p)->next);
    }
  }

  _log_global_min_severity = get_min_log_level();
  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void delete_log ( logfile_t victim) [static]

Remove and free the log entry victim from the linked-list logfiles (it is probably present, but it might not be due to thread racing issues).

After this function is called, the caller shouldn't refer to victim anymore.

Long-term, we need to do something about races in the log subsystem in general. See bug 222 for more details.

Definition at line 576 of file log.c.

{
  logfile_t *tmpl;
  if (victim == logfiles)
    logfiles = victim->next;
  else {
    for (tmpl = logfiles; tmpl && tmpl->next != victim; tmpl=tmpl->next) ;
//    tor_assert(tmpl);
//    tor_assert(tmpl->next == victim);
    if (!tmpl)
      return;
    tmpl->next = victim->next;
  }
  log_free(victim);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char * domain_to_string ( log_domain_mask_t  domain,
char *  buf,
size_t  buflen 
) [static]

Translate a bitmask of log domains to a string.

Definition at line 928 of file log.c.

{
  char *cp = buf;
  char *eos = buf+buflen;

  buf[0] = '\0';
  if (! domain)
    return buf;
  while (1) {
    const char *d;
    int bit = tor_log2(domain);
    size_t n;
    if (bit >= N_LOGGING_DOMAINS) {
      tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
      return buf+strlen(buf);
    }
    d = domain_list[bit];
    n = strlcpy(cp, d, eos-cp);
    if (n >= buflen) {
      tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
      return buf+strlen(buf);
    }
    cp += n;
    domain &= ~(1<<bit);

    if (domain == 0 || (eos-cp) < 2)
      return cp;

    memcpy(cp, ",", 2); /*Nul-terminated ,"*/
    cp++;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void flush_pending_log_callbacks ( void  )

If there are any log messages that were generated with LD_NOCB waiting to be sent to callback-based loggers, send them now.

Definition at line 736 of file log.c.

{
  logfile_t *lf;
  smartlist_t *messages, *messages_tmp;

  LOCK_LOGS();
  if (0 == smartlist_len(pending_cb_messages)) {
    UNLOCK_LOGS();
    return;
  }

  messages = pending_cb_messages;
  pending_cb_messages = smartlist_new();
  do {
    SMARTLIST_FOREACH_BEGIN(messages, pending_cb_message_t *, msg) {
      const int severity = msg->severity;
      const int domain = msg->domain;
      for (lf = logfiles; lf; lf = lf->next) {
        if (! lf->callback || lf->seems_dead ||
            ! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
          continue;
        }
        lf->callback(severity, domain, msg->msg);
      }
      tor_free(msg->msg);
      tor_free(msg);
    } SMARTLIST_FOREACH_END(msg);
    smartlist_clear(messages);

    messages_tmp = pending_cb_messages;
    pending_cb_messages = messages;
    messages = messages_tmp;
  } while (smartlist_len(messages));

  smartlist_free(messages);

  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

static INLINE char * format_msg ( char *  buf,
size_t  buf_len,
log_domain_mask_t  domain,
int  severity,
const char *  funcname,
const char *  format,
va_list  ap,
size_t *  msg_len_out 
) [static]

Helper: Format a log message into a fixed-sized buffer.

(This is factored out of logv so that we never format a message more than once.) Return a pointer to the first character of the message portion of the formatted string.

Definition at line 252 of file log.c.

{
  size_t n;
  int r;
  char *end_of_prefix;
  char *buf_end;

  assert(buf_len >= 16); /* prevent integer underflow and general stupidity */
  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
  buf_end = buf+buf_len; /* point *after* the last char we can write to */

  n = _log_prefix(buf, buf_len, severity);
  end_of_prefix = buf+n;

  if (log_domains_are_logged) {
    char *cp = buf+n;
    if (cp == buf_end) goto format_msg_no_room_for_domains;
    *cp++ = '{';
    if (cp == buf_end) goto format_msg_no_room_for_domains;
    cp = domain_to_string(domain, cp, (buf+buf_len-cp));
    if (cp == buf_end) goto format_msg_no_room_for_domains;
    *cp++ = '}';
    if (cp == buf_end) goto format_msg_no_room_for_domains;
    *cp++ = ' ';
    if (cp == buf_end) goto format_msg_no_room_for_domains;
    end_of_prefix = cp;
    n = cp-buf;
  format_msg_no_room_for_domains:
    /* This will leave end_of_prefix and n unchanged, and thus cause
     * whatever log domain string we had written to be clobbered. */
    ;
  }

  if (funcname && should_log_function_name(domain, severity)) {
    r = tor_snprintf(buf+n, buf_len-n, "%s(): ", funcname);
    if (r<0)
      n = strlen(buf);
    else
      n += r;
  }

  if (domain == LD_BUG && buf_len-n > 6) {
    memcpy(buf+n, "Bug: ", 6);
    n += 5;
  }

  r = tor_vsnprintf(buf+n,buf_len-n,format,ap);
  if (r < 0) {
    /* The message was too long; overwrite the end of the buffer with
     * "[...truncated]" */
    if (buf_len >= TRUNCATED_STR_LEN) {
      size_t offset = buf_len-TRUNCATED_STR_LEN;
      /* We have an extra 2 characters after buf_len to hold the \n\0,
       * so it's safe to add 1 to the size here. */
      strlcpy(buf+offset, TRUNCATED_STR, buf_len-offset+1);
    }
    /* Set 'n' to the end of the buffer, where we'll be writing \n\0.
     * Since we already subtracted 2 from buf_len, this is safe.*/
    n = buf_len;
  } else {
    n += r;
  }
  buf[n]='\n';
  buf[n+1]='\0';
  *msg_len_out = n+1;
  return end_of_prefix;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_min_log_level ( void  )

Return the least severe log level that any current log is interested in.

Definition at line 1086 of file log.c.

{
  logfile_t *lf;
  int i;
  int min = LOG_ERR;
  for (lf = logfiles; lf; lf = lf->next) {
    for (i = LOG_DEBUG; i > min; --i)
      if (lf->severities->masks[SEVERITY_MASK_IDX(i)])
        min = i;
  }
  return min;
}

Here is the caller graph for this function:

void init_logging ( void  )

Initialize the global logging facility.

Definition at line 657 of file log.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void log_free ( logfile_t victim) [static]

Free all storage held by victim.

Definition at line 528 of file log.c.

{
  if (!victim)
    return;
  tor_free(victim->severities);
  tor_free(victim->filename);
  tor_free(victim);
}

Here is the caller graph for this function:

const char* log_level_to_string ( int  level)

Return the string equivalent of a given log level.

Definition at line 900 of file log.c.

{
  return sev_to_string(level);
}

Here is the call graph for this function:

void log_set_application_name ( const char *  name)

Set the "application name" for the logs to name: we'll use this name in the message we write when starting up, and at the start of each new log.

Tor uses this string to write the version number to the log file.

Definition at line 159 of file log.c.

{
  tor_free(appname);
  appname = name ? tor_strdup(name) : NULL;
}

Here is the caller graph for this function:

static int log_tor_version ( logfile_t lf,
int  reset 
) [static]

If lf refers to an actual file that we have just opened, and the file contains no data, log an "opening new logfile" message at the top.

Return -1 if the log is broken and needs to be deleted, else return 0.

Definition at line 214 of file log.c.

{
  char buf[256];
  size_t n;
  int is_new;

  if (!lf->needs_close)
    /* If it doesn't get closed, it isn't really a file. */
    return 0;
  if (lf->is_temporary)
    /* If it's temporary, it isn't really a file. */
    return 0;

  is_new = lf->fd >= 0 && tor_fd_getpos(lf->fd) == 0;

  if (reset && !is_new)
    /* We are resetting, but we aren't at the start of the file; no
     * need to log again. */
    return 0;
  n = _log_prefix(buf, sizeof(buf), LOG_NOTICE);
  if (appname) {
    tor_snprintf(buf+n, sizeof(buf)-n,
                 "%s opening %slog file.\n", appname, is_new?"new ":"");
  } else {
    tor_snprintf(buf+n, sizeof(buf)-n,
                 "Tor %s opening %slog file.\n", VERSION, is_new?"new ":"");
  }
  if (write_all(lf->fd, buf, strlen(buf), 0) < 0) /* error */
    return -1; /* failed */
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void logs_free_all ( void  )

Close all open log files, and free other static memory.

Definition at line 539 of file log.c.

{
  logfile_t *victim, *next;
  smartlist_t *messages;
  LOCK_LOGS();
  next = logfiles;
  logfiles = NULL;
  messages = pending_cb_messages;
  pending_cb_messages = NULL;
  UNLOCK_LOGS();
  while (next) {
    victim = next;
    next = next->next;
    close_log(victim);
    log_free(victim);
  }
  tor_free(appname);

  SMARTLIST_FOREACH(messages, pending_cb_message_t *, msg, {
      tor_free(msg->msg);
      tor_free(msg);
    });
  smartlist_free(messages);

  /* We _could_ destroy the log mutex here, but that would screw up any logs
   * that happened between here and the end of execution. */
}

Here is the call graph for this function:

Here is the caller graph for this function:

void logs_set_domain_logging ( int  enabled)

Set whether we report logging domains as a part of our log messages.

Definition at line 670 of file log.c.

Here is the caller graph for this function:

static void logv ( int  severity,
log_domain_mask_t  domain,
const char *  funcname,
const char *  format,
va_list  ap 
) [static]

Helper: sends a message to the appropriate logfiles, at loglevel severity.

If provided, funcname is prepended to the message. The actual message is derived as from tor_snprintf(format,ap).

Definition at line 327 of file log.c.

{
  char buf[10024];
  size_t msg_len = 0;
  int formatted = 0;
  logfile_t *lf;
  char *end_of_prefix=NULL;
  int callbacks_deferred = 0;

  /* Call assert, not tor_assert, since tor_assert calls log on failure. */
  assert(format);
  /* check that severity is sane.  Overrunning the masks array leads to
   * interesting and hard to diagnose effects */
  assert(severity >= LOG_ERR && severity <= LOG_DEBUG);
  LOCK_LOGS();

  if ((! (domain & LD_NOCB)) && smartlist_len(pending_cb_messages))
    flush_pending_log_callbacks();

  lf = logfiles;
  while (lf) {
    if (! (lf->severities->masks[SEVERITY_MASK_IDX(severity)] & domain)) {
      lf = lf->next;
      continue;
    }
    if (! (lf->fd >= 0 || lf->is_syslog || lf->callback)) {
      lf = lf->next;
      continue;
    }
    if (lf->seems_dead) {
      lf = lf->next;
      continue;
    }

    if (!formatted) {
      end_of_prefix =
        format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
                   &msg_len);
      formatted = 1;
    }

    if (lf->is_syslog) {
#ifdef HAVE_SYSLOG_H
      char *m = end_of_prefix;
#ifdef MAXLINE
      /* Some syslog implementations have limits on the length of what you can
       * pass them, and some very old ones do not detect overflow so well.
       * Regrettably, they call their maximum line length MAXLINE. */
#if MAXLINE < 64
#warn "MAXLINE is a very low number; it might not be from syslog.h after all"
#endif
      if (msg_len >= MAXLINE)
        m = tor_strndup(end_of_prefix, MAXLINE-1);
#endif
      syslog(severity, "%s", m);
#ifdef MAXLINE
      if (m != end_of_prefix) {
        tor_free(m);
      }
#endif
#endif
      lf = lf->next;
      continue;
    } else if (lf->callback) {
      if (domain & LD_NOCB) {
        if (!callbacks_deferred && pending_cb_messages) {
          pending_cb_message_t *msg = tor_malloc(sizeof(pending_cb_message_t));
          msg->severity = severity;
          msg->domain = domain;
          msg->msg = tor_strdup(end_of_prefix);
          smartlist_add(pending_cb_messages, msg);

          callbacks_deferred = 1;
        }
      } else {
        lf->callback(severity, domain, end_of_prefix);
      }
      lf = lf->next;
      continue;
    }
    if (write_all(lf->fd, buf, msg_len, 0) < 0) { /* error */
      /* don't log the error! mark this log entry to be blown away, and
       * continue. */
      lf->seems_dead = 1;
    }
    lf = lf->next;
  }
  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void mark_logs_temp ( void  )

Configure all log handles to be closed by close_temp_logs().

Definition at line 814 of file log.c.

{
  logfile_t *lf;
  LOCK_LOGS();
  for (lf = logfiles; lf; lf = lf->next)
    lf->is_temporary = 1;
  UNLOCK_LOGS();
}

Here is the caller graph for this function:

static log_domain_mask_t parse_log_domain ( const char *  domain) [static]

Return a bitmask for the log domain for which domain is the name, or 0 if there is no such name.

Definition at line 916 of file log.c.

{
  int i;
  for (i=0; domain_list[i]; ++i) {
    if (!strcasecmp(domain, domain_list[i]))
      return (1u<<i);
  }
  return 0;
}

Here is the caller graph for this function:

int parse_log_level ( const char *  level)

If level is a valid log severity, return the corresponding numeric value.

Otherwise, return -1.

Definition at line 883 of file log.c.

{
  if (!strcasecmp(level, "err"))
    return LOG_ERR;
  if (!strcasecmp(level, "warn"))
    return LOG_WARN;
  if (!strcasecmp(level, "notice"))
    return LOG_NOTICE;
  if (!strcasecmp(level, "info"))
    return LOG_INFO;
  if (!strcasecmp(level, "debug"))
    return LOG_DEBUG;
  return -1;
}

Here is the caller graph for this function:

int parse_log_severity_config ( const char **  cfg_ptr,
log_severity_list_t severity_out 
)

Parse a log severity pattern in *cfg_ptr.

Advance cfg_ptr after the end of the severityPattern. Set the value of severity_out to the parsed pattern. Return 0 on success, -1 on failure.

The syntax for a SeverityPattern is:

   SeverityPattern = *(DomainSeverity SP)* DomainSeverity
   DomainSeverity = (DomainList SP)? SeverityRange
   SeverityRange = MinSeverity ("-" MaxSeverity )?
   DomainList = "[" (SP? DomainSpec SP? ",") SP? DomainSpec "]"
   DomainSpec = "*" | Domain | "~" Domain
 

A missing MaxSeverity defaults to ERR. Severities and domains are case-insensitive. "~" indicates negation for a domain; negation happens last inside a DomainList. Only one SeverityRange without a DomainList is allowed per line.

Definition at line 979 of file log.c.

{
  const char *cfg = *cfg_ptr;
  int got_anything = 0;
  int got_an_unqualified_range = 0;
  memset(severity_out, 0, sizeof(*severity_out));

  cfg = eat_whitespace(cfg);
  while (*cfg) {
    const char *dash, *space;
    char *sev_lo, *sev_hi;
    int low, high, i;
    log_domain_mask_t domains = ~0u;

    if (*cfg == '[') {
      int err = 0;
      char *domains_str;
      smartlist_t *domains_list;
      log_domain_mask_t neg_domains = 0;
      const char *closebracket = strchr(cfg, ']');
      if (!closebracket)
        return -1;
      domains = 0;
      domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
      domains_list = smartlist_new();
      smartlist_split_string(domains_list, domains_str, ",", SPLIT_SKIP_SPACE,
                             -1);
      tor_free(domains_str);
      SMARTLIST_FOREACH(domains_list, const char *, domain,
          {
            if (!strcmp(domain, "*")) {
              domains = ~0u;
            } else {
              int d;
              int negate=0;
              if (*domain == '~') {
                negate = 1;
                ++domain;
              }
              d = parse_log_domain(domain);
              if (!d) {
                log_warn(LD_CONFIG, "No such logging domain as %s", domain);
                err = 1;
              } else {
                if (negate)
                  neg_domains |= d;
                else
                  domains |= d;
              }
            }
          });
      SMARTLIST_FOREACH(domains_list, char *, d, tor_free(d));
      smartlist_free(domains_list);
      if (err)
        return -1;
      if (domains == 0 && neg_domains)
        domains = ~neg_domains;
      else
        domains &= ~neg_domains;
      cfg = eat_whitespace(closebracket+1);
    } else {
      ++got_an_unqualified_range;
    }
    if (!strcasecmpstart(cfg, "file") ||
        !strcasecmpstart(cfg, "stderr") ||
        !strcasecmpstart(cfg, "stdout") ||
        !strcasecmpstart(cfg, "syslog")) {
      goto done;
    }
    if (got_an_unqualified_range > 1)
      return -1;

    space = strchr(cfg, ' ');
    dash = strchr(cfg, '-');
    if (!space)
      space = strchr(cfg, '\0');
    if (dash && dash < space) {
      sev_lo = tor_strndup(cfg, dash-cfg);
      sev_hi = tor_strndup(dash+1, space-(dash+1));
    } else {
      sev_lo = tor_strndup(cfg, space-cfg);
      sev_hi = tor_strdup("ERR");
    }
    low = parse_log_level(sev_lo);
    high = parse_log_level(sev_hi);
    tor_free(sev_lo);
    tor_free(sev_hi);
    if (low == -1)
      return -1;
    if (high == -1)
      return -1;

    got_anything = 1;
    for (i=low; i >= high; --i)
      severity_out->masks[SEVERITY_MASK_IDX(i)] |= domains;

    cfg = eat_whitespace(space);
  }

 done:
  *cfg_ptr = cfg;
  return got_anything ? 0 : -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rollback_log_changes ( void  )

Make all currently temporary logs (set to be closed by close_temp_logs) live again, and close all non-temporary logs.

Definition at line 802 of file log.c.

{
  logfile_t *lf;
  LOCK_LOGS();
  for (lf = logfiles; lf; lf = lf->next)
    lf->is_temporary = ! lf->is_temporary;
  UNLOCK_LOGS();
  close_temp_logs();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void set_log_severity_config ( int  loglevelMin,
int  loglevelMax,
log_severity_list_t severity_out 
)

Adjust a log severity configuration in severity_out to contain every domain between loglevelMin and loglevelMax, inclusive.

Definition at line 614 of file log.c.

{
  int i;
  tor_assert(loglevelMin >= loglevelMax);
  tor_assert(loglevelMin >= LOG_ERR && loglevelMin <= LOG_DEBUG);
  tor_assert(loglevelMax >= LOG_ERR && loglevelMax <= LOG_DEBUG);
  memset(severity_out, 0, sizeof(log_severity_list_t));
  for (i = loglevelMin; i >= loglevelMax; --i) {
    severity_out->masks[SEVERITY_MASK_IDX(i)] = ~0u;
  }
}

Here is the caller graph for this function:

void set_log_time_granularity ( int  granularity_msec)

Define log time granularity for all logs to be granularity_msec milliseconds.

Definition at line 171 of file log.c.

{
  log_time_granularity = granularity_msec;
}

Here is the caller graph for this function:

static INLINE const char* sev_to_string ( int  severity) [static]

Helper: map a log severity to descriptive string.

Definition at line 64 of file log.c.

{
  switch (severity) {
    case LOG_DEBUG:   return "debug";
    case LOG_INFO:    return "info";
    case LOG_NOTICE:  return "notice";
    case LOG_WARN:    return "warn";
    case LOG_ERR:     return "err";
    default:          /* Call assert, not tor_assert, since tor_assert
                       * calls log on failure. */
                      assert(0); return "UNKNOWN";
  }
}

Here is the caller graph for this function:

static INLINE int should_log_function_name ( log_domain_mask_t  domain,
int  severity 
) [static]

Helper: decide whether to include the function name in the log message.

Definition at line 80 of file log.c.

{
  switch (severity) {
    case LOG_DEBUG:
    case LOG_INFO:
      /* All debugging messages occur in interesting places. */
      return 1;
    case LOG_NOTICE:
    case LOG_WARN:
    case LOG_ERR:
      /* We care about places where bugs occur. */
      return (domain == LD_BUG);
    default:
      /* Call assert, not tor_assert, since tor_assert calls log on failure. */
      assert(0); return 0;
  }
}

Here is the caller graph for this function:

void switch_logs_debug ( void  )

Switch all logs to output at most verbose level.

Definition at line 1101 of file log.c.

{
  logfile_t *lf;
  int i;
  LOCK_LOGS();
  for (lf = logfiles; lf; lf=lf->next) {
    for (i = LOG_DEBUG; i >= LOG_ERR; --i)
      lf->severities->masks[SEVERITY_MASK_IDX(i)] = ~0u;
  }
  _log_global_min_severity = get_min_log_level();
  UNLOCK_LOGS();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_log ( int  severity,
log_domain_mask_t  domain,
const char *  format,
  ... 
)

Output a message to the log.

It gets logged to all logfiles that care about messages with severity in domain. The content is formatted printf-style based on format and extra arguments.

Definition at line 423 of file log.c.

{
  va_list ap;
  if (severity > _log_global_min_severity)
    return;
  va_start(ap,format);
  logv(severity, domain, NULL, format, ap);
  va_end(ap);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char* _log_fn_function_name = NULL

Output a message to the log, prefixed with a function name fn.

Variant implementation of log_fn, log_debug, log_info,... for C compilers

without variadic macros. In this case, the calling function sets _log_fn_function_name to the name of the function, then invokes the appropriate _log_fn, _log_debug, etc.

Definition at line 455 of file log.c.

What's the lowest log level anybody cares about? Checking this lets us bail out early from log_debug if we aren't debugging.

Definition at line 134 of file log.c.

INLINE char static void static char* appname = NULL [static]

Name of the application: used to generate the message we write at the start of each new log.

Definition at line 151 of file log.c.

const char* domain_list[] [static]
Initial value:
 {
  "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
  "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
  "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL
}

NULL-terminated array of names for log domains such that domain_list[dom] is a description of dom.

Definition at line 907 of file log.c.

int log_domains_are_logged = 0 [static]

Boolean: do we report logging domains?

Definition at line 106 of file log.c.

A mutex to guard changes to logfiles and logging.

Definition at line 99 of file log.c.

int log_mutex_initialized = 0 [static]

True iff we have initialized log_mutex.

Definition at line 101 of file log.c.

int log_time_granularity = 1 [static]

Log time granularity in milliseconds.

Definition at line 166 of file log.c.

logfile_t* logfiles = NULL [static]

Linked list of logfile_t.

Definition at line 104 of file log.c.

smartlist_t* pending_cb_messages = NULL [static]

Log messages waiting to be replayed onto callback-based logs.

Definition at line 123 of file log.c.