diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-10-26 21:48:41 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-10-26 21:48:41 +0000 |
commit | 26f3cb865202160fe6b8ecfb20a0e41fea3a4a6a (patch) | |
tree | 4f0246453c39783f476c2b088a961d3fc0bf2da8 /src/common/log.c | |
parent | 64fc462a3a8687845c255c32941fee98a31eb3f3 (diff) | |
download | tor-26f3cb865202160fe6b8ecfb20a0e41fea3a4a6a.tar tor-26f3cb865202160fe6b8ecfb20a0e41fea3a4a6a.tar.gz |
Add SysLog option to direct log messages to the system log instead of a FILE*.
svn:r2591
Diffstat (limited to 'src/common/log.c')
-rw-r--r-- | src/common/log.c | 108 |
1 files changed, 84 insertions, 24 deletions
diff --git a/src/common/log.c b/src/common/log.c index 07a83e36f..3a64750ca 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -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) { - format_msg(buf, sizeof(buf), severity, funcname, format, ap); + 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"))) { - /* 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); - } + 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; } 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; |