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, ...)
713 logv(severity, domain, fn, NULL, format, ap);
718 const char *fn,
const char *format, ...)
727 va_start(ap, format);
728 logv(severity, domain, fn, m, format, ap);
768 pending_log_message_free(msg);
770 smartlist_free(messages);
774 pending_log_message_free(msg);
776 smartlist_free(messages2);
806 (void)fsync(victim->
fd);
857 if (--syslog_count == 0) {
873 raw_assert(loglevelMin >= loglevelMax);
877 for (i = loglevelMin; i >= loglevelMax; --i) {
916 tor_bug_init_counter();
920 if (strchr(__PRETTY_FUNCTION__,
'(')) {
926 if (disable_startup_queue)
985 lf->
filename = tor_strdup(
"<callback>");
1008 memcpy(lf->
severities, &severities,
sizeof(severities));
1033 const int severity = msg->severity;
1040 lf->
callback(severity, domain, msg->msg);
1042 pending_log_message_free(msg);
1043 } SMARTLIST_FOREACH_END(msg);
1048 messages = messages_tmp;
1049 }
while (smartlist_len(messages));
1051 smartlist_free(messages);
1072 int callbacks_deferred = 0;
1079 if (lf->
fd == STDOUT_FILENO || lf->
fd == STDERR_FILENO) {
1084 msg->domain, msg->severity, &callbacks_deferred);
1086 pending_log_message_free(msg);
1087 } SMARTLIST_FOREACH_END(msg);
1103 if ((*p)->is_temporary) {
1149 const char *filename,
1184 const char* syslog_identity_tag)
1187 if (syslog_count++ == 0) {
1189 static char buf[256];
1190 if (syslog_identity_tag) {
1191 tor_snprintf(buf,
sizeof(buf),
"Tor-%s", syslog_identity_tag);
1195 openlog(buf, LOG_PID | LOG_NDELAY, LOGFACILITY);
1198 lf = tor_malloc_zero(
sizeof(
logfile_t));
1201 lf->
filename = tor_strdup(
"<syslog>");
1218 if (!strcasecmp(level,
"err"))
1220 if (!strcasecmp(level,
"warn"))
1222 if (!strcasecmp(level,
"notice"))
1224 if (!strcasecmp(level,
"info"))
1226 if (!strcasecmp(level,
"debug"))
1244 "GENERAL",
"CRYPTO",
"NET",
"CONFIG",
"FS",
"PROTOCOL",
"MM",
1245 "HTTP",
"APP",
"CONTROL",
"CIRC",
"REND",
"BUG",
"DIR",
"DIRSERV",
1246 "OR",
"EDGE",
"ACCT",
"HIST",
"HANDSHAKE",
"HEARTBEAT",
"CHANNEL",
1247 "SCHED",
"GUARD",
"CONSDIFF",
"DOS",
"PROCESS",
"PT",
"BTRACK",
"MESG",
1265 return (UINT64_C(1)<<i);
1275 char *eos = buf+buflen;
1286 tor_snprintf(buf, buflen,
"<BUG:Unknown domain %lx>", (
long)domain);
1287 return buf+strlen(buf);
1290 n = strlcpy(cp, d, eos-cp);
1292 tor_snprintf(buf, buflen,
"<BUG:Truncating domain %lx>", (
long)domain);
1293 return buf+strlen(buf);
1296 domain &= ~(1<<bit);
1298 if (domain == 0 || (eos-cp) < 2)
1327 const char *cfg = *cfg_ptr;
1328 int got_anything = 0;
1329 int got_an_unqualified_range = 0;
1330 memset(severity_out, 0,
sizeof(*severity_out));
1334 const char *dash, *space;
1335 char *sev_lo, *sev_hi;
1344 const char *closebracket = strchr(cfg,
']');
1348 domains_str = tor_strndup(cfg+1, closebracket-cfg-1);
1354 if (!strcmp(domain,
"*")) {
1359 if (*domain ==
'~') {
1365 log_warn(
LD_CONFIG,
"No such logging domain as %s", domain);
1374 } SMARTLIST_FOREACH_END(domain);
1376 smartlist_free(domains_list);
1379 if (domains == 0 && neg_domains)
1380 domains = ~neg_domains;
1382 domains &= ~neg_domains;
1385 ++got_an_unqualified_range;
1393 if (got_an_unqualified_range > 1)
1397 dash = strchr(cfg,
'-');
1398 if (dash && dash < space) {
1399 sev_lo = tor_strndup(cfg, dash-cfg);
1400 sev_hi = tor_strndup(dash+1, space-(dash+1));
1402 sev_lo = tor_strndup(cfg, space-cfg);
1403 sev_hi = tor_strdup(
"ERR");
1415 for (i=low; i >= high; --i)
1416 severity_out->
masks[SEVERITY_MASK_IDX(i)] |= domains;
1423 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
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.