failures.c revision 647d32fa263de5e03a7a38898777fb49b5774762
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter/* Copyright (c) 2002-2003 Timo Sirainen */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "lib.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "str.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "write-full.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "fd-close-on-exec.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include "printf-upper-bound.h"
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <stdio.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <stdlib.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <syslog.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#include <time.h>
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_panic_handler(const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter __attr_noreturn__;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_fatal_handler(int status, const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter __attr_noreturn__;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_error_handler(const char *format, va_list args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_warning_handler(const char *format, va_list args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_info_handler(const char *format, va_list args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter/* Initialize working defaults */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic failure_callback_t *panic_handler __attr_noreturn__ =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter default_panic_handler;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic fatal_failure_callback_t *fatal_handler __attr_noreturn__ =
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter default_fatal_handler;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic failure_callback_t *error_handler = default_error_handler;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic failure_callback_t *warning_handler = default_warning_handler;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic failure_callback_t *info_handler = default_info_handler;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walterstatic FILE *log_fd = NULL, *log_info_fd = NULL;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic char *log_prefix = NULL, *log_stamp_format = NULL;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic const char *get_log_stamp_format(const char *unused)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek __attr_format_arg__(1);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnikstatic const char *get_log_stamp_format(const char *unused __attr_unused__)
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik{
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik return log_stamp_format;
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik}
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnikstatic void write_prefix(FILE *f)
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik{
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik struct tm *tm;
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik char str[256];
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik time_t now;
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik if (log_prefix != NULL)
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik fputs(log_prefix, f);
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik
1a94716209e40a9ccaedc7e70f9de961d1cced48Lukas Slebodnik if (log_stamp_format != NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter now = time(NULL);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter tm = localtime(&now);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (strftime(str, sizeof(str),
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter get_log_stamp_format("unused"), tm) > 0)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fputs(str, f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic int default_handler(const char *prefix, FILE *f,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter static int recursed = 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter va_list args2;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter int old_errno = errno;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (recursed == 2) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* we're being called from some signal handler, or
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter printf_string_upper_bound() killed us again */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter recursed++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (f == NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter f = stderr;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (log_fd == NULL)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter log_fd = stderr;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter VA_COPY(args2, args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter t_push();
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (recursed == 2) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* printf_string_upper_bound() probably killed us last time,
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter just write the format now. */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fputs("recursed: ", f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fputs(format, f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter } else {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter write_prefix(f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fputs(prefix, f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter /* make sure there's no %n in there and fix %m */
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter (void)printf_string_upper_bound(&format, args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter vfprintf(f, format, args2);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fputc('\n', f);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter t_pop();
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter errno = old_errno;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter recursed--;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return 0;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_panic_handler(const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter (void)default_handler("Panic: ", log_fd, format, args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter abort();
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_fatal_handler(int status, const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (default_handler("Fatal: ", log_fd, format, args) < 0 &&
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter status == FATAL_DEFAULT)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter status = FATAL_LOGERROR;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter status = FATAL_LOGWRITE;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter exit(status);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walterstatic void default_error_handler(const char *format, va_list args)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter int old_errno = errno;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (default_handler("Error: ", log_fd, format, args) < 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter exit(FATAL_LOGERROR);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter if (fflush(log_fd) < 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter exit(FATAL_LOGWRITE);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter errno = old_errno;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic void default_warning_handler(const char *format, va_list args)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int old_errno = errno;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter (void)default_handler("Warning: ", log_fd, format, args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (fflush(log_fd) < 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter exit(FATAL_LOGWRITE);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter errno = old_errno;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walterstatic void default_info_handler(const char *format, va_list args)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter int old_errno = errno;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter (void)default_handler("Info: ", log_info_fd, format, args);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter if (fflush(log_info_fd) < 0)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter exit(FATAL_LOGWRITE);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter errno = old_errno;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter}
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Waltervoid i_panic(const char *format, ...)
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter{
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter va_list args;
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_start(args, format);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter panic_handler(format, args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_end(args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter}
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Waltervoid i_fatal(const char *format, ...)
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter{
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_list args;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter va_start(args, format);
c3c6eb141d6a288b3da20ad6a2e5718844b2d4adPavel Reichl fatal_handler(FATAL_DEFAULT, format, args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_end(args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter}
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Waltervoid i_fatal_status(int status, const char *format, ...)
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter{
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_list args;
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_start(args, format);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter fatal_handler(status, format, args);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter va_end(args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter}
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Waltervoid i_error(const char *format, ...)
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter{
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter va_list args;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter va_start(args, format);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter error_handler(format, args);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter va_end(args);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter}
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Waltervoid i_warning(const char *format, ...)
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter{
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter va_list args;
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter va_start(args, format);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter warning_handler(format, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter va_end(args);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Waltervoid i_info(const char *format, ...)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter va_list args;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter va_start(args, format);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter info_handler(format, args);
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter va_end(args);
c2cc119de8eac712c040b3993f41c967ff2278deStef Walter}
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_panic_handler(failure_callback_t *callback __attr_noreturn__)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (callback == NULL)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter callback = default_panic_handler;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter panic_handler = callback;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_fatal_handler(fatal_failure_callback_t *callback __attr_noreturn__)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (callback == NULL)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter callback = default_fatal_handler;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter fatal_handler = callback;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_error_handler(failure_callback_t *callback)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (callback == NULL)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter callback = default_error_handler;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter error_handler = callback;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_warning_handler(failure_callback_t *callback)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (callback == NULL)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter callback = default_warning_handler;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter warning_handler = callback;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_info_handler(failure_callback_t *callback)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (callback == NULL)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter callback = default_info_handler;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter info_handler = callback;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walterstatic int syslog_handler(int level, const char *format, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter va_list args2;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter static int recursed = 0;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (recursed != 0)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter return -1;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter recursed++;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter /* make sure there's no %n in there */
1203e462650f035b0df2304075d60b9a99e36715Stef Walter VA_COPY(args2, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter (void)printf_string_upper_bound(&format, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter vsyslog(level, format, args2);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter recursed--;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter return 0;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_syslog_panic_handler(const char *fmt, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter (void)syslog_handler(LOG_CRIT, fmt, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter abort();
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_syslog_fatal_handler(int status, const char *fmt, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (syslog_handler(LOG_CRIT, fmt, args) < 0 && status == FATAL_DEFAULT)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter status = FATAL_LOGERROR;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter exit(status);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_syslog_error_handler(const char *fmt, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (syslog_handler(LOG_ERR, fmt, args) < 0)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter exit(FATAL_LOGERROR);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_syslog_warning_handler(const char *fmt, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter (void)syslog_handler(LOG_WARNING, fmt, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_syslog_info_handler(const char *fmt, va_list args)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter (void)syslog_handler(LOG_INFO, fmt, args);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_failure_syslog(const char *ident, int options, int facility)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter openlog(ident, options, facility);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_set_panic_handler(i_syslog_panic_handler);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_set_fatal_handler(i_syslog_fatal_handler);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_set_error_handler(i_syslog_error_handler);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_set_warning_handler(i_syslog_warning_handler);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_set_info_handler(i_syslog_info_handler);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walterstatic void open_log_file(FILE **file, const char *path)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (*file != NULL && *file != stderr)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter (void)fclose(*file);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (path == NULL || strcmp(path, "/dev/stderr") == 0)
1203e462650f035b0df2304075d60b9a99e36715Stef Walter *file = stderr;
1203e462650f035b0df2304075d60b9a99e36715Stef Walter else {
1203e462650f035b0df2304075d60b9a99e36715Stef Walter *file = fopen(path, "a");
1203e462650f035b0df2304075d60b9a99e36715Stef Walter if (*file == NULL) {
1203e462650f035b0df2304075d60b9a99e36715Stef Walter i_fatal_status(FATAL_LOGOPEN,
1203e462650f035b0df2304075d60b9a99e36715Stef Walter "Can't open log file %s: %m", path);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter }
1203e462650f035b0df2304075d60b9a99e36715Stef Walter fd_close_on_exec(fileno(*file), TRUE);
1203e462650f035b0df2304075d60b9a99e36715Stef Walter }
1203e462650f035b0df2304075d60b9a99e36715Stef Walter}
1203e462650f035b0df2304075d60b9a99e36715Stef Walter
1203e462650f035b0df2304075d60b9a99e36715Stef Waltervoid i_set_failure_file(const char *path, const char *prefix)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_free(log_prefix);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_prefix = i_strconcat(prefix, ": ", NULL);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek open_log_file(&log_fd, path);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (log_info_fd != NULL && log_info_fd != stderr)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)fclose(log_info_fd);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_info_fd = log_fd;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_panic_handler(NULL);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_fatal_handler(NULL);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_error_handler(NULL);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_warning_handler(NULL);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic int internal_handler(char log_type, const char *format, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek string_t *str;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek int ret;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek t_push();
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str = t_str_new(512);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str_append_c(str, 1);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str_append_c(str, log_type);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str_vprintfa(str, format, args);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek str_append_c(str, '\n');
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek ret = write_full(2, str_data(str), str_len(str));
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek t_pop();
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek return ret;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_panic_handler(const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek __attr_noreturn__;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_panic_handler(const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)internal_handler('F', fmt, args);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek abort();
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek __attr_noreturn__;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (internal_handler('F', fmt, args) < 0 && status == FATAL_DEFAULT)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek status = FATAL_LOGERROR;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek exit(status);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_error_handler(const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (internal_handler('E', fmt, args) < 0)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek exit(FATAL_LOGERROR);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_warning_handler(const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)internal_handler('W', fmt, args);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekstatic void i_internal_info_handler(const char *fmt, va_list args)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)internal_handler('I', fmt, args);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekvoid i_set_failure_internal(void)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_panic_handler(i_internal_panic_handler);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_fatal_handler(i_internal_fatal_handler);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_error_handler(i_internal_error_handler);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_warning_handler(i_internal_warning_handler);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_set_info_handler(i_internal_info_handler);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekvoid i_set_info_file(const char *path)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (log_info_fd == log_fd)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_info_fd = NULL;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek open_log_file(&log_info_fd, path);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek info_handler = default_info_handler;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekvoid i_set_failure_timestamp_format(const char *fmt)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek i_free(log_stamp_format);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_stamp_format = i_strdup(fmt);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek}
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozekvoid failures_deinit(void)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek{
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (log_info_fd == log_fd)
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_info_fd = NULL;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (log_fd != NULL && log_fd != stderr) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)fclose(log_fd);
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek log_fd = stderr;
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek }
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek if (log_info_fd != NULL && log_info_fd != stderr) {
90e04eae7e54ec892a6f239783df94dab5d1ed9aJakub Hrozek (void)fclose(log_info_fd);
58229439447d5617913a5a2e173b78105c694842Pavel Březina log_info_fd = stderr;
58229439447d5617913a5a2e173b78105c694842Pavel Březina }
58229439447d5617913a5a2e173b78105c694842Pavel Březina
58229439447d5617913a5a2e173b78105c694842Pavel Březina i_free(log_prefix);
58229439447d5617913a5a2e173b78105c694842Pavel Březina log_prefix = NULL;
58229439447d5617913a5a2e173b78105c694842Pavel Březina
58229439447d5617913a5a2e173b78105c694842Pavel Březina i_free(log_stamp_format);
5de968e80ade1c02d1907834dcff95e9fc9ad10aJakub Hrozek log_stamp_format = NULL;
5de968e80ade1c02d1907834dcff95e9fc9ad10aJakub Hrozek}
5de968e80ade1c02d1907834dcff95e9fc9ad10aJakub Hrozek