failures.c revision 81333312b6be6cdf054959f519544fddfe350a6e
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "ioloop.h"
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen#include "str.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "hostpid.h"
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen#include "network.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "backtrace-string.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "printf-format-fix.h"
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen#include "write-full.h"
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen#include "fd-close-on-exec.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdlib.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <unistd.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <fcntl.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <syslog.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <time.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenconst char *failure_log_type_prefixes[LOG_TYPE_COUNT] = {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Debug: ",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Info: ",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Warning: ",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Error: ",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Fatal: ",
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen "Panic: "
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen};
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen/* Initialize working defaults */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic fatal_failure_callback_t *fatal_handler ATTR_NORETURN =
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen default_fatal_handler;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic failure_callback_t *error_handler = default_error_handler;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic failure_callback_t *info_handler = default_error_handler;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic failure_callback_t *debug_handler = default_error_handler;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void (*failure_exit_callback)(int *) = NULL;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic int log_fd = STDERR_FILENO, log_info_fd = STDERR_FILENO,
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen log_debug_fd = STDERR_FILENO;
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstatic char *log_prefix = NULL, *log_stamp_format = NULL;
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipekstatic bool failure_ignore_errors = FALSE;
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipekstatic void ATTR_FORMAT(2, 0)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Siraineni_internal_error_handler(enum log_type type, const char *fmt, va_list args);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstatic const char *get_log_stamp_format(const char *unused)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen ATTR_FORMAT_ARG(1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic const char *get_log_stamp_format(const char *unused ATTR_UNUSED)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return log_stamp_format;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipekvoid failure_exit(int status)
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek{
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek if (failure_exit_callback != NULL)
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek failure_exit_callback(&status);
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek exit(status);
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenstatic void log_prefix_add(string_t *str)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct tm *tm;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen char buf[256];
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen time_t now;
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek if (log_stamp_format != NULL) {
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen now = time(NULL);
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen tm = localtime(&now);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (strftime(buf, sizeof(buf),
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen get_log_stamp_format("unused"), tm) > 0)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen str_append(str, buf);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen }
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (log_prefix != NULL)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen str_append(str, log_prefix);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen}
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainenstatic void log_fd_flush_stop(struct ioloop *ioloop)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen{
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen io_loop_stop(ioloop);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen}
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainenstatic int log_fd_write(int fd, const unsigned char *data, unsigned int len)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen{
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen struct ioloop *ioloop;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen struct io *io;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int eintr_count = 0;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen while ((ret = write(fd, data, len)) != (ssize_t)len) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret > 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* some was written, continue.. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen data += ret;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen len -= ret;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen continue;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen }
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (ret == 0) {
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen /* out of disk space? */
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen errno = ENOSPC;
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen return -1;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen }
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen if (errno == EINTR && ++eintr_count < 3) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* we don't want to die because of this.
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen try again a couple of times. */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen continue;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen }
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (errno != EAGAIN)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return -1;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* wait until we can write more. this can happen at least
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen when writing to terminal, even if fd is blocking. */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen ioloop = io_loop_create();
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen io = io_add(fd, IO_WRITE, log_fd_flush_stop, ioloop);
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen io_loop_run(ioloop);
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen io_remove(&io);
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen io_loop_destroy(&ioloop);
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen }
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen return 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
660ecbaf80e6b3cf3a70ed1e0cdf7f8af6d895d0Josef 'Jeff' Sipek
660ecbaf80e6b3cf3a70ed1e0cdf7f8af6d895d0Josef 'Jeff' Sipekstatic int ATTR_FORMAT(3, 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainendefault_handler(const char *prefix, int fd, const char *format, va_list args)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen static int recursed = 0;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen int ret;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (recursed >= 2) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen /* we're being called from some signal handler or we ran
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen out of memory */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen recursed++;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen T_BEGIN {
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen string_t *str = t_str_new(256);
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen log_prefix_add(str);
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen str_append(str, prefix);
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen /* make sure there's no %n in there and fix %m */
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen str_vprintfa(str, printf_format_fix(format), args);
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen str_append_c(str, '\n');
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen ret = log_fd_write(fd, str_data(str), str_len(str));
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen } T_END;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (ret < 0 && failure_ignore_errors)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen ret = 0;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen recursed--;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return ret;
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen}
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainenstatic void ATTR_NORETURN
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainendefault_fatal_finish(enum log_type type, int status)
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen{
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen const char *backtrace;
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen if (type == LOG_TYPE_PANIC || status == FATAL_OUTOFMEM) {
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen if (backtrace_get(&backtrace) == 0)
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen i_error("Raw backtrace: %s", backtrace);
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen }
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen if (type == LOG_TYPE_PANIC)
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen abort();
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen else
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen failure_exit(status);
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen}
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainenvoid default_fatal_handler(enum log_type type, int status,
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen const char *format, va_list args)
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen{
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen if (default_handler(failure_log_type_prefixes[type], log_fd, format,
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen args) < 0 && status == FATAL_DEFAULT)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen status = FATAL_LOGWRITE;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen default_fatal_finish(type, status);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenvoid default_error_handler(enum log_type type, const char *format, va_list args)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen int fd;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen switch (type) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen case LOG_TYPE_DEBUG:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd = log_debug_fd;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen break;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen case LOG_TYPE_INFO:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd = log_info_fd;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen break;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen default:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd = log_fd;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen }
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen if (default_handler(failure_log_type_prefixes[type],
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd, format, args) < 0) {
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen if (fd == log_fd)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen failure_exit(FATAL_LOGWRITE);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* we failed to log to info/debug log, try to log the
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen write error to error log - maybe that'll work. */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_fatal_status(FATAL_LOGWRITE, "write() failed to %s log: %m",
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fd == log_info_fd ? "info" : "debug");
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen }
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen}
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenvoid i_log_type(enum log_type type, const char *format, ...)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen{
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_list args;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_start(args, format);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen switch (type) {
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen case LOG_TYPE_DEBUG:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen debug_handler(type, format, args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen break;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen case LOG_TYPE_INFO:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen info_handler(type, format, args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen break;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen default:
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen error_handler(type, format, args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen }
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_end(args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen}
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenvoid i_panic(const char *format, ...)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen{
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_list args;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_start(args, format);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen fatal_handler(LOG_TYPE_PANIC, 0, format, args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_end(args);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen}
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenvoid i_fatal(const char *format, ...)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen{
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen va_list args;
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen va_start(args, format);
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen fatal_handler(LOG_TYPE_FATAL, FATAL_DEFAULT, format, args);
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen va_end(args);
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen}
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainenvoid i_fatal_status(int status, const char *format, ...)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen{
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_list args;
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_start(args, format);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen fatal_handler(LOG_TYPE_FATAL, status, format, args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_end(args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen}
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainenvoid i_error(const char *format, ...)
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen{
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen int old_errno = errno;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_list args;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_start(args, format);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen error_handler(LOG_TYPE_ERROR, format, args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_end(args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen errno = old_errno;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen}
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainenvoid i_warning(const char *format, ...)
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen{
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen int old_errno = errno;
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_list args;
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_start(args, format);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen error_handler(LOG_TYPE_WARNING, format, args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_end(args);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen errno = old_errno;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen}
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainenvoid i_info(const char *format, ...)
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen{
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen int old_errno = errno;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen va_list args;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_start(args, format);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen info_handler(LOG_TYPE_INFO, format, args);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen va_end(args);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen errno = old_errno;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen}
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenvoid i_debug(const char *format, ...)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
a2738cdb6d2733fb3e186331d68009421a19ea00Timo Sirainen int old_errno = errno;
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen va_list args;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen va_start(args, format);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen debug_handler(LOG_TYPE_DEBUG, format, args);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen va_end(args);
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen errno = old_errno;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenvoid i_set_fatal_handler(fatal_failure_callback_t *callback ATTR_NORETURN)
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen{
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (callback == NULL)
7af4788b402346c94496095dd819f95ce03fe431Timo Sirainen callback = default_fatal_handler;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen fatal_handler = callback;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen}
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainenvoid i_set_error_handler(failure_callback_t *callback)
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen{
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (callback == NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen callback = default_error_handler;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen error_handler = callback;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen}
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenvoid i_set_info_handler(failure_callback_t *callback)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen{
c24ef531ca58abad996482f5c2e8992be9ae8981Timo Sirainen if (callback == NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen callback = default_error_handler;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen info_handler = callback;
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen}
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainenvoid i_set_debug_handler(failure_callback_t *callback)
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen{
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen if (callback == NULL)
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen callback = default_error_handler;
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen debug_handler = callback;
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen}
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenvoid i_get_failure_handlers(fatal_failure_callback_t **fatal_callback_r,
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen failure_callback_t **error_callback_r,
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen failure_callback_t **info_callback_r,
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen failure_callback_t **debug_callback_r)
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen{
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen *fatal_callback_r = fatal_handler;
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen *error_callback_r = error_handler;
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen *info_callback_r = info_handler;
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen *debug_callback_r = debug_handler;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainenstatic int ATTR_FORMAT(3, 0)
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainensyslog_handler(int level, enum log_type type, const char *format, va_list args)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen static int recursed = 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen if (recursed >= 2)
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen return -1;
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen recursed++;
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen /* syslogs don't generatelly bother to log the level in any way,
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen so make sure errors are shown clearly */
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen T_BEGIN {
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen syslog(level, "%s%s%s",
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen log_prefix == NULL ? "" : log_prefix,
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen type != LOG_TYPE_INFO ?
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen failure_log_type_prefixes[type] : "",
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen t_strdup_vprintf(format, args));
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen } T_END;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen recursed--;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return 0;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid i_syslog_fatal_handler(enum log_type type, int status,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *fmt, va_list args)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (syslog_handler(LOG_CRIT, type, fmt, args) < 0 &&
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen status == FATAL_DEFAULT)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen status = FATAL_LOGERROR;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen default_fatal_finish(type, status);
bcd286622779a93f809b11993db0550f8c7cc9b5Timo Sirainen}
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid i_syslog_error_handler(enum log_type type, const char *fmt, va_list args)
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen int level = LOG_ERR;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen switch (type) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_DEBUG:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen level = LOG_DEBUG;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen break;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_INFO:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen level = LOG_INFO;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen break;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_WARNING:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen level = LOG_WARNING;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen break;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_ERROR:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen level = LOG_ERR;
c6b6ac7819931dfa92c0182ffaa7db07ac6ab0daTimo Sirainen break;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_FATAL:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen case LOG_TYPE_PANIC:
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen level = LOG_CRIT;
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen break;
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen case LOG_TYPE_COUNT:
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen case LOG_TYPE_OPTION:
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen i_unreached();
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen }
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen if (syslog_handler(level, type, fmt, args) < 0)
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen failure_exit(FATAL_LOGERROR);
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen}
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainenvoid i_set_failure_syslog(const char *ident, int options, int facility)
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen{
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen openlog(ident, options, facility);
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_set_fatal_handler(i_syslog_fatal_handler);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_set_error_handler(i_syslog_error_handler);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen i_set_info_handler(i_syslog_error_handler);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_set_debug_handler(i_syslog_error_handler);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainenstatic void open_log_file(int *fd, const char *path)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *str;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen if (*fd != STDERR_FILENO) {
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen if (close(*fd) < 0) {
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen str = t_strdup_printf("close(%d) failed: %m", *fd);
54bd0fec0be357266e299466a582f3c9269884e9Timo Sirainen (void)write_full(STDERR_FILENO, str, strlen(str));
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (path == NULL || strcmp(path, "/dev/stderr") == 0)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen *fd = STDERR_FILENO;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else {
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen *fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0600);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*fd == -1) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *fd = STDERR_FILENO;
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi str = t_strdup_printf("Can't open log file %s: %m\n",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen path);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen (void)write_full(STDERR_FILENO, str, strlen(str));
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (fd == &log_fd)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen failure_exit(FATAL_LOGOPEN);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_fatal_status(FATAL_LOGOPEN, "%s", str);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen fd_close_on_exec(*fd, TRUE);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen }
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenvoid i_set_failure_file(const char *path, const char *prefix)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen i_set_failure_prefix(prefix);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (log_info_fd != STDERR_FILENO && log_info_fd != log_fd) {
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (close(log_info_fd) < 0)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen i_error("close(%d) failed: %m", log_info_fd);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (log_debug_fd != STDERR_FILENO && log_debug_fd != log_info_fd &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen log_debug_fd != log_fd) {
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (close(log_debug_fd) < 0)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_error("close(%d) failed: %m", log_debug_fd);
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi open_log_file(&log_fd, path);
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi /* if info/debug logs are elsewhere, i_set_info/debug_file()
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen overrides these later. */
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi log_info_fd = log_fd;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen log_debug_fd = log_fd;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_set_fatal_handler(NULL);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_set_error_handler(NULL);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen i_set_info_handler(NULL);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen i_set_debug_handler(NULL);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen}
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void i_failure_send_option(const char *key, const char *value)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen{
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi const char *str;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (error_handler != i_internal_error_handler)
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen str = t_strdup_printf("\001%c%s %s=%s\n", LOG_TYPE_OPTION+1,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen my_pid, key, value);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (void)write_full(2, str, strlen(str));
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid i_set_failure_prefix(const char *prefix)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi i_free(log_prefix);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen log_prefix = i_strdup(prefix);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_failure_send_option("prefix", prefix);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen}
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic int internal_send_split(string_t *full_str, unsigned int prefix_len)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen{
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen string_t *str;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen unsigned int max_text_len, pos = prefix_len;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen str = t_str_new(PIPE_BUF);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen str_append_n(str, str_c(full_str), prefix_len);
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi max_text_len = PIPE_BUF - prefix_len - 1;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen while (pos < str_len(full_str)) {
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi str_truncate(str, prefix_len);
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi str_append_n(str, str_c(full_str) + pos, max_text_len);
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen str_append_c(str, '\n');
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi if (log_fd_write(2, str_data(str), str_len(str)) < 0)
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen return -1;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen pos += max_text_len;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen return 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen}
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic int ATTR_FORMAT(2, 0)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Siraineninternal_handler(enum log_type log_type, const char *format, va_list args)
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen static int recursed = 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen int ret;
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi if (recursed >= 2) {
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi /* we're being called from some signal handler or we ran
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi out of memory */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return -1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen recursed++;
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen T_BEGIN {
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen string_t *str;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen unsigned int prefix_len;
1bc075e2e4ed422f9590c95c3ae223422b97ce6aTimo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen str = t_str_new(128);
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen str_printfa(str, "\001%c%s ", log_type + 1, my_pid);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen prefix_len = str_len(str);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen str_vprintfa(str, format, args);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (str_len(str)+1 <= PIPE_BUF) {
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen str_append_c(str, '\n');
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen ret = log_fd_write(2, str_data(str), str_len(str));
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen } else {
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen ret = internal_send_split(str, prefix_len);
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen }
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen } T_END;
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen if (ret < 0 && failure_ignore_errors)
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen ret = 0;
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen recursed--;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenstatic bool line_is_ok(const char *line)
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (*line != 1)
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen return FALSE;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (line[1] == '\0') {
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen i_warning("Broken log line follows (type=NUL)");
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen return FALSE;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e6bc5e739360377c5badf0da24208f4836722eaeStephan Bosch
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (line[1]-1 > LOG_TYPE_OPTION) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_warning("Broken log line follows (type=%d)", line[1]-1);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return FALSE;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return TRUE;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid i_failure_parse_line(const char *line, struct failure_line *failure)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen memset(failure, 0, sizeof(*failure));
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (!line_is_ok(line)) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen failure->log_type = LOG_TYPE_ERROR;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen failure->text = line;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen failure->log_type = line[1] - 1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen line += 2;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen failure->text = line;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen while (*line >= '0' && *line <= '9') {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen failure->pid = failure->pid*10 + (*line - '0');
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen line++;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (*line != ' ') {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* some old protocol? */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen failure->pid = 0;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen }
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen failure->text = line + 1;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void ATTR_NORETURN ATTR_FORMAT(3, 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Siraineni_internal_fatal_handler(enum log_type type, int status,
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen const char *fmt, va_list args)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
7a77b948806106b46a33f3e6a3869657f49877fdTimo Sirainen if (internal_handler(type, fmt, args) < 0 &&
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen status == FATAL_DEFAULT)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen status = FATAL_LOGERROR;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen default_fatal_finish(type, status);
b7651d283ca261015ef3c445f1f27f340f0864e2Timo Sirainen}
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainenstatic void
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Siraineni_internal_error_handler(enum log_type type, const char *fmt, va_list args)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen if (internal_handler(type, fmt, args) < 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen failure_exit(FATAL_LOGERROR);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenvoid i_set_failure_internal(void)
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen{
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_set_fatal_handler(i_internal_fatal_handler);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen i_set_error_handler(i_internal_error_handler);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_set_info_handler(i_internal_error_handler);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen i_set_debug_handler(i_internal_error_handler);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen}
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainenvoid i_set_failure_ignore_errors(bool ignore)
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen{
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen failure_ignore_errors = ignore;
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen}
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainenvoid i_set_info_file(const char *path)
f20e7fbdc9bdbe8fecb9c661c9b8175f3bb78c69Timo Sirainen{
c0b1543512bc3e0a3a9f526056a3678a07ce32f5Timo Sirainen if (log_info_fd == log_fd)
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen log_info_fd = STDERR_FILENO;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen open_log_file(&log_info_fd, path);
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen info_handler = default_error_handler;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen /* write debug-level messages to the info_log_path,
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen until i_set_debug_file() was called */
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen log_debug_fd = log_info_fd;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_set_debug_handler(NULL);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen}
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainenvoid i_set_debug_file(const char *path)
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen{
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen if (log_debug_fd == log_fd || log_debug_fd == log_info_fd)
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen log_debug_fd = STDERR_FILENO;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen open_log_file(&log_debug_fd, path);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen debug_handler = default_error_handler;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainenvoid i_set_failure_timestamp_format(const char *fmt)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen{
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_free(log_stamp_format);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen log_stamp_format = i_strdup(fmt);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainenvoid i_set_failure_ip(const struct ip_addr *ip)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen{
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_failure_send_option("ip", net_ip2addr(ip));
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainenvoid i_set_failure_exit_callback(void (*callback)(int *status))
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen{
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen failure_exit_callback = callback;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenvoid failures_deinit(void)
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (log_debug_fd == log_info_fd || log_debug_fd == log_fd)
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen log_debug_fd = STDERR_FILENO;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (log_info_fd == log_fd)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen log_info_fd = STDERR_FILENO;
5965eaa2d972e6264cecaf54091cd43019bc7d1fTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (log_fd != STDERR_FILENO) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (void)close(log_fd);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen log_fd = STDERR_FILENO;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen if (log_info_fd != STDERR_FILENO) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen (void)close(log_info_fd);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen log_info_fd = STDERR_FILENO;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen if (log_debug_fd != STDERR_FILENO) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen (void)close(log_debug_fd);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen log_debug_fd = STDERR_FILENO;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen }
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_free_and_null(log_prefix);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen i_free_and_null(log_stamp_format);
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen}
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen