failures.c revision 41062ccab36f31f345e9b9f3198547c4c2096314
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "str.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fd-close-on-exec.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "printf-upper-bound.h"
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdio.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <stdlib.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <syslog.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include <time.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_panic_handler(const char *format, va_list args)
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen __attr_noreturn__;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen __attr_noreturn__;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_error_handler(const char *format, va_list args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_warning_handler(const char *format, va_list args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_info_handler(const char *format, va_list args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Initialize working defaults */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic failure_callback_t *panic_handler __attr_noreturn__ =
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen default_panic_handler;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic fatal_failure_callback_t *fatal_handler __attr_noreturn__ =
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen default_fatal_handler;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic failure_callback_t *error_handler = default_error_handler;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic failure_callback_t *warning_handler = default_warning_handler;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic failure_callback_t *info_handler = default_info_handler;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic FILE *log_fd = NULL, *log_info_fd = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic char *log_prefix = NULL, *log_stamp_format = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic const char *get_log_stamp_format(const char *unused)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen __attr_format_arg__(1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic const char *get_log_stamp_format(const char *unused __attr_unused__)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return log_stamp_format;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void write_prefix(FILE *f)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct tm *tm;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen char str[256];
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen time_t now;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log_prefix != NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputs(log_prefix, f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log_stamp_format != NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen now = time(NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen tm = localtime(&now);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (strftime(str, sizeof(str),
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen get_log_stamp_format("unused"), tm) > 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputs(str, f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int default_handler(const char *prefix, FILE *f,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen static int recursed = 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen va_list args2;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int old_errno = errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (recursed == 2) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* we're being called from some signal handler, or
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen printf_string_upper_bound() killed us again */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return -1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen recursed++;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (f == NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen f = stderr;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (log_fd == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen log_fd = stderr;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen VA_COPY(args2, args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen t_push();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (recursed == 2) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* printf_string_upper_bound() probably killed us last time,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen just write the format now. */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputs("recursed: ", f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputs(format, f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen } else {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen write_prefix(f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputs(prefix, f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* make sure there's no %n in there and fix %m */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)printf_string_upper_bound(&format, args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen vfprintf(f, format, args2);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen fputc('\n', f);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen t_pop();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen errno = old_errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen recursed--;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return 0;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_panic_handler(const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)default_handler("Panic: ", log_fd, format, args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen abort();
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (default_handler("Fatal: ", log_fd, format, args) < 0 &&
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen status == FATAL_DEFAULT)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen status = FATAL_LOGERROR;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen status = FATAL_LOGWRITE;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen exit(status);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_error_handler(const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int old_errno = errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (default_handler("Error: ", log_fd, format, args) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen exit(FATAL_LOGERROR);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fflush(log_fd) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen exit(FATAL_LOGWRITE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen errno = old_errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_warning_handler(const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int old_errno = errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)default_handler("Warning: ", log_fd, format, args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fflush(log_fd) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen exit(FATAL_LOGWRITE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen errno = old_errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void default_info_handler(const char *format, va_list args)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int old_errno = errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)default_handler("Info: ", log_info_fd, format, args);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (fflush(log_info_fd) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen exit(FATAL_LOGWRITE);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen errno = old_errno;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenvoid i_panic(const char *format, ...)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen va_list args;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(args, format);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen panic_handler(format, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(args);
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid i_fatal(const char *format, ...)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen va_list args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(args, format);
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen fatal_handler(FATAL_DEFAULT, format, args);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen va_end(args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenvoid i_fatal_status(int status, const char *format, ...)
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_list args;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(args, format);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fatal_handler(status, format, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainenvoid i_error(const char *format, ...)
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen{
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen va_list args;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen va_start(args, format);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen error_handler(format, args);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen va_end(args);
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen}
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainenvoid i_warning(const char *format, ...)
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen va_list args;
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_start(args, format);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen warning_handler(format, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_end(args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenvoid i_info(const char *format, ...)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen va_list args;
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen va_start(args, format);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen info_handler(format, args);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen va_end(args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9c7e765845357342923e16351181091028e5930fTimo Sirainenvoid i_set_panic_handler(failure_callback_t *callback __attr_noreturn__)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (callback == NULL)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen callback = default_panic_handler;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen panic_handler = callback;
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen}
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainenvoid i_set_fatal_handler(fatal_failure_callback_t *callback __attr_noreturn__)
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen{
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen if (callback == NULL)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen callback = default_fatal_handler;
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainen fatal_handler = callback;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenvoid i_set_error_handler(failure_callback_t *callback)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (callback == NULL)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen callback = default_error_handler;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen error_handler = callback;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainenvoid i_set_warning_handler(failure_callback_t *callback)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen if (callback == NULL)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen callback = default_warning_handler;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen warning_handler = callback;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainenvoid i_set_info_handler(failure_callback_t *callback)
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (callback == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen callback = default_info_handler;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info_handler = callback;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int syslog_handler(int level, const char *format, va_list args)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen va_list args2;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen static int recursed = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (recursed != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen recursed++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e05181d973025627ba08b631c12c07c3bbc99528Timo Sirainen /* make sure there's no %n in there */
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen VA_COPY(args2, args);
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen (void)printf_string_upper_bound(&format, args);
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen
0b3662995e9fa0d0d857ec5350ce2b1ee6d3b94fTimo Sirainen vsyslog(level, format, args2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen recursed--;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen return 0;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainenvoid i_syslog_panic_handler(const char *fmt, va_list args)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen{
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen (void)syslog_handler(LOG_CRIT, fmt, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen abort();
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainenvoid i_syslog_fatal_handler(int status, const char *fmt, va_list args)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (syslog_handler(LOG_CRIT, fmt, args) < 0 && status == FATAL_DEFAULT)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen status = FATAL_LOGERROR;
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen exit(status);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainenvoid i_syslog_error_handler(const char *fmt, va_list args)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (syslog_handler(LOG_ERR, fmt, args) < 0)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen exit(FATAL_LOGERROR);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenvoid i_syslog_warning_handler(const char *fmt, va_list args)
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen{
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen (void)syslog_handler(LOG_WARNING, fmt, args);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenvoid i_syslog_info_handler(const char *fmt, va_list args)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen (void)syslog_handler(LOG_INFO, fmt, args);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenvoid i_set_failure_syslog(const char *ident, int options, int facility)
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen{
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen openlog(ident, options, facility);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_set_panic_handler(i_syslog_panic_handler);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_set_fatal_handler(i_syslog_fatal_handler);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_set_error_handler(i_syslog_error_handler);
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen i_set_warning_handler(i_syslog_warning_handler);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_set_info_handler(i_syslog_info_handler);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen}
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainenstatic void open_log_file(FILE **file, const char *path)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen{
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen if (*file != NULL && *file != stderr)
4b43f50117630aa12b3cfd0cbd05ae22ba27fec1Timo Sirainen (void)fclose(*file);
538303a216166f3526c0ae9658c9978275cfa100Timo Sirainen
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen if (path == NULL || strcmp(path, "/dev/stderr") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *file = stderr;
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen else {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen *file = fopen(path, "a");
a87e5f15283e057c7dc26dd9db7b616268c95ca7Timo Sirainen if (*file == NULL) {
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen i_fatal_status(FATAL_LOGOPEN,
c93cd163f9c1d4b0ca29f49cbfdbf474caeef5bfTimo Sirainen "Can't open log file %s: %m", path);
6925fd9cd70c30884406d50f1d85efb6561e776cTimo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen fd_close_on_exec(fileno(*file), TRUE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid i_set_failure_file(const char *path, const char *prefix)
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen{
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen i_free(log_prefix);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen log_prefix = i_strconcat(prefix, ": ", NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen open_log_file(&log_fd, path);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (log_info_fd != NULL && log_info_fd != stderr)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen (void)fclose(log_info_fd);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen log_info_fd = log_fd;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_set_panic_handler(NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_set_fatal_handler(NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_set_error_handler(NULL);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen i_set_warning_handler(NULL);
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen}
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainenstatic int internal_handler(char log_type, const char *format, va_list args)
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen{
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen string_t *str;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen int ret;
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_str_new(512);
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen str_append_c(str, 1);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen str_append_c(str, log_type);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_vprintfa(str, format, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = write_full(2, str_data(str), str_len(str));
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen t_pop();
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
b60baf6af900a610b2b2ddd24a46f8311acc3386Timo Sirainen return ret;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen __attr_noreturn__;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen{
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen (void)internal_handler('F', fmt, args);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen abort();
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen}
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen __attr_noreturn__;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen{
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen if (internal_handler('F', fmt, args) < 0 && status == FATAL_DEFAULT)
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen status = FATAL_LOGERROR;
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen exit(status);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen}
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void i_internal_error_handler(const char *fmt, va_list args)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (internal_handler('E', fmt, args) < 0)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen exit(FATAL_LOGERROR);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void i_internal_warning_handler(const char *fmt, va_list args)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen (void)internal_handler('W', fmt, args);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenstatic void i_internal_info_handler(const char *fmt, va_list args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)internal_handler('I', fmt, args);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid i_set_failure_internal(void)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_set_panic_handler(i_internal_panic_handler);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_set_fatal_handler(i_internal_fatal_handler);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_set_error_handler(i_internal_error_handler);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_set_warning_handler(i_internal_warning_handler);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen i_set_info_handler(i_internal_info_handler);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainenvoid i_set_info_file(const char *path)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen{
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen if (log_info_fd == log_fd)
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen log_info_fd = NULL;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen open_log_file(&log_info_fd, path);
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen info_handler = default_info_handler;
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid i_set_failure_timestamp_format(const char *fmt)
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen{
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen i_free(log_stamp_format);
d77c309fccbc6a7594f8cb08fb01009fa613c568Timo Sirainen log_stamp_format = i_strdup(fmt);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen}
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainenvoid failures_deinit(void)
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen{
41264e5dcef8335ab7ba422822b3ab518b7a327aTimo Sirainen if (log_info_fd == log_fd)
7bd6001d84ecc1792ddfd54fe8efa63c509d90b1Timo Sirainen log_info_fd = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (log_fd != NULL && log_fd != stderr) {
d3eff05aaa4c2bc0a7580ee87a54f6693f4a8241Timo Sirainen (void)fclose(log_fd);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen log_fd = stderr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (log_info_fd != NULL && log_info_fd != stderr) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)fclose(log_info_fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen log_info_fd = stderr;
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen }
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen
8754bb7a1f24705ffa5434f9e10d57e0b3b88d6eTimo Sirainen i_free_and_null(log_prefix);
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainen i_free_and_null(log_stamp_format);
d67f54632110cfb6aafe2d7cd1f99b031c0b208aTimo Sirainen}
d61a5e0e4ff58d1aa613f0d51161e5bb0f092514Timo Sirainen