#include "orconfig.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include "lib/err/torerr.h"
#include "lib/err/backtrace.h"
static int sigsafe_log_fds[TOR_SIGSAFE_LOG_MAX_FDS] = { STDERR_FILENO };
static int n_sigsafe_log_fds = 1;
static int log_granularity = 1000;
static int
tor_log_err_sigsafe_write(const char *s)
{
int i;
ssize_t r;
size_t len = strlen(s);
int err = 0;
for (i=0; i < n_sigsafe_log_fds; ++i) {
r = write(sigsafe_log_fds[i], s, len);
err += (r != (ssize_t)len);
}
return err ? -1 : 0;
}
void
tor_log_err_sigsafe(const char *m, ...)
{
va_list ap;
const char *x;
char timebuf[33];
time_t now = time(NULL);
if (!m)
return;
if (log_granularity >= 2000) {
int g = log_granularity / 1000;
now -= now % g;
}
timebuf[0] = now < 0 ? '-' : ' ';
if (now < 0) now = -now;
timebuf[1] = '\0';
format_dec_number_sigsafe(now, timebuf+1, sizeof(timebuf)-1);
tor_log_err_sigsafe_write("\n=========================================="
"================== T=");
tor_log_err_sigsafe_write(timebuf);
tor_log_err_sigsafe_write("\n");
tor_log_err_sigsafe_write(m);
va_start(ap, m);
while ((x = va_arg(ap, const char*))) {
tor_log_err_sigsafe_write(x);
}
va_end(ap);
}
int
tor_log_get_sigsafe_err_fds(const int **out)
{
*out = sigsafe_log_fds;
return n_sigsafe_log_fds;
}
void
tor_log_set_sigsafe_err_fds(const int *fds, int n)
{
if (n > TOR_SIGSAFE_LOG_MAX_FDS) {
n = TOR_SIGSAFE_LOG_MAX_FDS;
}
n_sigsafe_log_fds = 0;
memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
if (fds && n > 0) {
memcpy(sigsafe_log_fds, fds, n * sizeof(int));
n_sigsafe_log_fds = n;
}
}
void
tor_log_reset_sigsafe_err_fds(void)
{
int fds[] = { STDERR_FILENO };
tor_log_set_sigsafe_err_fds(fds, 1);
}
void
tor_log_flush_sigsafe_err_fds(void)
{
#ifdef HAVE_FSYNC
int n_fds, i;
const int *fds = NULL;
n_fds = tor_log_get_sigsafe_err_fds(&fds);
for (i = 0; i < n_fds; ++i) {
(void)fsync(fds[i]);
}
#endif
}
void
tor_log_sigsafe_err_set_granularity(int ms)
{
log_granularity = ms;
}
void
tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
const char *msg)
{
char linebuf[16];
format_dec_number_sigsafe(line, linebuf, sizeof(linebuf));
tor_log_err_sigsafe("INTERNAL ERROR: Raw assertion failed in ",
get_tor_backtrace_version(), " at ",
file, ":", linebuf, ": ", expr, "\n", NULL);
if (msg) {
tor_log_err_sigsafe_write(msg);
tor_log_err_sigsafe_write("\n");
}
dump_stack_symbols_to_error_fds();
tor_log_err_sigsafe_write("\n");
}
void
tor_raw_abort_(void)
{
tor_log_flush_sigsafe_err_fds();
abort();
}
static int
format_number_sigsafe(unsigned long x, char *buf, int buf_len,
unsigned int radix)
{
unsigned long tmp;
int len;
char *cp;
if (radix < 2 || radix > 16)
return 0;
tmp = x;
len = 1;
while (tmp >= radix) {
tmp /= radix;
++len;
}
if (!buf || len >= buf_len)
return 0;
cp = buf + len;
*cp = '\0';
do {
unsigned digit = (unsigned) (x % radix);
if (cp <= buf) {
tor_raw_abort_();
}
--cp;
*cp = "0123456789ABCDEF"[digit];
x /= radix;
} while (x);
if (cp != buf) {
tor_raw_abort_(); }
return len;
}
int
format_hex_number_sigsafe(unsigned long x, char *buf, int buf_len)
{
return format_number_sigsafe(x, buf, buf_len, 16);
}
int
format_dec_number_sigsafe(unsigned long x, char *buf, int buf_len)
{
return format_number_sigsafe(x, buf, buf_len, 10);
}