26#ifdef HAVE_SYS_TYPES_H
58#define TRUNCATED_STR "[...truncated]"
59#define TRUNCATED_STR_LEN 14
85 FREE_AND_NULL(logfile_t, log_free_, (lg))
88static inline const char *
99 raw_assert_unreached();
return "UNKNOWN";
120 raw_assert(0);
return 0;
137static int syslog_count = 0;
173#define MAX_STARTUP_MSG_LEN (1<<16)
176#define LOCK_LOGS() STMT_BEGIN \
177 raw_assert(log_mutex_initialized); \
178 tor_mutex_acquire(&log_mutex); \
181#define UNLOCK_LOGS() STMT_BEGIN \
182 raw_assert(log_mutex_initialized); \
183 tor_mutex_release(&log_mutex); \
195 char *buf,
size_t buflen);
196static inline char *
format_msg(
char *buf,
size_t buf_len,
199 const char *format, va_list ap,
size_t *msg_len_out)
237 const char *function,
const char *
string)
239 log_fn_(severity, domain, function,
"%s",
string);
267 t = (time_t)now.tv_sec;
268 ms = (
int)now.tv_usec / 1000;
276 n = strftime(buf, buf_len,
"%b %d %H:%M:%S",
308 if (reset && !is_new)
315 "%s opening %slog file.\n",
appname, is_new?
"new ":
"");
318 "Tor %s opening %slog file.\n", VERSION, is_new?
"new ":
"");
334 const char *format, va_list ap,
size_t *msg_len_out)
341 raw_assert(buf_len >= 16);
343 buf_end = buf+buf_len;
346 end_of_prefix = buf+n;
350 if (cp == buf_end)
goto format_msg_no_room_for_domains;
352 if (cp == buf_end)
goto format_msg_no_room_for_domains;
354 if (cp == buf_end)
goto format_msg_no_room_for_domains;
356 if (cp == buf_end)
goto format_msg_no_room_for_domains;
358 if (cp == buf_end)
goto format_msg_no_room_for_domains;
361 format_msg_no_room_for_domains:
377 if (domain ==
LD_BUG && buf_len-n > 6) {
378 memcpy(buf+n,
"Bug: ", 6);
386 if (buf_len >= TRUNCATED_STR_LEN) {
387 size_t offset = buf_len-TRUNCATED_STR_LEN;
398 size_t suffix_len = strlen(suffix);
399 if (buf_len-n >= suffix_len) {
400 memcpy(buf+n, suffix, suffix_len);
415 return end_of_prefix;
421 const char *fullmsg,
const char *shortmsg)
426 m->
fullmsg = fullmsg ? tor_strdup(fullmsg) : NULL;
427 m->
msg = tor_strdup(shortmsg);
431#define pending_log_message_free(msg) \
432 FREE_AND_NULL(pending_log_message_t, pending_log_message_free_, (msg))
484 int severity,
int *callbacks_deferred)
494#warning "MAXLINE is very low; it might not be from syslog.h."
496 char *m = msg_after_prefix;
497 if (msg_len >= MAXLINE)
498 m = tor_strndup(msg_after_prefix, MAXLINE-1);
499 syslog(severity,
"%s", m);
500 if (m != msg_after_prefix) {
505 syslog(severity,
"%s", msg_after_prefix);
512 pending_log_message_new(severity,domain,NULL,msg_after_prefix));
513 *callbacks_deferred = 1;
519 lf->
callback(severity, domain, msg_after_prefix);
536 const char *suffix,
const char *format, va_list ap))
542 char *end_of_prefix=NULL;
543 int callbacks_deferred = 0;
560 format_msg(buf,
sizeof(buf), domain, severity, funcname, suffix,
561 format, ap, &msg_len);
565 pending_log_message_new(severity,domain,buf,end_of_prefix));
575 format_msg(buf,
sizeof(buf), domain, severity, funcname, suffix,
576 format, ap, &msg_len);
581 &callbacks_deferred);
602 if (domain & LD_NO_MOCK)
603 logv__real(severity, domain, NULL, NULL, format, ap);
606 logv(severity, domain, NULL, NULL, format, ap);
616 for (j = 0; j < n; ++j) {
617 if (array[j] == item)
629 int found_real_stderr = 0;
639 fds[0] = STDERR_FILENO;
652 if (lf->
fd == STDERR_FILENO)
653 found_real_stderr = 1;
665 if (!found_real_stderr &&
671 raw_assert(n_fds >= 2);
707 const char *format, ...)
715 logv(severity, domain, fn, NULL, format, ap);
720 const char *fn,
const char *format, ...)
731 va_start(ap, format);
732 logv(severity, domain, fn, m, format, ap);
772 pending_log_message_free(msg);
774 smartlist_free(messages);
778 pending_log_message_free(msg);
780 smartlist_free(messages2);
810 (void)fsync(victim->
fd);
861 if (--syslog_count == 0) {
877 raw_assert(loglevelMin >= loglevelMax);
881 for (i = loglevelMin; i >= loglevelMax; --i) {
920 tor_bug_init_counter();
924 if (strchr(__PRETTY_FUNCTION__,
'(')) {
930 if (disable_startup_queue)
989 lf->
filename = tor_strdup(
"<callback>");
1012 memcpy(lf->
severities, &severities,
sizeof(severities));
1037 const int severity = msg->severity;
1044 lf->
callback(severity, domain, msg->msg);
1046 pending_log_message_free(msg);
1047 } SMARTLIST_FOREACH_END(msg);
1052 messages = messages_tmp;
1053 }
while (smartlist_len(messages));
1055 smartlist_free(messages);
1076 int callbacks_deferred = 0;
1083 if (lf->
fd == STDOUT_FILENO || lf->
fd == STDERR_FILENO) {
1088 msg->domain, msg->severity, &callbacks_deferred);
1090 pending_log_message_free(msg);
1091 } SMARTLIST_FOREACH_END(msg);
1107 if ((*p)->is_temporary) {
1153 const char *filename,
1188 const char* syslog_identity_tag)
1191 if (syslog_count++ == 0) {
1193 static char buf[256];
1194 if (syslog_identity_tag) {
1195 tor_snprintf(buf,
sizeof(buf),
"Tor-%s", syslog_identity_tag);
1199 openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1202 lf = tor_malloc_zero(
sizeof(
logfile_t));
1205 lf->
filename = tor_strdup(
"<syslog>");
1222 if (!strcasecmp(level,
"err"))
1224 if (!strcasecmp(level,
"warn"))
1226 if (!strcasecmp(level,
"notice"))
1228 if (!strcasecmp(level,
"info"))
1230 if (!strcasecmp(level,
"debug"))
1248 "GENERAL",
"CRYPTO",
"NET",
"CONFIG",
"FS",
"PROTOCOL",
"MM",
1249 "HTTP",
"APP",
"CONTROL",
"CIRC",
"REND",
"BUG",
"DIR",
"DIRSERV",
1250 "OR",
"EDGE",
"ACCT",
"HIST",
"HANDSHAKE",
"HEARTBEAT",
"CHANNEL",
1251 "SCHED",
"GUARD",
"CONSDIFF",
"DOS",
"PROCESS",
"PT",
"BTRACK",
"MESG",
1269 return (UINT64_C(1)<<i);
1279 char *eos = buf+buflen;
1290 tor_snprintf(buf, buflen,
"<BUG:Unknown domain %lx>", (
long)domain);
1291 return buf+strlen(buf);
1294 n = strlcpy(cp, d, eos-cp);
1296 tor_snprintf(buf, buflen,
"<BUG:Truncating domain %lx>", (
long)domain);
1297 return buf+strlen(buf);
1300 domain &= ~(1<<bit);
1302 if (domain == 0 || (eos-cp) < 2)
1331 const char *cfg = *cfg_ptr;
1332 int got_anything = 0;
1333 int got_an_unqualified_range = 0;
1334 memset(severity_out, 0,
sizeof(*severity_out));
1338 const char *dash, *space;
1339 char *sev_lo, *sev_hi;
1348 const char *closebracket = strchr(cfg,
']');
1352 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1358 if (!strcmp(domain,
"*")) {
1363 if (*domain ==
'~') {
1369 log_warn(
LD_CONFIG,
"No such logging domain as %s", domain);
1378 } SMARTLIST_FOREACH_END(domain);
1380 smartlist_free(domains_list);
1383 if (domains == 0 && neg_domains)
1384 domains = ~neg_domains;
1386 domains &= ~neg_domains;
1389 ++got_an_unqualified_range;
1397 if (got_an_unqualified_range > 1)
1401 dash = strchr(cfg,
'-');
1402 if (dash && dash < space) {
1403 sev_lo = tor_strndup(cfg, dash-cfg);
1404 sev_hi = tor_strndup(dash+1, space-(dash+1));
1406 sev_lo = tor_strndup(cfg, space-cfg);
1407 sev_hi = tor_strdup(
"ERR");
1419 for (i=low; i >= high; --i)
1420 severity_out->
masks[SEVERITY_MASK_IDX(i)] |= domains;
1427 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).
CTASSERT(NUMBER_SECOND_GUARDS< 20)
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)
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
const char * log_level_to_string(int level)
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
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
static const char * sev_to_string(int severity)
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.
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
smartlist_t * smartlist_new(void)
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
void tor_bug_increment_count_(void)
Macros to manage assertions, fatal and non-fatal.
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.