failures.c revision 6a058aa8c986a8fbec5ddd72c141db9df0b64b2d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen#include "str.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "write-full.h"
d6601a0bc4fd60e58bedbddf2481abd82cba76d7Timo Sirainen#include "fd-close-on-exec.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "printf-upper-bound.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdio.h>
abf015c9682f0f723db87a7c97bc284ef814818fTimo Sirainen#include <stdlib.h>
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include <syslog.h>
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include <time.h>
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainenstatic void default_panic_handler(const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_noreturn__ __attr_format__(1, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_noreturn__ __attr_format__(2, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic void default_error_handler(const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_format__(1, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void default_warning_handler(const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_format__(1, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void default_info_handler(const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_format__(1, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Initialize working defaults */
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic failure_callback_t *panic_handler __attr_noreturn__ =
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen default_panic_handler;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic fatal_failure_callback_t *fatal_handler __attr_noreturn__ =
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen default_fatal_handler;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic failure_callback_t *error_handler = default_error_handler;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic failure_callback_t *warning_handler = default_warning_handler;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainenstatic failure_callback_t *info_handler = default_info_handler;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic FILE *log_fd = NULL, *log_info_fd = NULL;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic char *log_prefix = NULL, *log_stamp_format = NULL;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstatic const char *get_log_stamp_format(const char *unused)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen __attr_format_arg__(1);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic const char *get_log_stamp_format(const char *unused __attr_unused__)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return log_stamp_format;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainenstatic void write_prefix(FILE *f)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen struct tm *tm;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen char str[256];
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen time_t now;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (log_prefix != NULL)
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen fputs(log_prefix, f);
49621bf0ef1d55aaaa2dc7d76011cbfeabdcfbe1Timo Sirainen
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen if (log_stamp_format != NULL) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen now = time(NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tm = localtime(&now);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (strftime(str, sizeof(str),
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen get_log_stamp_format("unused"), tm) > 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen fputs(str, f);
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen }
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen}
3482fee0e3733456512ba110780824e6daa7ff9fTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenstatic int default_handler(const char *prefix, FILE *f,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen const char *format, va_list args)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen static int recursed = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_list args2;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen int old_errno = errno;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen if (recursed == 2) {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen /* we're being called from some signal handler, or
b9b841558c5f91db7f5fc71c0ac62aad1bbf6418Timo Sirainen printf_string_upper_bound() killed us again */
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen return -1;
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
1388b590dbd85245b591346f860bc1319953318aTimo Sirainen recursed++;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (f == NULL) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen f = stderr;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch if (log_fd == NULL)
c977ee6ce06cbc0b4668fde1ec34f2f5e1773684Timo Sirainen log_fd = stderr;
c977ee6ce06cbc0b4668fde1ec34f2f5e1773684Timo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen VA_COPY(args2, args);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen t_push();
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen if (recursed == 2) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* printf_string_upper_bound() probably killed us last time,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen just write the format now. */
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen fputs("recursed: ", f);
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen fputs(format, f);
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen } else {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen write_prefix(f);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen fputs(prefix, f);
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* write may have failed, restore errno so %m works. although
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen it probably can't write the error then anyway. */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen errno = old_errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* make sure there's no %n in there and fix %m */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen (void)printf_string_upper_bound(&format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen vfprintf(f, format, args2);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen fputc('\n', f);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen t_pop();
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen errno = old_errno;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen recursed--;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void default_panic_handler(const char *format, va_list args)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen (void)default_handler("Panic: ", log_fd, format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen abort();
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void default_fatal_handler(int status, const char *format, va_list args)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (default_handler("Fatal: ", log_fd, format, args) < 0 &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen status == FATAL_DEFAULT)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen status = FATAL_LOGERROR;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (fflush(log_fd) < 0 && status == FATAL_DEFAULT)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen status = FATAL_LOGWRITE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen exit(status);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void default_error_handler(const char *format, va_list args)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen int old_errno = errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen if (default_handler("Error: ", log_fd, format, args) < 0)
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen exit(FATAL_LOGERROR);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (fflush(log_fd) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit(FATAL_LOGWRITE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen errno = old_errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainenstatic void default_warning_handler(const char *format, va_list args)
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen{
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen int old_errno = errno;
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen (void)default_handler("Warning: ", log_fd, format, args);
7af5f78e9fee296e42430d94ef252ff0333d8024Timo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen if (fflush(log_fd) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit(FATAL_LOGWRITE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen errno = old_errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void default_info_handler(const char *format, va_list args)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen int old_errno = errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen (void)default_handler("Info: ", log_info_fd, format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (fflush(log_info_fd) < 0)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit(FATAL_LOGWRITE);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen errno = old_errno;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainenvoid i_panic(const char *format, ...)
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen{
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen va_list args;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
79fff45046397ba48c8693d5f37a1fd93096987fTimo Sirainen va_start(args, format);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen panic_handler(format, args);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen va_end(args);
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen}
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainen
1f5597beba229acd914e30a6da3c0e62d83b6e8fTimo Sirainenvoid i_fatal(const char *format, ...)
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen{
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen va_list args;
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen va_start(args, format);
47569a4b2b4d3cc55e786177798c922c3c44233dTimo Sirainen fatal_handler(FATAL_DEFAULT, format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen va_end(args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainenvoid i_fatal_status(int status, const char *format, ...)
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen{
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen va_list args;
417642ddac19708bea6dd2c2bbeaf6a9578d521bTimo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen va_start(args, format);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen fatal_handler(status, format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen va_end(args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenvoid i_error(const char *format, ...)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_list args;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_start(args, format);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen error_handler(format, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_end(args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_warning(const char *format, ...)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_list args;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_start(args, format);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen warning_handler(format, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_end(args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_info(const char *format, ...)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_list args;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen va_start(args, format);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen info_handler(format, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen va_end(args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid i_set_panic_handler(failure_callback_t *callback __attr_noreturn__)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (callback == NULL)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen callback = default_panic_handler;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen panic_handler = callback;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_set_fatal_handler(fatal_failure_callback_t *callback __attr_noreturn__)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (callback == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen callback = default_fatal_handler;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen fatal_handler = callback;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenvoid i_set_error_handler(failure_callback_t *callback)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen if (callback == NULL)
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen callback = default_error_handler;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen error_handler = callback;
f3e17726502b6cf1912f30aae7e283b5d31ea69cTimo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainenvoid i_set_warning_handler(failure_callback_t *callback)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen{
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (callback == NULL)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen callback = default_warning_handler;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen warning_handler = callback;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen}
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainenvoid i_set_info_handler(failure_callback_t *callback)
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen{
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen if (callback == NULL)
e30b9e07f9657c35ca09ac36d57d60cbe2ebbc66Timo Sirainen callback = default_info_handler;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen info_handler = callback;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen}
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int syslog_handler(int level, const char *format, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen va_list args2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen static int recursed = 0;
002179a890bf4f1942cad6463787719eaa9fd6c0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (recursed != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch
e438c85a6b0f77889e25913bbbba808d6078282dStephan Bosch recursed++;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen /* make sure there's no %n in there */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen VA_COPY(args2, args);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen (void)printf_string_upper_bound(&format, args);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen vsyslog(level, format, args2);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen recursed--;
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch return 0;
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch}
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Boschvoid i_syslog_panic_handler(const char *fmt, va_list args)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch{
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen (void)syslog_handler(LOG_CRIT, fmt, args);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen abort();
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen}
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschvoid i_syslog_fatal_handler(int status, const char *fmt, va_list args)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch{
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen if (syslog_handler(LOG_CRIT, fmt, args) < 0 && status == FATAL_DEFAULT)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen status = FATAL_LOGERROR;
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen exit(status);
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen}
5a9912dcadfd467c5ea54bdc3331eef359f0b1c5Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid i_syslog_error_handler(const char *fmt, va_list args)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen if (syslog_handler(LOG_ERR, fmt, args) < 0)
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen exit(FATAL_LOGERROR);
4c261fb48e6e36570a0841aa51ca483024d6a0a6Timo Sirainen}
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_syslog_warning_handler(const char *fmt, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (void)syslog_handler(LOG_WARNING, fmt, args);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_syslog_info_handler(const char *fmt, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (void)syslog_handler(LOG_INFO, fmt, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainenvoid i_set_failure_syslog(const char *ident, int options, int facility)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen openlog(ident, options, facility);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_panic_handler(i_syslog_panic_handler);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen i_set_fatal_handler(i_syslog_fatal_handler);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_set_error_handler(i_syslog_error_handler);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_warning_handler(i_syslog_warning_handler);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_info_handler(i_syslog_info_handler);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen}
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainen
b9dc21a94401638c00e40b695998875e1563ce77Timo Sirainenstatic void open_log_file(FILE **file, const char *path)
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen{
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen if (*file != NULL && *file != stderr)
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen (void)fclose(*file);
27ca6cb0548c6478005c77d04be641356ec7d83cTimo Sirainen
11120acd01d43973cd504952d691a2ae1c546ee2Timo Sirainen if (path == NULL || strcmp(path, "/dev/stderr") == 0)
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen *file = stderr;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen else {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen *file = fopen(path, "a");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (*file == NULL) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_fatal_status(FATAL_LOGOPEN,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "Can't open log file %s: %m", path);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen fd_close_on_exec(fileno(*file), TRUE);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenvoid i_set_failure_file(const char *path, const char *prefix)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen i_free(log_prefix);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen log_prefix = i_strconcat(prefix, ": ", NULL);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (log_info_fd != NULL && log_info_fd != log_fd &&
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen log_info_fd != stderr)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (void)fclose(log_info_fd);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen open_log_file(&log_fd, path);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen log_info_fd = log_fd;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen i_set_panic_handler(NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_fatal_handler(NULL);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_set_error_handler(NULL);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_set_warning_handler(NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic int internal_handler(char log_type, const char *format, va_list args)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen string_t *str;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen int ret;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen t_push();
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen str = t_str_new(512);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen str_append_c(str, 1);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen str_append_c(str, log_type);
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen str_vprintfa(str, format, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append_c(str, '\n');
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = write_full(2, str_data(str), str_len(str));
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen t_pop();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen __attr_noreturn__;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic void i_internal_panic_handler(const char *fmt, va_list args)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen (void)internal_handler('F', fmt, args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen abort();
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen __attr_noreturn__;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainenstatic void i_internal_fatal_handler(int status, const char *fmt, va_list args)
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen{
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen if (internal_handler('F', fmt, args) < 0 && status == FATAL_DEFAULT)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen status = FATAL_LOGERROR;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen exit(status);
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen}
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainenstatic void i_internal_error_handler(const char *fmt, va_list args)
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen{
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen if (internal_handler('E', fmt, args) < 0)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen exit(FATAL_LOGERROR);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenstatic void i_internal_warning_handler(const char *fmt, va_list args)
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen (void)internal_handler('W', fmt, args);
39f5c2b2143842ff6f827b7198cae8853b8c5bbaTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenstatic void i_internal_info_handler(const char *fmt, va_list args)
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen (void)internal_handler('I', fmt, args);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainenvoid i_set_failure_internal(void)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_set_panic_handler(i_internal_panic_handler);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_set_fatal_handler(i_internal_fatal_handler);
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen i_set_error_handler(i_internal_error_handler);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_set_warning_handler(i_internal_warning_handler);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_set_info_handler(i_internal_info_handler);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenvoid i_set_info_file(const char *path)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (log_info_fd == log_fd)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen log_info_fd = NULL;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen open_log_file(&log_info_fd, path);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen info_handler = default_info_handler;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenvoid i_set_failure_timestamp_format(const char *fmt)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen i_free(log_stamp_format);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen log_stamp_format = i_strdup(fmt);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenvoid failures_deinit(void)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen if (log_info_fd == log_fd)
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen log_info_fd = NULL;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen if (log_fd != NULL && log_fd != stderr) {
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen (void)fclose(log_fd);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen log_fd = stderr;
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen }
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen if (log_info_fd != NULL && log_info_fd != stderr) {
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen (void)fclose(log_info_fd);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen log_info_fd = stderr;
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen i_free_and_null(log_prefix);
19cadcc25c26af7afea1355d78e20ad64eaad263Timo Sirainen i_free_and_null(log_stamp_format);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen}
265cb53cf8d5cb35edd4c4ff086ca6165605b708Timo Sirainen