failures.c revision 8009758e97922663d9a375a52efe044c8fe4d462
/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "str.h"
#include "hostpid.h"
#include "net.h"
#include "process-title.h"
#include "lib-signals.h"
#include "backtrace-string.h"
#include "printf-format-fix.h"
#include "write-full.h"
#include <unistd.h>
#include <fcntl.h>
#include <syslog.h>
#include <time.h>
const char *failure_log_type_prefixes[LOG_TYPE_COUNT] = {
"Debug: ",
"Info: ",
"Warning: ",
"Error: ",
"Fatal: ",
"Panic: "
};
const char *failure_log_type_names[LOG_TYPE_COUNT] = {
"debug", "info", "warning", "error", "fatal", "panic"
};
/* Initialize working defaults */
static void (*failure_exit_callback)(int *) = NULL;
static char *log_prefix = NULL;
static bool coredump_on_error = FALSE;
static void ATTR_FORMAT(2, 0)
/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
static const char *
ATTR_FORMAT_ARG(1);
unsigned int timestamp_usecs)
{
if (log_stamp_format_suffix == NULL)
return log_stamp_format;
}
void failure_exit(int status)
{
}
}
{
char buf[256];
if (log_stamp_format != NULL) {
i_panic("gettimeofday() failed: %m");
} else {
}
}
if (log_prefix != NULL)
}
{
}
{
unsigned int prev_signal_term_counter = signal_term_counter;
unsigned int terminal_eintr_count = 0;
if (ret > 0) {
/* some was written, continue.. */
continue;
}
if (ret == 0) {
/* out of disk space? */
return -1;
}
switch (errno) {
case EAGAIN: {
/* wait until we can write more. this can happen at
least when writing to terminal, even if fd is
blocking. Internal logging fd is also now
non-blocking, so we can show warnings about blocking
on a log write. */
title = "[blocking on log write]";
else
ioloop = io_loop_create();
break;
}
case EINTR:
if (prev_signal_term_counter == signal_term_counter) {
/* non-terminal signal. ignore. */
} else if (terminal_eintr_count++ == 0) {
/* we'd rather not die in the middle of
writing to log. try again once more */
} else {
/* received two terminal signals.
someone wants us dead. */
return -1;
}
break;
default:
return -1;
}
}
return 0;
}
static int ATTR_FORMAT(3, 0)
{
static int recursed = 0;
int ret;
if (recursed >= 2) {
/* we're being called from some signal handler or we ran
out of memory */
return -1;
}
recursed++;
T_BEGIN {
/* make sure there's no %n in there and fix %m */
} T_END;
if (ret < 0 && failure_ignore_errors)
ret = 0;
recursed--;
return ret;
}
static void ATTR_NORETURN
{
const char *backtrace;
static int recursed = 0;
recursed++;
recursed == 1) {
if (backtrace_get(&backtrace) == 0)
}
recursed--;
abort();
else
}
{
status == FATAL_DEFAULT)
}
{
int fd;
case LOG_TYPE_DEBUG:
fd = log_debug_fd;
break;
case LOG_TYPE_INFO:
fd = log_info_fd;
break;
default:
}
write error to error log - maybe that'll work. */
}
abort();
}
{
}
{
case LOG_TYPE_DEBUG:
break;
case LOG_TYPE_INFO:
break;
default:
}
}
{
struct failure_context ctx;
i_unreached();
/*va_end(args);*/
}
{
struct failure_context ctx;
i_unreached();
/*va_end(args);*/
}
{
struct failure_context ctx;
i_unreached();
/*va_end(args);*/
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
static int ATTR_FORMAT(3, 0)
{
static int recursed = 0;
if (recursed >= 2)
return -1;
recursed++;
/* syslogs don't generally bother to log the level in any way,
so make sure errors are shown clearly */
T_BEGIN {
type != LOG_TYPE_INFO ?
} T_END;
recursed--;
return 0;
}
{
status == FATAL_DEFAULT)
}
{
case LOG_TYPE_DEBUG:
break;
case LOG_TYPE_INFO:
break;
case LOG_TYPE_WARNING:
level = LOG_WARNING;
break;
case LOG_TYPE_ERROR:
break;
case LOG_TYPE_FATAL:
case LOG_TYPE_PANIC:
break;
case LOG_TYPE_COUNT:
case LOG_TYPE_OPTION:
i_unreached();
}
}
{
}
{
const char *str;
if (*fd != STDERR_FILENO) {
}
}
*fd = STDERR_FILENO;
else {
if (*fd == -1) {
*fd = STDERR_FILENO;
path);
else
}
}
}
{
if (close(log_info_fd) < 0)
}
log_debug_fd != log_fd) {
if (close(log_debug_fd) < 0)
}
/* if info/debug logs are elsewhere, i_set_info/debug_file()
overrides these later. */
}
{
const char *str;
return;
}
void i_set_failure_prefix(const char *prefix_fmt, ...)
{
}
void i_unset_failure_prefix(void)
{
}
const char *i_get_failure_prefix(void)
{
}
{
return -1;
pos += max_text_len;
}
return 0;
}
static int ATTR_FORMAT(2, 0)
{
static int recursed = 0;
int ret;
if (recursed >= 2) {
/* we're being called from some signal handler or we ran
out of memory */
return -1;
}
recursed++;
T_BEGIN {
}
} else {
}
} T_END;
if (ret < 0 && failure_ignore_errors)
ret = 0;
recursed--;
return ret;
}
static bool line_is_ok(const char *line)
{
if (*line != 1)
return FALSE;
i_warning("Broken log line follows (type=NUL)");
return FALSE;
}
return FALSE;
}
return TRUE;
}
{
if (!line_is_ok(line)) {
return;
}
line += 2;
line++;
}
if (*line != ' ') {
/* some old protocol? */
return;
}
}
{
status == FATAL_DEFAULT)
}
static void
{
}
void i_set_failure_internal(void)
{
}
void i_set_failure_ignore_errors(bool ignore)
{
}
void i_set_info_file(const char *path)
{
if (log_info_fd == log_fd)
/* write debug-level messages to the info_log_path,
until i_set_debug_file() was called */
}
void i_set_debug_file(const char *path)
{
}
void i_set_failure_timestamp_format(const char *fmt)
{
const char *p;
if (p == NULL)
else {
}
}
{
}
void i_set_failure_send_prefix(const char *prefix)
{
}
{
}
void failures_deinit(void)
{
if (log_info_fd == log_fd)
if (log_fd != STDERR_FILENO) {
i_close_fd(&log_fd);
}
if (log_info_fd != STDERR_FILENO) {
}
if (log_debug_fd != STDERR_FILENO) {
}
}