]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added command_register() and related functions so we can dynamically
authorTimo Sirainen <tss@iki.fi>
Wed, 14 May 2003 17:23:11 +0000 (20:23 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 14 May 2003 17:23:11 +0000 (20:23 +0300)
register new commands.

--HG--
branch : HEAD

src/imap/client.c
src/imap/client.h
src/imap/cmd-uid.c
src/imap/commands.c
src/imap/commands.h
src/imap/main.c

index 1d1bf88be67e6e2c1ba325008cad59968afef36a..2820385acf8b81325f62c65aaf73fc0cda650a7f 100644 (file)
@@ -292,7 +292,7 @@ static int client_handle_input(struct client *client)
                /* command not given - cmd_func is already NULL. */
        } else {
                /* find the command function */
-               client->cmd_func = client_command_find(client->cmd_name);
+               client->cmd_func = command_find(client->cmd_name);
        }
 
        if (client->cmd_func == NULL) {
index 6a61fdf50a902ce05efce8dd78028aa7a50d54ef..495338b415a66c0c1f4dcde20bbfb001c485e31d 100644 (file)
@@ -6,7 +6,7 @@ struct mail_storage;
 struct imap_parser;
 struct imap_arg;
 
-typedef int client_command_func_t(struct client *client);
+typedef int command_func_t(struct client *client);
 
 struct mailbox_custom_flags {
        pool_t pool; /* will be p_clear()ed when changed */
@@ -32,7 +32,7 @@ struct client {
        struct imap_parser *parser;
        const char *cmd_tag; /* tag of command (allocated from parser pool), */
        const char *cmd_name; /* command name (allocated from parser pool) */
-       client_command_func_t *cmd_func;
+       command_func_t *cmd_func;
 
        struct timeout *idle_to;
        unsigned int idle_expunge;
index 1e6ec7ae0998a25fd63d5597777dbfd8e1575199..8e583777e233bebcf62978cad0ee500fbd82a870 100644 (file)
@@ -12,33 +12,7 @@ int cmd_uid(struct client *client)
        if (cmd == NULL)
                return FALSE;
 
-       client->cmd_func = NULL;
-       switch (*cmd) {
-       case 'c':
-       case 'C':
-               if (strcasecmp(cmd, "COPY") == 0)
-                       client->cmd_func = cmd_copy;
-               break;
-       case 'f':
-       case 'F':
-               if (strcasecmp(cmd, "FETCH") == 0)
-                       client->cmd_func = cmd_fetch;
-               break;
-       case 's':
-       case 'S':
-               if (strcasecmp(cmd, "STORE") == 0)
-                       client->cmd_func = cmd_store;
-               else if (strcasecmp(cmd, "SEARCH") == 0)
-                       client->cmd_func = cmd_search;
-               else if (strcasecmp(cmd, "SORT") == 0)
-                       client->cmd_func = cmd_sort;
-               break;
-       case 't':
-       case 'T':
-               if (strcasecmp(cmd, "THREAD") == 0)
-                       client->cmd_func = cmd_thread;
-               break;
-       }
+       client->cmd_func = command_find(t_strconcat("UID ", cmd, NULL));
 
        if (client->cmd_func != NULL) {
                client->cmd_uid = TRUE;
index 1d6bf6209c4aa53d4906a2474580095209011b0a..31df3dc936f3c3d348784fad7fafc7fbb1a280b6 100644 (file)
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "common.h"
+#include "buffer.h"
 #include "commands.h"
 
-client_command_func_t *client_command_find(const char *name)
+#include <stdlib.h>
+
+const struct command imap4rev1_commands[] = {
+       { "AUTHENTICATE",       cmd_authenticate },
+       { "CAPABILITY",         cmd_capability },
+       { "LOGIN",              cmd_login },
+       { "LOGOUT",             cmd_logout },
+       { "NOOP",               cmd_noop },
+
+       { "APPEND",             cmd_append },
+       { "EXAMINE",            cmd_examine },
+       { "CREATE",             cmd_create },
+       { "DELETE",             cmd_delete },
+       { "RENAME",             cmd_rename },
+       { "LIST",               cmd_list },
+       { "LSUB",               cmd_lsub },
+       { "SELECT",             cmd_select },
+       { "STATUS",             cmd_status },
+       { "SUBSCRIBE",          cmd_subscribe },
+       { "UNSUBSCRIBE",        cmd_unsubscribe },
+
+       { "CHECK",              cmd_check },
+       { "CLOSE",              cmd_close },
+       { "COPY",               cmd_copy },
+       { "EXPUNGE",            cmd_expunge },
+       { "FETCH",              cmd_fetch },
+       { "SEARCH",             cmd_search },
+       { "STORE",              cmd_store },
+       { "UID",                cmd_uid },
+       { "UID COPY",           cmd_copy },
+       { "UID FETCH",          cmd_fetch },
+       { "UID SEARCH",         cmd_search },
+       { "UID STORE",          cmd_store }
+};
+#define IMAP4REV1_COMMANDS_COUNT \
+       (sizeof(imap4rev1_commands) / sizeof(imap4rev1_commands[0]))
+
+const struct command imap_ext_commands[] = {
+       { "IDLE",               cmd_idle },
+       { "SORT",               cmd_sort },
+       { "THREAD",             cmd_thread },
+       { "UID SORT",           cmd_sort },
+       { "UID THREAD",         cmd_thread },
+       { "UNSELECT",           cmd_unselect }
+};
+#define IMAP_EXT_COMMANDS_COUNT \
+       (sizeof(imap_ext_commands) / sizeof(imap_ext_commands[0]))
+
+static buffer_t *cmdbuf;
+static int cmdbuf_unsorted;
+
+void command_register(const char *name, command_func_t *func)
+{
+       struct command *cmd;
+
+       cmd = buffer_append_space(cmdbuf, sizeof(*cmd));
+       cmd->name = name;
+       cmd->func = func;
+
+       cmdbuf_unsorted = TRUE;
+}
+
+void command_unregister(const char *name)
+{
+       const struct command *cmd;
+       size_t i, size, count;
+
+       cmd = buffer_get_data(cmdbuf, &size);
+       count = size / sizeof(*cmd);
+
+       for (i = 0; i < count; i++) {
+               if (strcasecmp(cmd[i].name, name) == 0) {
+                       buffer_delete(cmdbuf, i * sizeof(*cmd), sizeof(*cmd));
+                       return;
+               }
+       }
+
+       i_error("Trying to unregister unknown command '%s'", name);
+}
+
+void command_register_array(const struct command *commands, size_t count)
+{
+       cmdbuf_unsorted = TRUE;
+       buffer_append(cmdbuf, commands, sizeof(*commands) * count);
+}
+
+void command_unregister_array(const struct command *commands, size_t count)
 {
-       /* keep the command uppercased */
-       name = str_ucase(t_strdup_noconst(name));
-
-       switch (*name) {
-       case 'A':
-               if (strcmp(name, "APPEND") == 0)
-                       return cmd_append;
-               if (strcmp(name, "AUTHENTICATE") == 0)
-                       return cmd_authenticate;
-               break;
-       case 'C':
-               if (strcmp(name, "CREATE") == 0)
-                       return cmd_create;
-               if (strcmp(name, "COPY") == 0)
-                       return cmd_copy;
-               if (strcmp(name, "CLOSE") == 0)
-                       return cmd_close;
-               if (strcmp(name, "CHECK") == 0)
-                       return cmd_check;
-               if (strcmp(name, "CAPABILITY") == 0)
-                       return cmd_capability;
-               break;
-       case 'D':
-               if (strcmp(name, "DELETE") == 0)
-                       return cmd_delete;
-               break;
-       case 'E':
-               if (strcmp(name, "EXPUNGE") == 0)
-                       return cmd_expunge;
-               if (strcmp(name, "EXAMINE") == 0)
-                       return cmd_examine;
-               break;
-       case 'F':
-               if (strcmp(name, "FETCH") == 0)
-                       return cmd_fetch;
-               break;
-       case 'I':
-               if (strcmp(name, "IDLE") == 0)
-                       return cmd_idle;
-               break;
-       case 'L':
-               if (strcmp(name, "LIST") == 0)
-                       return cmd_list;
-               if (strcmp(name, "LSUB") == 0)
-                       return cmd_lsub;
-               if (strcmp(name, "LOGOUT") == 0)
-                       return cmd_logout;
-               if (strcmp(name, "LOGIN") == 0)
-                       return cmd_login;
-               break;
-       case 'N':
-               if (strcmp(name, "NOOP") == 0)
-                       return cmd_noop;
-               break;
-       case 'R':
-               if (strcmp(name, "RENAME") == 0)
-                       return cmd_rename;
-               break;
-       case 'S':
-               if (strcmp(name, "STORE") == 0)
-                       return cmd_store;
-               if (strcmp(name, "SEARCH") == 0)
-                       return cmd_search;
-               if (strcmp(name, "SORT") == 0)
-                       return cmd_sort;
-               if (strcmp(name, "SELECT") == 0)
-                       return cmd_select;
-               if (strcmp(name, "STATUS") == 0)
-                       return cmd_status;
-               if (strcmp(name, "SUBSCRIBE") == 0)
-                       return cmd_subscribe;
-               break;
-       case 'T':
-               if (strcmp(name, "THREAD") == 0)
-                       return cmd_thread;
-               break;
-       case 'U':
-               if (strcmp(name, "UID") == 0)
-                       return cmd_uid;
-               if (strcmp(name, "UNSUBSCRIBE") == 0)
-                       return cmd_unsubscribe;
-               if (strcmp(name, "UNSELECT") == 0)
-                       return cmd_unselect;
-
-               break;
+       while (count > 0) {
+               command_unregister(commands->name);
+               count--; commands++;
        }
+}
+
+static int command_cmp(const void *p1, const void *p2)
+{
+        const struct command *c1 = p1, *c2 = p2;
+
+       return strcasecmp(c1->name, c2->name);
+}
+
+static int command_bsearch(const void *name, const void *cmd_p)
+{
+        const struct command *cmd = cmd_p;
+
+       return strcasecmp(name, cmd->name);
+}
+
+command_func_t *command_find(const char *name)
+{
+       const struct command *cmd;
+       void *base;
+       size_t size;
 
-       return NULL;
+       base = buffer_get_modifyable_data(cmdbuf, &size);
+       size /= sizeof(struct command);
+
+       if (cmdbuf_unsorted) {
+               qsort(base, size, sizeof(struct command), command_cmp);
+                cmdbuf_unsorted = FALSE;
+       }
+
+       cmd = bsearch(name, base, size, sizeof(struct command),
+                     command_bsearch);
+       return cmd == NULL ? NULL : cmd->func;
+}
+
+void commands_init(void)
+{
+       cmdbuf = buffer_create_dynamic(system_pool,
+                                      sizeof(struct command) * 64, (size_t)-1);
+       cmdbuf_unsorted = FALSE;
+
+        command_register_array(imap4rev1_commands, IMAP4REV1_COMMANDS_COUNT);
+        command_register_array(imap_ext_commands, IMAP_EXT_COMMANDS_COUNT);
+}
+
+void commands_deinit(void)
+{
+        command_unregister_array(imap4rev1_commands, IMAP4REV1_COMMANDS_COUNT);
+        command_unregister_array(imap_ext_commands, IMAP_EXT_COMMANDS_COUNT);
+       buffer_free(cmdbuf);
 }
index 89aa8228b7ec907e55e62c1a4c827b686a72e671..7a044852ababf59e3d94aa4f9ed7c5a1685ecf0f 100644 (file)
@@ -5,7 +5,26 @@
 #include "imap-parser.h"
 #include "commands-util.h"
 
-client_command_func_t *client_command_find(const char *name);
+struct command {
+       const char *name;
+       command_func_t *func;
+};
+
+/* Register command. Given name parameter must be permanently stored until
+   command is unregistered. */
+void command_register(const char *name, command_func_t *func);
+void command_unregister(const char *name);
+
+/* Register array of commands. */
+void command_register_array(const struct command *commands, size_t count);
+void command_unregister_array(const struct command *commands, size_t count);
+
+command_func_t *command_find(const char *name);
+
+void commands_init(void);
+void commands_deinit(void);
+
+/* IMAP4rev1 commands: */
 
 /* Non-Authenticated State */
 int cmd_authenticate(struct client *client);
@@ -37,12 +56,14 @@ int cmd_check(struct client *client);
 int cmd_close(struct client *client);
 int cmd_expunge(struct client *client);
 int cmd_search(struct client *client);
-int cmd_sort(struct client *client);
-int cmd_thread(struct client *client);
 int cmd_fetch(struct client *client);
 int cmd_store(struct client *client);
 int cmd_copy(struct client *client);
 int cmd_uid(struct client *client);
+
+/* IMAP extensions: */
+int cmd_sort(struct client *client);
+int cmd_thread(struct client *client);
 int cmd_unselect(struct client *client);
 int cmd_idle(struct client *client);
 
index 68b6dbb2161f6d1916ba0dee2f99c2d8de1312ad..fe025497e551cd33b224753feb2c409ff0c9b11f 100644 (file)
@@ -8,6 +8,7 @@
 #include "fd-close-on-exec.h"
 #include "process-title.h"
 #include "mail-storage.h"
+#include "commands.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -87,6 +88,7 @@ static void main_init(void)
 
         mail_storage_init();
        mail_storage_register_all();
+       commands_init();
        clients_init();
 
        mail = getenv("MAIL");
@@ -143,6 +145,7 @@ static void main_deinit(void)
                i_warning("Killed with signal %d", lib_signal_kill);
 
        clients_deinit();
+       commands_deinit();
         mail_storage_deinit();
 
        closelog();