failures.c revision 8cd74cad9a59837fe23ef7be7a3a9a783a20d05f
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen/*
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen failures.c : Failure manager
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen Copyright (c) 2001-2002 Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen Permission is hereby granted, free of charge, to any person obtaining
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen a copy of this software and associated documentation files (the
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen "Software"), to deal in the Software without restriction, including
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen without limitation the rights to use, copy, modify, merge, publish,
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen distribute, sublicense, and/or sell copies of the Software, and to
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen permit persons to whom the Software is furnished to do so, subject to
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen the following conditions:
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen The above copyright notice and this permission notice shall be
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen included in all copies or substantial portions of the Software.
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen*/
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include "lib.h"
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include "ioloop.h"
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include <stdio.h>
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include <stdlib.h>
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include <syslog.h>
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen#include <time.h>
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic FailureFunc panic_handler __attr_noreturn__, fatal_handler __attr_noreturn__;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic FailureFunc error_handler, warning_handler;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic FILE *log_fd;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic char *log_prefix, *log_stamp_format;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_panic_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen __attr_noreturn__;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_fatal_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen __attr_noreturn__;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void write_prefix(void)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen struct tm *tm;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen char str[256];
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen if (log_prefix != NULL)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs(log_prefix, log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen if (log_stamp_format != NULL) {
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen tm = localtime(&ioloop_time);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen if (strftime(str, sizeof(str), log_stamp_format, tm) > 0)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs(str, log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen }
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_panic_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen write_prefix();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs("Panic: ", log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen vfprintf(log_fd, printf_string_fix_format(format), args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputc('\n', log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen abort();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_fatal_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen write_prefix();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs("Fatal: ", log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen vfprintf(log_fd, printf_string_fix_format(format), args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputc('\n', log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen exit(98);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_error_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen int old_errno = errno;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen write_prefix();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen t_push();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs("Error: ", log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen vfprintf(log_fd, printf_string_fix_format(format), args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputc('\n', log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen t_pop();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fflush(log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen errno = old_errno;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenstatic void default_warning_handler(const char *format, va_list args)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen int old_errno = errno;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen write_prefix();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen t_push();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputs("Warning: ", log_fd);
ba1a5db879b08d2fefcb42160af67853cdfe7687Timo Sirainen vfprintf(log_fd, printf_string_fix_format(format), args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fputc('\n', log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen t_pop();
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fflush(log_fd);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen errno = old_errno;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenvoid i_panic(const char *format, ...)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_list args;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_start(args, format);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen panic_handler(format, args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_end(args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenvoid i_fatal(const char *format, ...)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_list args;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_start(args, format);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen fatal_handler(format, args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_end(args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenvoid i_error(const char *format, ...)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_list args;
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_start(args, format);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen error_handler(format, args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen va_end(args);
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen}
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainenvoid i_warning(const char *format, ...)
6509aa7306649042e828fef9e2f280f4535ea137Timo Sirainen{
va_list args;
va_start(args, format);
warning_handler(format, args);
va_end(args);
}
void i_set_panic_handler(FailureFunc func __attr_noreturn__)
{
if (func == NULL)
func = default_panic_handler;
panic_handler = func;
}
void i_set_fatal_handler(FailureFunc func __attr_noreturn__)
{
if (func == NULL)
func = default_fatal_handler;
fatal_handler = func;
}
void i_set_error_handler(FailureFunc func)
{
if (func == NULL)
func = default_error_handler;
error_handler = func;
}
void i_set_warning_handler(FailureFunc func)
{
if (func == NULL)
func = default_warning_handler;
warning_handler = func;
}
void i_syslog_panic_handler(const char *fmt, va_list args)
{
vsyslog(LOG_CRIT, fmt, args);
abort();
}
void i_syslog_fatal_handler(const char *fmt, va_list args)
{
vsyslog(LOG_CRIT, fmt, args);
exit(98);
}
void i_syslog_error_handler(const char *fmt, va_list args)
{
vsyslog(LOG_ERR, fmt, args);
}
void i_syslog_warning_handler(const char *fmt, va_list args)
{
vsyslog(LOG_WARNING, fmt, args);
}
void i_set_failure_file(const char *path, const char *prefix)
{
if (log_fd != stderr)
(void)fclose(log_fd);
log_fd = fopen(path, "a");
if (log_fd == NULL)
i_fatal("Can't open log file %s: %m", path);
i_free(log_prefix);
log_prefix = i_strconcat(prefix, ": ", NULL);
}
void i_set_failure_timestamp_format(const char *fmt)
{
i_free(log_stamp_format);
log_stamp_format = i_strdup(fmt);
}
void failures_init(void)
{
log_fd = stderr;
log_prefix = NULL;
log_stamp_format = NULL;
i_set_panic_handler(NULL);
i_set_fatal_handler(NULL);
i_set_error_handler(NULL);
i_set_warning_handler(NULL);
}
void failures_deinit(void)
{
if (log_fd != stderr) {
(void)fclose(log_fd);
log_fd = stderr;
}
}