failures.c revision b461f35f91cb6ecdb673092cc30406360d528d8b
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "str.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include "write-full.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "fd-close-on-exec.h"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#include "printf-upper-bound.h"
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include <stdio.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include <stdlib.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include <syslog.h>
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include <time.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void default_panic_handler(const char *format, va_list args)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen __attr_noreturn__;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen __attr_noreturn__;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void default_error_handler(const char *format, va_list args);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void default_warning_handler(const char *format, va_list args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void default_info_handler(const char *format, va_list args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen/* Initialize working defaults */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic failure_callback_t *panic_handler __attr_noreturn__ =
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen default_panic_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic fatal_failure_callback_t *fatal_handler __attr_noreturn__ =
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen default_fatal_handler;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenstatic failure_callback_t *error_handler = default_error_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic failure_callback_t *warning_handler = default_warning_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic failure_callback_t *info_handler = default_info_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic FILE *log_fd = NULL, *log_info_fd = NULL;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic char *log_prefix = NULL, *log_stamp_format = NULL;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic const char *get_log_stamp_format(const char *unused)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen __attr_format_arg__(1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenstatic const char *get_log_stamp_format(const char *unused __attr_unused__)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return log_stamp_format;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic void write_prefix(FILE *f)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct tm *tm;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen char str[256];
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen time_t now;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (log_prefix != NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fputs(log_prefix, f);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (log_stamp_format != NULL) {
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen now = time(NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen tm = localtime(&now);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strftime(str, sizeof(str),
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen get_log_stamp_format("unused"), tm) > 0)
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen fputs(str, f);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen }
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainenstatic int default_handler(const char *prefix, FILE *f,
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen const char *format, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen static int recursed = 0;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen va_list args2;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen int old_errno = errno;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen if (recursed == 2) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we're being called from some signal handler, or
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen printf_string_upper_bound() killed us again */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen recursed++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (f == NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen f = stderr;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen if (log_fd == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen log_fd = stderr;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen }
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen VA_COPY(args2, args);
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen t_push();
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (recursed == 2) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* printf_string_upper_bound() probably killed us last time,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen just write the format now. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fputs("recursed: ", f);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fputs(format, f);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen write_prefix(f);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fputs(prefix, f);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* make sure there's no %n in there and fix %m */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)printf_string_upper_bound(&format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen vfprintf(f, format, args2);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen fputc('\n', f);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen t_pop();
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen errno = old_errno;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen recursed--;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenstatic void default_panic_handler(const char *format, va_list args)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen{
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen (void)default_handler("Panic: ", log_fd, format, args);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen abort();
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (default_handler("Fatal: ", log_fd, format, args) < 0 &&
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen status == FATAL_DEFAULT)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen status = FATAL_LOGERROR;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen status = FATAL_LOGWRITE;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen exit(status);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void default_error_handler(const char *format, va_list args)
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen int old_errno = errno;
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (default_handler("Error: ", log_fd, format, args) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen exit(FATAL_LOGERROR);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fflush(log_fd) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen exit(FATAL_LOGWRITE);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen errno = old_errno;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenstatic void default_warning_handler(const char *format, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen int old_errno = errno;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)default_handler("Warning: ", log_fd, format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (fflush(log_fd) < 0)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen exit(FATAL_LOGWRITE);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen errno = old_errno;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void default_info_handler(const char *format, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen int old_errno = errno;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen (void)default_handler("Info: ", log_info_fd, format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (fflush(log_info_fd) < 0)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen exit(FATAL_LOGWRITE);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen errno = old_errno;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid i_panic(const char *format, ...)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_list args;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_start(args, format);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen panic_handler(format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_end(args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid i_fatal(const char *format, ...)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen va_list args;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen va_start(args, format);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen fatal_handler(FATAL_DEFAULT, format, args);
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainen va_end(args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenvoid i_fatal_status(int status, const char *format, ...)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen va_list args;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen va_start(args, format);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen fatal_handler(status, format, args);
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen va_end(args);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenvoid i_error(const char *format, ...)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen va_list args;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen va_start(args, format);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen error_handler(format, args);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen va_end(args);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen}
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainenvoid i_warning(const char *format, ...)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_list args;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen va_start(args, format);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen warning_handler(format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_end(args);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainenvoid i_info(const char *format, ...)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_list args;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_start(args, format);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen info_handler(format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen va_end(args);
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid i_set_panic_handler(failure_callback_t *callback __attr_noreturn__)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen if (callback == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen callback = default_panic_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen panic_handler = callback;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainenvoid i_set_fatal_handler(fatal_failure_callback_t *callback __attr_noreturn__)
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen if (callback == NULL)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen callback = default_fatal_handler;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen fatal_handler = callback;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid i_set_error_handler(failure_callback_t *callback)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (callback == NULL)
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen callback = default_error_handler;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen error_handler = callback;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenvoid i_set_warning_handler(failure_callback_t *callback)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (callback == NULL)
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen callback = default_warning_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen warning_handler = callback;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainenvoid i_set_info_handler(failure_callback_t *callback)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (callback == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen callback = default_info_handler;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen info_handler = callback;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainenstatic int syslog_handler(int level, const char *format, va_list args)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen va_list args2;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen static int recursed = 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (recursed != 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen recursed++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen /* make sure there's no %n in there */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen VA_COPY(args2, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)printf_string_upper_bound(&format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen vsyslog(level, format, args2);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen recursed--;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return 0;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenvoid i_syslog_panic_handler(const char *fmt, va_list args)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen (void)syslog_handler(LOG_CRIT, fmt, args);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen abort();
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid i_syslog_fatal_handler(int status, const char *fmt, va_list args)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (syslog_handler(LOG_CRIT, fmt, args) < 0 && status == FATAL_DEFAULT)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen status = FATAL_LOGERROR;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen exit(status);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid i_syslog_error_handler(const char *fmt, va_list args)
fd14806f879f6cd4f023750e0c4cac27a7f94fbbTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (syslog_handler(LOG_ERR, fmt, args) < 0)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen exit(FATAL_LOGERROR);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid i_syslog_warning_handler(const char *fmt, va_list args)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen (void)syslog_handler(LOG_WARNING, fmt, args);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid i_syslog_info_handler(const char *fmt, va_list args)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen (void)syslog_handler(LOG_INFO, fmt, args);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen}
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainenvoid i_set_failure_syslog(const char *ident, int options, int facility)
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen openlog(ident, options, facility);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen i_set_panic_handler(i_syslog_panic_handler);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen i_set_fatal_handler(i_syslog_fatal_handler);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen i_set_error_handler(i_syslog_error_handler);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen i_set_warning_handler(i_syslog_warning_handler);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen i_set_info_handler(i_syslog_info_handler);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenstatic void open_log_file(FILE **file, const char *path)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (*file != NULL && *file != stderr)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen (void)fclose(*file);
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (path == NULL || strcmp(path, "/dev/stderr") == 0)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen *file = stderr;
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen else {
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen *file = fopen(path, "a");
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen if (*file == NULL) {
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen i_fatal_status(FATAL_LOGOPEN,
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen "Can't open log file %s: %m", path);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen }
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen fd_close_on_exec(fileno(*file), TRUE);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen }
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenvoid i_set_failure_file(const char *path, const char *prefix)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_free(log_prefix);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen log_prefix = i_strconcat(prefix, ": ", NULL);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen if (log_info_fd != NULL && log_info_fd != log_fd &&
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen log_info_fd != stderr)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen (void)fclose(log_info_fd);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen open_log_file(&log_fd, path);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen log_info_fd = log_fd;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_panic_handler(NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_fatal_handler(NULL);
a7061727e8f1378228f110b23d816329d39ce82bTimo Sirainen i_set_error_handler(NULL);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_set_warning_handler(NULL);
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen}
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenstatic int internal_handler(char log_type, const char *format, va_list args)
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen{
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen string_t *str;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen int ret;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen t_push();
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen str = t_str_new(512);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen str_append_c(str, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen str_append_c(str, log_type);
a7061727e8f1378228f110b23d816329d39ce82bTimo Sirainen str_vprintfa(str, format, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen str_append_c(str, '\n');
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ret = write_full(2, str_data(str), str_len(str));
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen t_pop();
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return ret;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen __attr_noreturn__;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen (void)internal_handler('F', fmt, args);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen abort();
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen __attr_noreturn__;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen if (internal_handler('F', fmt, args) < 0 && status == FATAL_DEFAULT)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen status = FATAL_LOGERROR;
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen exit(status);
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen}
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainenstatic void i_internal_error_handler(const char *fmt, va_list args)
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen{
083c67ac280fb4930a280ce1f76fb27a1637e818Timo Sirainen if (internal_handler('E', fmt, args) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen exit(FATAL_LOGERROR);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_warning_handler(const char *fmt, va_list args)
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen (void)internal_handler('W', fmt, args);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void i_internal_info_handler(const char *fmt, va_list args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen (void)internal_handler('I', fmt, args);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid i_set_failure_internal(void)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_panic_handler(i_internal_panic_handler);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_fatal_handler(i_internal_fatal_handler);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_error_handler(i_internal_error_handler);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen i_set_warning_handler(i_internal_warning_handler);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_set_info_handler(i_internal_info_handler);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid i_set_info_file(const char *path)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (log_info_fd == log_fd)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen log_info_fd = NULL;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen open_log_file(&log_info_fd, path);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen info_handler = default_info_handler;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen}
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenvoid i_set_failure_timestamp_format(const char *fmt)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen i_free(log_stamp_format);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen log_stamp_format = i_strdup(fmt);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen}
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenvoid failures_deinit(void)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen{
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen if (log_info_fd == log_fd)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen log_info_fd = NULL;
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (log_fd != NULL && log_fd != stderr) {
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen (void)fclose(log_fd);
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen log_fd = stderr;
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen }
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen if (log_info_fd != NULL && log_info_fd != stderr) {
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen (void)fclose(log_info_fd);
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen log_info_fd = stderr;
a0475b241a56220714d96a41f11a174c11a48bfaTimo Sirainen }
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen i_free_and_null(log_prefix);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_free_and_null(log_stamp_format);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen