# HG changeset patch # User Timo Sirainen # Date 1314324522 -10800 # Node ID 6eb42d5d0ce39324ae4dbc15cfb6f623638573c1 # Parent d473660bc54d1ead7aec74d6898e855fe9f18df8 imap: Added hooks that can be run always before/after any command handler. diff -r d473660bc54d -r 6eb42d5d0ce3 src/imap/cmd-append.c --- 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 diff -r d473660bc54d -r 6eb42d5d0ce3 src/imap/cmd-uid.c --- 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); } diff -r d473660bc54d -r 6eb42d5d0ce3 src/imap/imap-client.c --- 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); diff -r d473660bc54d -r 6eb42d5d0ce3 src/imap/imap-commands.c --- 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 +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); } diff -r d473660bc54d -r 6eb42d5d0ce3 src/imap/imap-commands.h --- 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);