failures.c revision bb3d09ab39d75ca5269723237f4e0eeec916b534
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi "Warning: ",
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic char log_type_internal_chars[] = {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi/* Initialize working defaults */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic fatal_failure_callback_t *fatal_handler ATTR_NORETURN =
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic failure_callback_t *error_handler = default_error_handler;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic failure_callback_t *info_handler = default_error_handler;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic void (*failure_exit_callback)(int *) = NULL;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic int log_fd = STDERR_FILENO, log_info_fd = STDERR_FILENO;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic char *log_prefix = NULL, *log_stamp_format = NULL;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi/* kludgy .. we want to trust log_stamp_format with -Wformat-nonliteral */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic const char *get_log_stamp_format(const char *unused)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic const char *get_log_stamp_format(const char *unused ATTR_UNUSED)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic void log_fd_flush_stop(struct ioloop *ioloop)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic int log_fd_write(int fd, const unsigned char *data, unsigned int len)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi while ((ret = write(fd, data, len)) != (ssize_t)len) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* some was written, continue.. */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (ret == 0) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* out of disk space? */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* wait until we can write more. this can happen at least
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi when writing to terminal, even if fd is blocking. */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi io = io_add(fd, IO_WRITE, log_fd_flush_stop, ioloop);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomidefault_handler(const char *prefix, int fd, const char *format, va_list args)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi static int recursed = 0;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* we're being called from some signal handler or we ran
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi out of memory */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* make sure there's no %n in there and fix %m */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi str_vprintfa(str, printf_format_fix(format), args);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi ret = log_fd_write(fd, str_data(str), str_len(str));
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomidefault_fatal_finish(enum log_type type, int status)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (type == LOG_TYPE_PANIC || status == FATAL_OUTOFMEM) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid default_fatal_handler(enum log_type type, int status,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (default_handler(failure_log_type_prefixes[type], log_fd, format,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid default_error_handler(enum log_type type, const char *format, va_list args)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi int fd = type == LOG_TYPE_INFO ? log_info_fd : log_fd;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (default_handler(failure_log_type_prefixes[type],
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* we failed to log to info log, try to log the write error
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi to error log - maybe that'll work. */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi "write() failed to info log: %m");
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_log_type(enum log_type type, const char *format, ...)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi fatal_handler(LOG_TYPE_FATAL, FATAL_DEFAULT, format, args);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_fatal_status(int status, const char *format, ...)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi fatal_handler(LOG_TYPE_FATAL, status, format, args);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_set_fatal_handler(fatal_failure_callback_t *callback ATTR_NORETURN)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_set_error_handler(failure_callback_t *callback)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_set_info_handler(failure_callback_t *callback)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomisyslog_handler(int level, enum log_type type, const char *format, va_list args)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi static int recursed = 0;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* syslogs don't generatelly bother to log the level in any way,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi so make sure fatals and panics are shown clearly */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi type == LOG_TYPE_FATAL || type == LOG_TYPE_PANIC ?
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_syslog_fatal_handler(enum log_type type, int status,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (syslog_handler(LOG_CRIT, type, fmt, args) < 0 &&
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_syslog_error_handler(enum log_type type, const char *fmt, va_list args)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid i_set_failure_syslog(const char *ident, int options, int facility)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic void open_log_file(int *fd, const char *path)
static int recursed = 0;
int ret;
recursed++;
T_BEGIN {
} T_END;
recursed--;
return ret;
void i_set_failure_internal(void)
void failures_deinit(void)