Mercurial > dovecot > core-2.2
changeset 13291:6eb42d5d0ce3
imap: Added hooks that can be run always before/after any command handler.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 26 Aug 2011 05:08:42 +0300 |
parents | d473660bc54d |
children | 78f9f28b5d24 |
files | src/imap/cmd-append.c src/imap/cmd-uid.c src/imap/imap-client.c src/imap/imap-commands.c src/imap/imap-commands.h |
diffstat | 5 files changed, 63 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-append.c Fri Aug 26 05:07:53 2011 +0300 +++ b/src/imap/cmd-append.c Fri Aug 26 05:08:42 2011 +0300 @@ -98,7 +98,7 @@ } o_stream_cork(client->output); - finished = cmd->func(cmd); + finished = command_exec(cmd); if (!finished && cmd->state != CLIENT_COMMAND_STATE_DONE) (void)client_handle_unfinished_cmd(cmd); else
--- a/src/imap/cmd-uid.c Fri Aug 26 05:07:53 2011 +0300 +++ b/src/imap/cmd-uid.c Fri Aug 26 05:08:42 2011 +0300 @@ -24,5 +24,5 @@ cmd->cmd_flags = command->flags; cmd->func = command->func; cmd->uid = TRUE; - return cmd->func(cmd); + return command_exec(cmd); }
--- a/src/imap/imap-client.c Fri Aug 26 05:07:53 2011 +0300 +++ b/src/imap/imap-client.c Fri Aug 26 05:08:42 2011 +0300 @@ -123,7 +123,8 @@ i_unreached(); } - cmd_ret = !cmd->cancel || cmd->func == NULL ? TRUE : cmd->func(cmd); + cmd_ret = !cmd->cancel || cmd->func == NULL ? TRUE : + command_exec(cmd); if (!cmd_ret && cmd->state != CLIENT_COMMAND_STATE_DONE) { if (cmd->client->output->closed) i_panic("command didn't cancel itself: %s", cmd->name); @@ -669,7 +670,8 @@ if (cmd->func != NULL) { /* command is being executed - continue it */ - if (cmd->func(cmd) || cmd->state == CLIENT_COMMAND_STATE_DONE) { + if (command_exec(cmd) || + cmd->state == CLIENT_COMMAND_STATE_DONE) { /* command execution was finished */ client_command_free(&cmd); client_add_missing_io(client); @@ -837,7 +839,7 @@ bool finished; /* continue processing command */ - finished = cmd->func(cmd) || cmd->state == CLIENT_COMMAND_STATE_DONE; + finished = command_exec(cmd) || cmd->state == CLIENT_COMMAND_STATE_DONE; if (!finished) (void)client_handle_unfinished_cmd(cmd);
--- a/src/imap/imap-commands.c Fri Aug 26 05:07:53 2011 +0300 +++ b/src/imap/imap-commands.c Fri Aug 26 05:08:42 2011 +0300 @@ -7,6 +7,11 @@ #include <stdlib.h> +struct command_hook { + command_hook_callback_t *pre; + command_hook_callback_t *post; +}; + static const struct command imap4rev1_commands[] = { { "CAPABILITY", cmd_capability, 0 }, { "LOGOUT", cmd_logout, COMMAND_FLAG_BREAKS_MAILBOX }, @@ -60,6 +65,7 @@ ARRAY_TYPE(command) imap_commands; static bool commands_unsorted; +static ARRAY_DEFINE(command_hooks, struct command_hook); void command_register(const char *name, command_func_t *func, enum command_flags flags) @@ -105,6 +111,45 @@ } } +void command_hook_register(command_hook_callback_t *pre, + command_hook_callback_t *post) +{ + struct command_hook hook; + + hook.pre = pre; + hook.post = post; + array_append(&command_hooks, &hook, 1); +} + +void command_hook_unregister(command_hook_callback_t *pre, + command_hook_callback_t *post) +{ + const struct command_hook *hooks; + unsigned int i, count; + + hooks = array_get(&command_hooks, &count); + for (i = 0; i < count; i++) { + if (hooks[i].pre == pre && hooks[i].post == post) { + array_delete(&command_hooks, i, 1); + return; + } + } + i_panic("command_hook_unregister(): hook not registered"); +} + +bool command_exec(struct client_command_context *cmd) +{ + const struct command_hook *hook; + bool ret; + + array_foreach(&command_hooks, hook) + hook->pre(cmd); + ret = cmd->func(cmd); + array_foreach(&command_hooks, hook) + hook->post(cmd); + return ret; +} + static int command_cmp(const struct command *c1, const struct command *c2) { return strcasecmp(c1->name, c2->name); @@ -128,6 +173,7 @@ void commands_init(void) { i_array_init(&imap_commands, 64); + i_array_init(&command_hooks, 4); commands_unsorted = FALSE; command_register_array(imap4rev1_commands, IMAP4REV1_COMMANDS_COUNT); @@ -139,4 +185,5 @@ command_unregister_array(imap4rev1_commands, IMAP4REV1_COMMANDS_COUNT); command_unregister_array(imap_ext_commands, IMAP_EXT_COMMANDS_COUNT); array_free(&imap_commands); + array_free(&command_hooks); }
--- a/src/imap/imap-commands.h Fri Aug 26 05:07:53 2011 +0300 +++ b/src/imap/imap-commands.h Fri Aug 26 05:08:42 2011 +0300 @@ -10,6 +10,7 @@ #include "imap-commands-util.h" typedef bool command_func_t(struct client_command_context *cmd); +typedef void command_hook_callback_t(struct client_command_context *ctx); enum command_flags { /* Command uses sequences as its input parameters */ @@ -52,6 +53,14 @@ void command_register_array(const struct command *cmdarr, unsigned int count); void command_unregister_array(const struct command *cmdarr, unsigned int count); +/* Register hook callbacks that are called before and after all commands */ +void command_hook_register(command_hook_callback_t *pre, + command_hook_callback_t *post); +void command_hook_unregister(command_hook_callback_t *pre, + command_hook_callback_t *post); +/* Execute command and hooks */ +bool command_exec(struct client_command_context *cmd); + struct command *command_find(const char *name); void commands_init(void);