17 #ifdef HAVE_SYS_TIME_H
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
57 #define TRUNCATED_STR "[...truncated]"
58 #define TRUNCATED_STR_LEN 14
83 #define log_free(lg) \
84 FREE_AND_NULL(logfile_t, log_free_, (lg))
87 static inline const char *
98 raw_assert_unreached();
return "UNKNOWN";
119 raw_assert(0);
return 0;
136 static int syslog_count = 0;
172 #define MAX_STARTUP_MSG_LEN (1<<16)
175 #define LOCK_LOGS() STMT_BEGIN \
176 raw_assert(log_mutex_initialized); \
177 tor_mutex_acquire(&log_mutex); \
180 #define UNLOCK_LOGS() STMT_BEGIN \
181 raw_assert(log_mutex_initialized); \
182 tor_mutex_release(&log_mutex); \
194 char *buf,
size_t buflen);
195 static inline char *
format_msg(
char *buf,
size_t buf_len,
198 const char *format, va_list ap,
size_t *msg_len_out)
236 const char *
function,
const char *
string)
238 log_fn_(severity, domain,
function,
"%s",
string);
266 t = (time_t)now.tv_sec;
267 ms = (
int)now.tv_usec / 1000;
275 n = strftime(buf, buf_len,
"%b %d %H:%M:%S",
307 if (reset && !is_new)
314 "%s opening %slog file.\n",
appname, is_new?
"new ":
"");
317 "Tor %s opening %slog file.\n", VERSION, is_new?
"new ":
"");
333 const char *format, va_list ap,
size_t *msg_len_out)
340 raw_assert(buf_len >= 16);
342 buf_end = buf+buf_len;
345 end_of_prefix = buf+n;
349 if (cp == buf_end)
goto format_msg_no_room_for_domains;
351 if (cp == buf_end)
goto format_msg_no_room_for_domains;
353 if (cp == buf_end)
goto format_msg_no_room_for_domains;
355 if (cp == buf_end)
goto format_msg_no_room_for_domains;
357 if (cp == buf_end)
goto format_msg_no_room_for_domains;
360 format_msg_no_room_for_domains:
376 if (domain ==
LD_BUG && buf_len-n > 6) {
377 memcpy(buf+n,
"Bug: ", 6);
385 if (buf_len >= TRUNCATED_STR_LEN) {
386 size_t offset = buf_len-TRUNCATED_STR_LEN;
397 size_t suffix_len = strlen(suffix);
398 if (buf_len-n >= suffix_len) {
399 memcpy(buf+n, suffix, suffix_len);
414 return end_of_prefix;
420 const char *fullmsg,
const char *shortmsg)
425 m->
fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
426 m->
msg = tor_strdup(shortmsg);
430 #define pending_log_message_free(msg) \
431 FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
483 int severity,
int *callbacks_deferred)
493 #warning "MAXLINE is very low; it might not be from syslog.h."
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) {
504 syslog(severity,
"%s", msg_after_prefix);
511 pending_log_message_new(severity,domain,NULL,msg_after_prefix));
512 *callbacks_deferred = 1;
518 lf->
callback(severity, domain, msg_after_prefix);
535 const char *suffix,
const char *format, va_list ap))
541 char *end_of_prefix=NULL;
542 int callbacks_deferred = 0;
559 format_msg(buf,
sizeof(buf), domain, severity, funcname, suffix,
560 format, ap, &msg_len);
564 pending_log_message_new(severity,domain,buf,end_of_prefix));
574 format_msg(buf,
sizeof(buf), domain, severity, funcname, suffix,
575 format, ap, &msg_len);
580 &callbacks_deferred);
600 #ifdef TOR_UNIT_TESTS
601 if (domain & LD_NO_MOCK)
602 logv__real(severity, domain, NULL, NULL, format, ap);
605 logv(severity, domain, NULL, NULL, format, ap);
615 for (j = 0; j < n; ++j) {
616 if (array[j] == item)
628 int found_real_stderr = 0;
638 fds[0] = STDERR_FILENO;
651 if (lf->
fd == STDERR_FILENO)
652 found_real_stderr = 1;
664 if (!found_real_stderr &&
670 raw_assert(n_fds >= 2);
706 const char *format, ...)
712 logv(severity, domain, fn, NULL, format, ap);
717 const char *fn,
const char *format, ...)
726 va_start(ap, format);
727 logv(severity, domain, fn, m, format, ap);
767 pending_log_message_free(msg);
769 smartlist_free(messages);
773 pending_log_message_free(msg);
775 smartlist_free(messages2);
805 (void)fsync(victim->
fd);
856 if (--syslog_count == 0) {
872 raw_assert(loglevelMin >= loglevelMax);
876 for (i = loglevelMin; i >= loglevelMax; --i) {
918 if (strchr(__PRETTY_FUNCTION__,
'(')) {
924 if (disable_startup_queue)
983 lf->
filename = tor_strdup(
"<callback>");
1006 memcpy(lf->
severities, &severities,
sizeof(severities));
1031 const int severity = msg->severity;
1038 lf->
callback(severity, domain, msg->msg);
1040 pending_log_message_free(msg);
1041 } SMARTLIST_FOREACH_END(msg);
1046 messages = messages_tmp;
1047 }
while (smartlist_len(messages));
1049 smartlist_free(messages);
1070 int callbacks_deferred = 0;
1077 if (lf->
fd == STDOUT_FILENO || lf->
fd == STDERR_FILENO) {
1082 msg->domain, msg->severity, &callbacks_deferred);
1084 pending_log_message_free(msg);
1085 } SMARTLIST_FOREACH_END(msg);
1101 if ((*p)->is_temporary) {
1147 const char *filename,
1173 #ifdef HAVE_SYSLOG_H
1182 const char* syslog_identity_tag)
1185 if (syslog_count++ == 0) {
1187 static char buf[256];
1188 if (syslog_identity_tag) {
1189 tor_snprintf(buf,
sizeof(buf),
"Tor-%s", syslog_identity_tag);
1193 openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1196 lf = tor_malloc_zero(
sizeof(
logfile_t));
1199 lf->
filename = tor_strdup(
"<syslog>");
1216 if (!strcasecmp(level,
"err"))
1218 if (!strcasecmp(level,
"warn"))
1220 if (!strcasecmp(level,
"notice"))
1222 if (!strcasecmp(level,
"info"))
1224 if (!strcasecmp(level,
"debug"))
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",
1263 return (UINT64_C(1)<<i);
1273 char *eos = buf+buflen;
1284 tor_snprintf(buf, buflen,
"<BUG:Unknown domain %lx>", (
long)domain);
1285 return buf+strlen(buf);
1288 n = strlcpy(cp, d, eos-cp);
1290 tor_snprintf(buf, buflen,
"<BUG:Truncating domain %lx>", (
long)domain);
1291 return buf+strlen(buf);
1294 domain &= ~(1<<bit);
1296 if (domain == 0 || (eos-cp) < 2)
1325 const char *cfg = *cfg_ptr;
1326 int got_anything = 0;
1327 int got_an_unqualified_range = 0;
1328 memset(severity_out, 0,
sizeof(*severity_out));
1332 const char *dash, *space;
1333 char *sev_lo, *sev_hi;
1342 const char *closebracket = strchr(cfg,
']');
1346 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1352 if (!strcmp(domain,
"*")) {
1357 if (*domain ==
'~') {
1363 log_warn(
LD_CONFIG,
"No such logging domain as %s", domain);
1372 } SMARTLIST_FOREACH_END(domain);
1374 smartlist_free(domains_list);
1377 if (domains == 0 && neg_domains)
1378 domains = ~neg_domains;
1380 domains &= ~neg_domains;
1383 ++got_an_unqualified_range;
1391 if (got_an_unqualified_range > 1)
1395 dash = strchr(cfg,
'-');
1396 if (dash && dash < space) {
1397 sev_lo = tor_strndup(cfg, dash-cfg);
1398 sev_hi = tor_strndup(dash+1, space-(dash+1));
1400 sev_lo = tor_strndup(cfg, space-cfg);
1401 sev_hi = tor_strdup(
"ERR");
1413 for (i=low; i >= high; --i)
1414 severity_out->
masks[SEVERITY_MASK_IDX(i)] |= domains;
1421 return got_anything ? 0 : -1;
Header for approx_time.c.
int tor_log2(uint64_t u64)
Header for compat_mutex.c.
void tor_mutex_init(tor_mutex_t *m)
Header for compat_string.c.
Compile-time assertions: CTASSERT(expression).
int tor_fd_seekend(int fd)
off_t tor_fd_getpos(int fd)
int write_all_to_fd_minimal(int fd, const char *buf, size_t count)
int tor_ftruncate(int fd)
const char tor_bug_suffix[]
Header for git_revision.c.
int add_file_log(const log_severity_list_t *severity, const char *filename, int fd)
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
void init_logging(int disable_startup_queue)
static int log_time_granularity
void flush_log_messages_from_startup(void)
void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb)
static char * domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
void mark_logs_temp(void)
static void log_free_(logfile_t *victim)
static log_domain_mask_t parse_log_domain(const char *domain)
void logs_flush_sigsafe(void)
void rollback_log_changes(void)
void logs_set_pending_callback_callback(pending_callback_callback cb)
int add_callback_log(const log_severity_list_t *severity, log_callback cb)
void switch_logs_debug(void)
static char * format_msg(char *buf, size_t buf_len, log_domain_mask_t domain, int severity, const char *funcname, const char *suffix, const char *format, va_list ap, size_t *msg_len_out)
void log_fn_(int severity, log_domain_mask_t domain, const char *fn, const char *format,...)
void set_log_severity_config(int loglevelMin, int loglevelMax, log_severity_list_t *severity_out)
void tor_log_string(int severity, log_domain_mask_t domain, const char *function, const char *string)
static int pretty_fn_has_parens
int get_min_log_level(void)
static int logfile_wants_message(const logfile_t *lf, int severity, log_domain_mask_t domain)
void log_set_application_name(const char *name)
const char * log_level_to_string(int level)
STATIC void add_stream_log_impl(const log_severity_list_t *severity, const char *name, int fd)
static smartlist_t * pending_startup_messages
void set_log_time_granularity(int granularity_msec)
void flush_pending_log_callbacks(void)
int log_message_is_interesting(int severity, log_domain_mask_t domain)
static void close_log(logfile_t *victim)
static int log_tor_version(logfile_t *lf, int reset)
static void close_log_sigsafe(logfile_t *victim)
static int logfile_is_external(const logfile_t *lf)
int log_global_min_severity_
static const char * domain_list[]
static void pending_log_message_free_(pending_log_message_t *msg)
void tor_log_update_sigsafe_err_fds(void)
static int log_domains_are_logged
static tor_mutex_t log_mutex
void add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
static smartlist_t * pending_cb_messages
static const char * sev_to_string(int severity)
void add_default_log(int min_severity)
static logfile_t * logfiles
STATIC void logv(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap)
static size_t log_prefix_(char *buf, size_t buf_len, int severity)
static int log_mutex_initialized
int parse_log_level(const char *level)
#define MAX_STARTUP_MSG_LEN
static void logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len, const char *msg_after_prefix, log_domain_mask_t domain, int severity, int *callbacks_deferred)
static void delete_log(logfile_t *victim)
static int int_array_contains(const int *array, int n, int item)
void logs_set_domain_logging(int enabled)
void tor_log_get_logfile_names(smartlist_t *out)
static int queue_startup_messages
int parse_log_severity_config(const char **cfg_ptr, log_severity_list_t *severity_out)
static pending_callback_callback pending_cb_cb
static int should_log_function_name(log_domain_mask_t domain, int severity)
void close_temp_logs(void)
static size_t pending_startup_messages_len
void(* log_callback)(int severity, log_domain_mask_t domain, const char *msg)
#define LOWEST_RESERVED_LD_FLAG_
#define N_LOGGING_DOMAINS
#define HIGHEST_RESERVED_LD_DOMAIN_
Declare subsystem object for the logging module.
uint64_t log_domain_mask_t
Headers for util_malloc.c.
int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
int tor_snprintf(char *str, size_t size, const char *format,...)
char * rate_limit_log(ratelim_t *lim, time_t now)
Summarize similar messages that would otherwise flood the logs.
smartlist_t * smartlist_new(void)
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_clear(smartlist_t *sl)
Top-level declarations for the smartlist_t dynamic array type.
Macros for iterating over the elements of a smartlist_t.
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
Header for smartlist_split.c.
log_domain_mask_t masks[LOG_DEBUG-LOG_ERR+1]
log_severity_list_t * severities
#define MOCK_IMPL(rv, funcname, arglist)
Definitions for timing-related constants.
struct tm * tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
void tor_gettimeofday(struct timeval *timeval)
Header for tor_gettimeofday.c.
void tor_log_sigsafe_err_set_granularity(int ms)
void tor_log_set_sigsafe_err_fds(const int *fds, int n)
#define TOR_SIGSAFE_LOG_MAX_FDS
int strcasecmpstart(const char *s1, const char *s2)
const char * find_whitespace(const char *s)
const char * eat_whitespace(const char *s)
Header for util_string.c.