Commit 26f3cb86 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Add SysLog option to direct log messages to the system log instead of a FILE*.


svn:r2591
parent 64fc462a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ AC_CHECK_HEADERS(unistd.h string.h signal.h netdb.h ctype.h poll.h sys/stat.h sy

dnl These headers are not essential

AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h)
AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h)

AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime)
AC_REPLACE_FUNCS(strlcat strlcpy)
+4 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ Set the verboseness level of the primary log. (Default: warn)
\fBlogfile \fR\fIFILE\fP
Rather than logging to stdout, log to FILE.
.TP
\fBsyslog\fP
Rather than logging to stdout, send messages to the system log. (Not
supported on all platforms)
.TP
\fBbandwidthrate \fR\fINUM\fP
A token bucket limits the average incoming bandwidth on this node to NUM bytes per second. (Default: 800000)
.TP
+84 −24
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ typedef struct logfile_t {
  int loglevel; /**< Lowest severity level to send to this stream. */
  int max_loglevel; /**< Highest severity level to send to this stream. */
  int is_temporary; /**< Boolean: close after initializing logging subsystem.*/
  int is_syslog; /**< Boolean: send messages to syslog. */
} logfile_t;

/** Helper: map a log severity to descriptive string. */
@@ -50,8 +51,13 @@ static INLINE const char *sev_to_string(int severity) {

/** Linked list of logfile_t. */
static logfile_t *logfiles = NULL;
#ifdef HAVE_SYSLOG_H
static int syslog_count = 0;
#endif

static void delete_log(logfile_t *victim);
static void close_log(logfile_t *victim);
static int reset_log(logfile_t *lf);

static INLINE size_t
_log_prefix(char *buf, size_t buf_len, int severity)
@@ -104,16 +110,19 @@ static void log_tor_version(logfile_t *lf, int reset)

/** Helper: Format a log message into a fixed-sized buffer. (This is
 * factored out of <b>logv</b> so that we never format a message more
 * than once.)
 * than once.)  Return a pointer to the first character of the message
 * portion of the formatted string.
 */
static INLINE void format_msg(char *buf, size_t buf_len,
static INLINE char *format_msg(char *buf, size_t buf_len,
                              int severity, const char *funcname,
                              const char *format, va_list ap)
{
  size_t n;
  char *end_of_prefix;
  buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */

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

  if (funcname) {
    n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
@@ -128,6 +137,7 @@ static INLINE void format_msg(char *buf, size_t buf_len,
  }
  buf[n]='\n';
  buf[n+1]='\0';
  return end_of_prefix;
}

/** Helper: sends a message to the appropriate logfiles, at loglevel
@@ -140,23 +150,32 @@ logv(int severity, const char *funcname, const char *format, va_list ap)
  char buf[10024];
  int formatted = 0;
  logfile_t *lf;
  char *end_of_prefix=NULL;

  assert(format);
  lf = logfiles;
  while(lf) {
    if (severity < lf->loglevel || severity > lf->max_loglevel) {
    if (severity > lf->loglevel || severity < lf->max_loglevel) {
      lf = lf->next;
      continue;
    }
    if (!lf->file) {
    if (! (lf->file || lf->is_syslog)) {
      lf = lf->next;
      continue;
    }

    if (!formatted) {
      end_of_prefix =
        format_msg(buf, sizeof(buf), severity, funcname, format, ap);
      formatted = 1;
    }
    if (lf->is_syslog) {
#ifdef HAVE_SYSLOG_H
      syslog(severity, "%s", end_of_prefix);
#endif
      lf = lf->next;
      continue;
    }
    if(fputs(buf, lf->file) == EOF ||
       fflush(lf->file) == EOF) { /* error */
      /* don't log the error! Blow away this log entry and continue. */
@@ -194,8 +213,7 @@ void close_logs()
  while(logfiles) {
    victim = logfiles;
    logfiles = logfiles->next;
    if (victim->needs_close)
      fclose(victim->file);
    close_log(victim);
    tor_free(victim->filename);
    tor_free(victim);
  }
@@ -206,17 +224,12 @@ void reset_logs()
{
  logfile_t *lf = logfiles;
  while(lf) {
    if (lf->needs_close) {
      if(fclose(lf->file)==EOF ||
        !(lf->file = fopen(lf->filename, "a"))) {
    if (reset_log(lf)) {
      /* error. don't log it. delete the log entry and continue. */
      logfile_t *victim = lf;
      lf = victim->next;
      delete_log(victim);
      continue;
      } else {
        log_tor_version(lf, 1);
      }
    }
    lf = lf->next;
  }
@@ -241,19 +254,43 @@ static void delete_log(logfile_t *victim) {
  tor_free(victim);
}

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

static int reset_log(logfile_t *lf)
{
  if (lf->needs_close) {
    if(fclose(lf->file)==EOF ||
       !(lf->file = fopen(lf->filename, "a"))) {
      return -1;
    } else {
      log_tor_version(lf, 1);
    }
  }
  return 0;
}

/** Add a log handler to send all messages of severity <b>loglevel</b>
 * or higher to <b>stream</b>. */
void add_stream_log(int loglevelMin, int loglevelMax, const char *name, FILE *stream)
{
  logfile_t *lf;
  lf = tor_malloc(sizeof(logfile_t));
  lf = tor_malloc_zero(sizeof(logfile_t));
  lf->filename = tor_strdup(name);
  lf->needs_close = 0;
  lf->loglevel = loglevelMin;
  lf->max_loglevel = loglevelMax;
  lf->file = stream;
  lf->next = logfiles;
  lf->is_temporary = 0;
  logfiles = lf;
}

@@ -266,6 +303,7 @@ void add_temp_log(void)
  logfiles->is_temporary = 1;
}

/** Close any log handlers added by add_temp_log or marked by mark_logs_temp */
void close_temp_logs(void)
{
  logfile_t *lf, **p;
@@ -273,8 +311,7 @@ void close_temp_logs(void)
    if ((*p)->is_temporary) {
      lf = *p;
      *p = (*p)->next;
      if (lf->needs_close)
        fclose(lf->file);
      close_log(lf);
      tor_free(lf->filename);
      tor_free(lf);
    } else {
@@ -283,6 +320,7 @@ void close_temp_logs(void)
  }
}

/** Configure all log handles to be closed by close_temp_logs */
void mark_logs_temp(void)
{
  logfile_t *lf;
@@ -306,6 +344,28 @@ int add_file_log(int loglevelMin, int loglevelMax, const char *filename)
  return 0;
}

#ifdef HAVE_SYSLOG_H
/**
 * Add a log handler to send messages to they system log facility.
 */
int add_syslog_log(int loglevelMin, int loglevelMax)
{
  logfile_t *lf;
  if (syslog_count++ == 0)
    /* This is the the first syslog. */
    openlog("Tor", LOG_NDELAY, LOG_DAEMON);

  lf = tor_malloc_zero(sizeof(logfile_t));
  lf->loglevel = loglevelMin;
  lf->filename = tor_strdup("<syslog>");
  lf->max_loglevel = loglevelMax;
  lf->is_syslog = 1;
  lf->next = logfiles;
  logfiles = lf;
  return 0;
}
#endif

/** If <b>level</b> is a valid log severity, return the corresponding
 * numeric value.  Otherwise, return -1. */
int parse_log_level(const char *level) {
@@ -327,7 +387,7 @@ int get_min_log_level(void)
  logfile_t *lf;
  int min = LOG_ERR;
  for (lf = logfiles; lf; lf = lf->next) {
    if (lf->loglevel < min)
    if (lf->loglevel > min)
      min = lf->loglevel;
  }
  return min;
+23 −7
Original line number Diff line number Diff line
@@ -18,24 +18,37 @@
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#define LOG_WARN LOG_WARNING
#if LOG_DEBUG < LOG_ERR
#error "Your syslog.h thinks high numbers are more important.  We aren't prepared to deal with that."
#endif
#else
/* XXXX Note: The code was originally written to refer to severities,
 * with 0 being the least severe; while syslog's logging code refers to
 * priorities, with 0 being the most important.  Thus, all our comparisons
 * needed to be reversed when we added syslog support.  
 *
 * The upshot of this is that comments about log levels may be messed
 * up: for "maximum severity" read "most severe" and "numerically
 * *lowest* severity".
 */

/** Debug-level severity: for hyper-verbose messages of no interest to
 * anybody but developers. */
#define LOG_DEBUG   0
#define LOG_DEBUG   7
/** Info-level severity: for messages that appear frequently during normal
 * operation. */
#define LOG_INFO    1
#define LOG_INFO    6
/** Notice-level severity: for messages that appear infrequently
 * during normal operation; that the user will probably care about;
 * and that are not errors.
 */
#define LOG_NOTICE  2
#define LOG_NOTICE  5
/** Warn-level severity: for messages that only appear when something has gone
 * wrong. */
#define LOG_WARN    3
#define LOG_WARN    4
/** Error-level severity: for messages that only appear when something has gone
 * very wrong, and the Tor process can no longer proceed. */
#define LOG_ERR     4
#define LOG_ERR     3
#endif

/* magic to make GCC check for proper format strings. */
@@ -49,9 +62,12 @@
int parse_log_level(const char *level);
void add_stream_log(int severityMin, int severityMax, const char *name, FILE *stream);
int add_file_log(int severityMin, int severityMax, const char *filename);
#ifdef HAVE_SYSLOG_H
int add_syslog_log(int loglevelMin, int loglevelMax);
#endif
int get_min_log_level(void);
void close_logs();
void reset_logs();
void close_logs(void);
void reset_logs(void);
void add_temp_log(void);
void close_temp_logs(void);
void mark_logs_temp(void);
+4 −0
Original line number Diff line number Diff line
@@ -1740,13 +1740,17 @@ try_next_line:
  while(*value && isspace((int)*value))
    value++;

#if 0
  if(!*end || !*value) { /* only a key on this line. no value. */
    *end = 0;
    log_fn(LOG_WARN,"Line has keyword '%s' but no value. Failing.",key);
    return -1;
  }
#endif
  *end = 0; /* null it out */

  tor_assert(key);
  tor_assert(value);
  log_fn(LOG_DEBUG,"got keyword '%s', value '%s'", key, value);
  *key_out = key, *value_out = value;
  return 1;
Loading