/* Copyright (C) 2007 Timo Sirainen, LGPLv2.1 */ /* export DOVECOT=~/src/dovecot-1.0.0 gcc -fPIC -g -shared -Wall -I$DOVECOT -I$DOVECOT/src/lib \ -I$DOVECOT/src/lib-storage -I$DOVECOT/src/lib-mail \ -I$DOVECOT/src/lib-imap -I$DOVECOT/src/imap \ -DHAVE_CONFIG_H imap-alert-plugin.c -o imap_alert_plugin.so Usage: Write the text you want in the alert to /etc/dovecot.alert. Running imap processes check if the file has changed every 5 seconds. When it has, the file's contents are sent to IMAP client as: * OK [ALERT] . The file should have only a single line, but newlines and some other illegal characters are automatically converted to spaces. You can change the ALERT_* macros below to change settings. */ #include "lib.h" #include "ioloop.h" #include "ostream.h" #include "common.h" #include #include /* Check if file has changed every 5 seconds */ #define ALERT_CHECK_INTERVAL 5 /* Don't alert client more often than once every 60 seconds */ #define ALERT_SEND_INTERVAL 60 /* File to use for alert */ #define ALERT_FILE "/etc/dovecot.alert" const char *imap_alert_plugin_version = PACKAGE_VERSION; static void (*alert_next_hook_client_created)(struct client **client); static struct timeout *to; static time_t last_alert_check = 0, last_alert_sent = 0; static void alert_send(struct client *client, const char *path) { char buf[1024]; int fd; ssize_t i, ret; last_alert_sent = 0; fd = open(path, O_RDONLY); if (fd == -1) { if (errno != ENOENT) i_error("open(%s) failed: %m", path); return; } ret = read(fd, buf, sizeof(buf)-1); if (ret < 0) i_error("read(%s) failed: %m", path); else { /* convert illegal characters to spaces */ for (i = 0; i < ret; i++) { if (buf[i] == '\r' || buf[i] == '\n' || buf[i] == ']' || buf[i] == '\0') buf[i] = ' '; } while (ret > 0 && buf[ret-1] == ' ') ret--; buf[ret] = '\0'; if (ret != 0) { const char *text = t_strconcat("* OK [ALERT] ", buf, "\r\n", NULL); o_stream_send_str(client->output, text); o_stream_flush(client->output); last_alert_sent = ioloop_time; } } if (close(fd) < 0) i_error("close(%s) failed: %m", path); } static void alert_timeout(void *context) { struct client *client = context; if (client->output_lock != NULL) return; if (last_alert_check + ALERT_CHECK_INTERVAL < ioloop_time && last_alert_sent + ALERT_SEND_INTERVAL < ioloop_time) { last_alert_check = ioloop_time; alert_send(client, ALERT_FILE); } } static void alert_client_created(struct client **client) { if (alert_next_hook_client_created != NULL) alert_next_hook_client_created(client); to = timeout_add(ALERT_CHECK_INTERVAL * 1000/2, alert_timeout, *client); } void imap_alert_plugin_init(void); void imap_alert_plugin_deinit(void); void imap_alert_plugin_init(void) { alert_next_hook_client_created = hook_client_created; hook_client_created = alert_client_created; } void imap_alert_plugin_deinit(void) { if (to != NULL) timeout_remove(&to); hook_client_created = alert_next_hook_client_created; }