mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
Allow multiple logfiles at different severity ranges
svn:r1899
This commit is contained in:
parent
1a829b0df4
commit
9d2cd7fc6e
@ -8,6 +8,8 @@ orconfig.h.in
|
|||||||
config.cache
|
config.cache
|
||||||
config.log
|
config.log
|
||||||
config.status
|
config.status
|
||||||
|
config.guess
|
||||||
|
config.sub
|
||||||
conftest*
|
conftest*
|
||||||
stamp-h
|
stamp-h
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "orconfig.h"
|
#include "orconfig.h"
|
||||||
#include "./util.h"
|
#include "./util.h"
|
||||||
#include "./log.h"
|
#include "./log.h"
|
||||||
@ -162,14 +163,14 @@ void reset_logs()
|
|||||||
|
|
||||||
/** Add a log handler to send all messages of severity <b>loglevel</b>
|
/** Add a log handler to send all messages of severity <b>loglevel</b>
|
||||||
* or higher to <b>stream</b>. */
|
* or higher to <b>stream</b>. */
|
||||||
void add_stream_log(int loglevel, const char *name, FILE *stream)
|
void add_stream_log(int loglevelMin, int loglevelMax, const char *name, FILE *stream)
|
||||||
{
|
{
|
||||||
logfile_t *lf;
|
logfile_t *lf;
|
||||||
lf = tor_malloc(sizeof(logfile_t));
|
lf = tor_malloc(sizeof(logfile_t));
|
||||||
lf->filename = name;
|
lf->filename = name;
|
||||||
lf->needs_close = 0;
|
lf->needs_close = 0;
|
||||||
lf->loglevel = loglevel;
|
lf->loglevel = loglevelMin;
|
||||||
lf->max_loglevel = LOG_ERR;
|
lf->max_loglevel = loglevelMax;
|
||||||
lf->file = stream;
|
lf->file = stream;
|
||||||
lf->next = logfiles;
|
lf->next = logfiles;
|
||||||
logfiles = lf;
|
logfiles = lf;
|
||||||
@ -180,16 +181,43 @@ void add_stream_log(int loglevel, const char *name, FILE *stream)
|
|||||||
* the logfile fails, -1 is returned and errno is set appropriately
|
* the logfile fails, -1 is returned and errno is set appropriately
|
||||||
* (by fopen).
|
* (by fopen).
|
||||||
*/
|
*/
|
||||||
int add_file_log(int loglevel, const char *filename)
|
int add_file_log(int loglevelMin, int loglevelMax, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
f = fopen(filename, "a");
|
f = fopen(filename, "a");
|
||||||
if (!f) return -1;
|
if (!f) return -1;
|
||||||
add_stream_log(loglevel, filename, f);
|
add_stream_log(loglevelMin, loglevelMax, filename, f);
|
||||||
logfiles->needs_close = 1;
|
logfiles->needs_close = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** If <b>level</b> is a valid log severity, return the corresponding
|
||||||
|
* numeric value. Otherwise, return -1. */
|
||||||
|
int parse_log_level(const char *level) {
|
||||||
|
if (!strcasecmp(level, "err"))
|
||||||
|
return LOG_ERR;
|
||||||
|
else if (!strcasecmp(level, "notice"))
|
||||||
|
return LOG_NOTICE;
|
||||||
|
else if (!strcasecmp(level, "info"))
|
||||||
|
return LOG_INFO;
|
||||||
|
else if (!strcasecmp(level, "debug"))
|
||||||
|
return LOG_DEBUG;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_min_log_level(void)
|
||||||
|
{
|
||||||
|
logfile_t *lf;
|
||||||
|
int min = LOG_ERR;
|
||||||
|
for (lf = logfiles; lf; lf = lf->next) {
|
||||||
|
if (lf->loglevel < min)
|
||||||
|
min = lf->loglevel;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode:c
|
mode:c
|
||||||
|
@ -46,8 +46,10 @@
|
|||||||
#define CHECK_PRINTF(formatIdx, firstArg)
|
#define CHECK_PRINTF(formatIdx, firstArg)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void add_stream_log(int loglevel, const char *name, FILE *stream);
|
int parse_log_level(const char *level);
|
||||||
int add_file_log(int severity, const char *filename);
|
void add_stream_log(int severityMin, int severityMax, const char *name, FILE *stream);
|
||||||
|
int add_file_log(int severityMin, int severityMax, const char *filename);
|
||||||
|
int get_min_log_level(void);
|
||||||
void close_logs();
|
void close_logs();
|
||||||
void reset_logs();
|
void reset_logs();
|
||||||
|
|
||||||
|
131
src/or/config.c
131
src/or/config.c
@ -28,7 +28,7 @@ static int config_close(FILE *f);
|
|||||||
static struct config_line_t *config_get_commandlines(int argc, char **argv);
|
static struct config_line_t *config_get_commandlines(int argc, char **argv);
|
||||||
static struct config_line_t *config_get_lines(FILE *f);
|
static struct config_line_t *config_get_lines(FILE *f);
|
||||||
static void config_free_lines(struct config_line_t *front);
|
static void config_free_lines(struct config_line_t *front);
|
||||||
static int config_compare(struct config_line_t *c, char *key, config_type_t type, void *arg);
|
static int config_compare(struct config_line_t *c, const char *key, config_type_t type, void *arg);
|
||||||
static int config_assign(or_options_t *options, struct config_line_t *list);
|
static int config_assign(or_options_t *options, struct config_line_t *list);
|
||||||
|
|
||||||
/** Open a configuration file for reading */
|
/** Open a configuration file for reading */
|
||||||
@ -131,12 +131,17 @@ static void config_free_lines(struct config_line_t *front) {
|
|||||||
* the result in <b>arg</b>. If the option is misformatted, log a warning and
|
* the result in <b>arg</b>. If the option is misformatted, log a warning and
|
||||||
* skip it.
|
* skip it.
|
||||||
*/
|
*/
|
||||||
static int config_compare(struct config_line_t *c, char *key, config_type_t type, void *arg) {
|
static int config_compare(struct config_line_t *c, const char *key, config_type_t type, void *arg) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(strncasecmp(c->key,key,strlen(c->key)))
|
if(strncasecmp(c->key,key,strlen(c->key)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if(strcasecmp(c->key,key)) {
|
||||||
|
tor_free(c->key);
|
||||||
|
c->key = tor_strdup(key);
|
||||||
|
}
|
||||||
|
|
||||||
/* it's a match. cast and assign. */
|
/* it's a match. cast and assign. */
|
||||||
log_fn(LOG_DEBUG,"Recognized keyword '%s' as %s, using value '%s'.",c->key,key,c->value);
|
log_fn(LOG_DEBUG,"Recognized keyword '%s' as %s, using value '%s'.",c->key,key,c->value);
|
||||||
|
|
||||||
@ -204,8 +209,8 @@ static int config_assign(or_options_t *options, struct config_line_t *list) {
|
|||||||
|
|
||||||
config_compare(list, "KeepalivePeriod",CONFIG_TYPE_INT, &options->KeepalivePeriod) ||
|
config_compare(list, "KeepalivePeriod",CONFIG_TYPE_INT, &options->KeepalivePeriod) ||
|
||||||
|
|
||||||
config_compare(list, "LogLevel", CONFIG_TYPE_STRING, &options->LogLevel) ||
|
config_compare(list, "LogLevel", CONFIG_TYPE_LINELIST, &options->LogOptions) ||
|
||||||
config_compare(list, "LogFile", CONFIG_TYPE_STRING, &options->LogFile) ||
|
config_compare(list, "LogFile", CONFIG_TYPE_LINELIST, &options->LogOptions) ||
|
||||||
config_compare(list, "LinkPadding", CONFIG_TYPE_BOOL, &options->LinkPadding) ||
|
config_compare(list, "LinkPadding", CONFIG_TYPE_BOOL, &options->LinkPadding) ||
|
||||||
|
|
||||||
config_compare(list, "MaxConn", CONFIG_TYPE_INT, &options->MaxConn) ||
|
config_compare(list, "MaxConn", CONFIG_TYPE_INT, &options->MaxConn) ||
|
||||||
@ -460,8 +465,7 @@ static int resolve_my_address(or_options_t *options) {
|
|||||||
|
|
||||||
/** Release storage held by <b>options</b> */
|
/** Release storage held by <b>options</b> */
|
||||||
static void free_options(or_options_t *options) {
|
static void free_options(or_options_t *options) {
|
||||||
tor_free(options->LogLevel);
|
config_free_lines(options->LogOptions);
|
||||||
tor_free(options->LogFile);
|
|
||||||
tor_free(options->DebugLogFile);
|
tor_free(options->DebugLogFile);
|
||||||
tor_free(options->DataDirectory);
|
tor_free(options->DataDirectory);
|
||||||
tor_free(options->RouterFile);
|
tor_free(options->RouterFile);
|
||||||
@ -487,7 +491,7 @@ static void free_options(or_options_t *options) {
|
|||||||
static void init_options(or_options_t *options) {
|
static void init_options(or_options_t *options) {
|
||||||
/* give reasonable values for each option. Defaults to zero. */
|
/* give reasonable values for each option. Defaults to zero. */
|
||||||
memset(options,0,sizeof(or_options_t));
|
memset(options,0,sizeof(or_options_t));
|
||||||
options->LogLevel = tor_strdup("notice");
|
options->LogOptions = NULL;
|
||||||
options->ExitNodes = tor_strdup("");
|
options->ExitNodes = tor_strdup("");
|
||||||
options->EntryNodes = tor_strdup("");
|
options->EntryNodes = tor_strdup("");
|
||||||
options->ExcludeNodes = tor_strdup("");
|
options->ExcludeNodes = tor_strdup("");
|
||||||
@ -498,7 +502,6 @@ static void init_options(or_options_t *options) {
|
|||||||
options->ORBindAddress = tor_strdup("0.0.0.0");
|
options->ORBindAddress = tor_strdup("0.0.0.0");
|
||||||
options->DirBindAddress = tor_strdup("0.0.0.0");
|
options->DirBindAddress = tor_strdup("0.0.0.0");
|
||||||
options->RecommendedVersions = NULL;
|
options->RecommendedVersions = NULL;
|
||||||
options->loglevel = LOG_INFO;
|
|
||||||
options->PidFile = NULL; // tor_strdup("tor.pid");
|
options->PidFile = NULL; // tor_strdup("tor.pid");
|
||||||
options->DataDirectory = NULL;
|
options->DataDirectory = NULL;
|
||||||
options->PathlenCoinWeight = 0.3;
|
options->PathlenCoinWeight = 0.3;
|
||||||
@ -616,23 +619,6 @@ int getconfig(int argc, char **argv, or_options_t *options) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options->LogLevel) {
|
|
||||||
if(!strcmp(options->LogLevel,"err"))
|
|
||||||
options->loglevel = LOG_ERR;
|
|
||||||
else if(!strcmp(options->LogLevel,"warn"))
|
|
||||||
options->loglevel = LOG_WARN;
|
|
||||||
else if(!strcmp(options->LogLevel,"notice"))
|
|
||||||
options->loglevel = LOG_NOTICE;
|
|
||||||
else if(!strcmp(options->LogLevel,"info"))
|
|
||||||
options->loglevel = LOG_INFO;
|
|
||||||
else if(!strcmp(options->LogLevel,"debug"))
|
|
||||||
options->loglevel = LOG_DEBUG;
|
|
||||||
else {
|
|
||||||
log(LOG_WARN,"LogLevel must be one of err|warn|notice|info|debug.");
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(options->ORPort < 0) {
|
if(options->ORPort < 0) {
|
||||||
log(LOG_WARN,"ORPort option can't be negative.");
|
log(LOG_WARN,"ORPort option can't be negative.");
|
||||||
result = -1;
|
result = -1;
|
||||||
@ -727,6 +713,101 @@ int getconfig(int argc, char **argv, or_options_t *options) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_single_log(struct config_line_t *level_opt,
|
||||||
|
struct config_line_t *file_opt,
|
||||||
|
int isDaemon)
|
||||||
|
{
|
||||||
|
int levelMin=-1, levelMax=-1;
|
||||||
|
char *cp, *tmp_sev;
|
||||||
|
|
||||||
|
if (level_opt) {
|
||||||
|
cp = strchr(level_opt->value, '-');
|
||||||
|
if (cp) {
|
||||||
|
tmp_sev = tor_strndup(level_opt->value, cp - level_opt->value);
|
||||||
|
levelMin = parse_log_level(tmp_sev);
|
||||||
|
if (levelMin<0) {
|
||||||
|
log_fn(LOG_WARN, "Unrecognized log severity %s: must be one of err|warn|notice|info|debug", tmp_sev);
|
||||||
|
}
|
||||||
|
tor_free(tmp_sev);
|
||||||
|
levelMax = parse_log_level(cp+1);
|
||||||
|
if (levelMax<0) {
|
||||||
|
log_fn(LOG_WARN, "Unrecognized log severity %s: must be one of err|warn|notice|info|debug", cp+1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
levelMin = parse_log_level(level_opt->value);
|
||||||
|
if (levelMin<0) {
|
||||||
|
log_fn(LOG_WARN, "Unrecognized log severity %s: must be one of err|warn|notice|info|debug", level_opt->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (levelMin < 0 && levelMax < 0) {
|
||||||
|
levelMin = LOG_NOTICE;
|
||||||
|
levelMax = LOG_ERR;
|
||||||
|
} else if (levelMin < 0) {
|
||||||
|
levelMin = levelMax;
|
||||||
|
} else {
|
||||||
|
levelMax = LOG_ERR;
|
||||||
|
}
|
||||||
|
if (file_opt) {
|
||||||
|
if (add_file_log(levelMin, levelMax, file_opt->value) < 0) {
|
||||||
|
/* opening the log file failed! Use stderr and log a warning */
|
||||||
|
add_stream_log(levelMin, levelMax, "<stderr>", stderr);
|
||||||
|
log_fn(LOG_WARN, "Cannot write to LogFile '%s': %s.", file_opt->value,
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
log_fn(LOG_NOTICE, "Successfully opened LogFile '%s', redirecting output.",
|
||||||
|
file_opt->value);
|
||||||
|
} else if (!isDaemon) {
|
||||||
|
add_stream_log(levelMin, levelMax, "<stderr>", stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the logs based on the configuration file.
|
||||||
|
*/
|
||||||
|
void config_init_logs(or_options_t *options)
|
||||||
|
{
|
||||||
|
/* The order of options is: Level? (File Level?)+
|
||||||
|
*/
|
||||||
|
struct config_line_t *opt = options->LogOptions;
|
||||||
|
|
||||||
|
/* Special case for if first option is LogLevel. */
|
||||||
|
if (opt && !strcasecmp(opt->key, "LogLevel")) {
|
||||||
|
if (opt->next && !strcasecmp(opt->next->key, "LogFile")) {
|
||||||
|
add_single_log(opt, opt->next, options->RunAsDaemon);
|
||||||
|
opt = opt->next->next;
|
||||||
|
} else if (!opt->next) {
|
||||||
|
add_single_log(opt, NULL, options->RunAsDaemon);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
opt = opt->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (opt) {
|
||||||
|
if (!strcasecmp(opt->key, "LogLevel")) {
|
||||||
|
log_fn(LOG_WARN, "Two LogLevel options in a row without intervening LogFile");
|
||||||
|
opt = opt->next;
|
||||||
|
} else {
|
||||||
|
assert(!strcasecmp(opt->key, "LogFile"));
|
||||||
|
if (opt->next && !strcasecmp(opt->next->key, "LogLevel")) {
|
||||||
|
/* LogFile followed by LogLevel */
|
||||||
|
add_single_log(opt->next, opt, options->RunAsDaemon);
|
||||||
|
opt = opt->next->next;
|
||||||
|
} else {
|
||||||
|
/* LogFile followed by LogFile or end of list. */
|
||||||
|
add_single_log(NULL, opt, options->RunAsDaemon);
|
||||||
|
opt = opt->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options->DebugLogFile) {
|
||||||
|
log_fn(LOG_WARN, "DebugLogFile is deprecated; use LogFile and LogLevel instead");
|
||||||
|
add_file_log(LOG_DEBUG, LOG_ERR, options->DebugLogFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode:c
|
mode:c
|
||||||
|
@ -566,22 +566,7 @@ static int init_from_config(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the log(s) */
|
/* Configure the log(s) */
|
||||||
if(!options.LogFile && !options.RunAsDaemon)
|
config_init_logs(&options);
|
||||||
add_stream_log(options.loglevel, "<stdout>", stdout);
|
|
||||||
if(options.LogFile) {
|
|
||||||
if (add_file_log(options.loglevel, options.LogFile) != 0) {
|
|
||||||
/* opening the log file failed! Use stderr and log a warning */
|
|
||||||
add_stream_log(options.loglevel, "<stderr>", stderr);
|
|
||||||
log_fn(LOG_WARN, "Cannot write to LogFile '%s': %s.", options.LogFile, strerror(errno));
|
|
||||||
}
|
|
||||||
log_fn(LOG_NOTICE, "Successfully opened LogFile '%s', redirecting output.",
|
|
||||||
options.LogFile);
|
|
||||||
}
|
|
||||||
if(options.DebugLogFile) {
|
|
||||||
if (add_file_log(LOG_DEBUG, options.DebugLogFile) != 0)
|
|
||||||
log_fn(LOG_WARN, "Cannot write to DebugLogFile '%s': %s.", options.DebugLogFile, strerror(errno));
|
|
||||||
log_fn(LOG_DEBUG, "Successfully opened DebugLogFile '%s'.", options.DebugLogFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up our buckets */
|
/* Set up our buckets */
|
||||||
connection_bucket_init();
|
connection_bucket_init();
|
||||||
@ -696,7 +681,7 @@ static int do_main_loop(void) {
|
|||||||
#ifndef MS_WINDOWS /* do signal stuff only on unix */
|
#ifndef MS_WINDOWS /* do signal stuff only on unix */
|
||||||
if(please_dumpstats) {
|
if(please_dumpstats) {
|
||||||
/* prefer to log it at INFO, but make sure we always see it */
|
/* prefer to log it at INFO, but make sure we always see it */
|
||||||
dumpstats(options.loglevel>LOG_INFO ? options.loglevel : LOG_INFO);
|
dumpstats(get_min_log_level()>LOG_INFO ? get_min_log_level() : LOG_INFO);
|
||||||
please_dumpstats = 0;
|
please_dumpstats = 0;
|
||||||
}
|
}
|
||||||
if(please_reset) {
|
if(please_reset) {
|
||||||
@ -867,7 +852,7 @@ void exit_function(void)
|
|||||||
int tor_main(int argc, char *argv[]) {
|
int tor_main(int argc, char *argv[]) {
|
||||||
|
|
||||||
/* give it somewhere to log to initially */
|
/* give it somewhere to log to initially */
|
||||||
add_stream_log(LOG_INFO, "<stdout>", stdout);
|
add_stream_log(LOG_INFO, LOG_ERR, "<stdout>", stdout);
|
||||||
log_fn(LOG_NOTICE,"Tor v%s. This is experimental software. Do not use it if you need anonymity.",VERSION);
|
log_fn(LOG_NOTICE,"Tor v%s. This is experimental software. Do not use it if you need anonymity.",VERSION);
|
||||||
|
|
||||||
if (network_init()<0) {
|
if (network_init()<0) {
|
||||||
|
@ -753,6 +753,9 @@ typedef struct circuit_t circuit_t;
|
|||||||
|
|
||||||
/** Configuration options for a Tor process */
|
/** Configuration options for a Tor process */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
struct config_line_t *LogOptions; /**< List of configuration lines
|
||||||
|
* for logfiles */
|
||||||
|
|
||||||
char *LogLevel; /**< Verbosity of log: minimal level of messages to report. */
|
char *LogLevel; /**< Verbosity of log: minimal level of messages to report. */
|
||||||
char *LogFile; /**< Where to send normal log messages. */
|
char *LogFile; /**< Where to send normal log messages. */
|
||||||
char *DebugLogFile; /**< Where to send verbose log messages. */
|
char *DebugLogFile; /**< Where to send verbose log messages. */
|
||||||
@ -811,8 +814,6 @@ typedef struct {
|
|||||||
int BandwidthBurst; /**< How much bandwidth, at maximum, are we willing to
|
int BandwidthBurst; /**< How much bandwidth, at maximum, are we willing to
|
||||||
* use in a second? */
|
* use in a second? */
|
||||||
int NumCpus; /**< How many CPUs should we try to use? */
|
int NumCpus; /**< How many CPUs should we try to use? */
|
||||||
int loglevel; /**< How verbose should we be? Log messages less severe than
|
|
||||||
* this will be ignored. */
|
|
||||||
int RunTesting; /**< If true, create testing circuits to measure how well the
|
int RunTesting; /**< If true, create testing circuits to measure how well the
|
||||||
* other ORs are running. */
|
* other ORs are running. */
|
||||||
struct config_line_t *RendConfigLines; /**< List of configuration lines
|
struct config_line_t *RendConfigLines; /**< List of configuration lines
|
||||||
@ -951,6 +952,7 @@ struct config_line_t {
|
|||||||
|
|
||||||
int config_assign_default_dirservers(void);
|
int config_assign_default_dirservers(void);
|
||||||
int getconfig(int argc, char **argv, or_options_t *options);
|
int getconfig(int argc, char **argv, or_options_t *options);
|
||||||
|
void config_init_logs(or_options_t *options);
|
||||||
|
|
||||||
/********************************* connection.c ***************************/
|
/********************************* connection.c ***************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user