failures.c revision af208f4a43a81a39a2ec44e68d65d12b95f1b386
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "str.h"
#include "hostpid.h"
#include "network.h"
#include "backtrace-string.h"
#include "printf-format-fix.h"
#include "write-full.h"
#include "fd-close-on-exec.h"
#include <stdlib.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: "
};
/* Initialize working defaults */
static void (*failure_exit_callback)(int *) = NULL;
static bool failure_ignore_errors = FALSE;
static void ATTR_FORMAT(2, 0)
/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
static const char *get_log_stamp_format(const char *unused)
ATTR_FORMAT_ARG(1);
{
return log_stamp_format;
}
void failure_exit(int status)
{
if (failure_exit_callback != NULL)
}
{
char buf[256];
if (log_stamp_format != NULL) {
}
if (log_prefix != NULL)
}
{
}
{
unsigned int eintr_count = 0;
if (ret > 0) {
/* some was written, continue.. */
continue;
}
if (ret == 0) {
/* out of disk space? */
return -1;
}
/* we don't want to die because of this.
try again a couple of times. */
continue;
}
return -1;
/* wait until we can write more. this can happen at least
when writing to terminal, even if fd is blocking. */
ioloop = io_loop_create();
}
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;
if (backtrace_get(&backtrace) == 0)
}
if (type == LOG_TYPE_PANIC)
abort();
else
}
{
}
{
int fd;
switch (type) {
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. */
}
}
{
switch (type) {
case LOG_TYPE_DEBUG:
break;
case LOG_TYPE_INFO:
break;
default:
}
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
static int ATTR_FORMAT(3, 0)
{
static int recursed = 0;
if (recursed >= 2)
return -1;
recursed++;
/* syslogs don't generatelly bother to log the level in any way,
so make sure fatals and panics are shown clearly */
T_BEGIN {
} T_END;
recursed--;
return 0;
}
{
status == FATAL_DEFAULT)
}
{
switch (type) {
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();
}
}
{
}
{
if (*fd != STDERR_FILENO) {
"close(%d) failed: %m", *fd);
}
}
*fd = STDERR_FILENO;
else {
if (*fd == -1) {
*fd = STDERR_FILENO;
"Can't open log file %s: %m\n", 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)
{
}
{
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 {
unsigned int prefix_len;
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)
{
}
{
}
{
}
void failures_deinit(void)
{
if (log_info_fd == log_fd)
if (log_fd != STDERR_FILENO) {
}
if (log_info_fd != STDERR_FILENO) {
(void)close(log_info_fd);
}
if (log_debug_fd != STDERR_FILENO) {
(void)close(log_debug_fd);
}
}