[dovecot-cvs] dovecot/src/imap client.c,1.27,1.28 client.h,1.14,1.15 cmd-uid.c,1.4,1.5 commands.c,1.9,1.10 commands.h,1.11,1.12 main.c,1.31,1.32

cras at procontrol.fi cras at procontrol.fi
Wed May 14 21:23:13 EEST 2003


Update of /home/cvs/dovecot/src/imap
In directory danu:/tmp/cvs-serv17074

Modified Files:
	client.c client.h cmd-uid.c commands.c commands.h main.c 
Log Message:
Added command_register() and related functions so we can dynamically
register new commands.



Index: client.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/client.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- client.c	20 Feb 2003 00:46:17 -0000	1.27
+++ client.c	14 May 2003 17:23:11 -0000	1.28
@@ -292,7 +292,7 @@
 		/* 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: client.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/client.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- client.h	20 Feb 2003 00:46:17 -0000	1.14
+++ client.h	14 May 2003 17:23:11 -0000	1.15
@@ -6,7 +6,7 @@
 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 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: cmd-uid.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-uid.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cmd-uid.c	8 Jan 2003 20:49:52 -0000	1.4
+++ cmd-uid.c	14 May 2003 17:23:11 -0000	1.5
@@ -12,33 +12,7 @@
 	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: commands.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- commands.c	14 Feb 2003 10:46:44 -0000	1.9
+++ commands.c	14 May 2003 17:23:11 -0000	1.10
@@ -1,96 +1,149 @@
 /* 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)
 {
-	/* keep the command uppercased */
-	name = str_ucase(t_strdup_noconst(name));
+	struct command *cmd;
 
-	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;
+	cmd = buffer_append_space(cmdbuf, sizeof(*cmd));
+	cmd->name = name;
+	cmd->func = func;
 
-		break;
+	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;
+		}
 	}
 
-	return NULL;
+	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)
+{
+	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;
+
+	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: commands.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- commands.h	24 Feb 2003 17:39:32 -0000	1.11
+++ commands.h	14 May 2003 17:23:11 -0000	1.12
@@ -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_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: main.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/main.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -d -r1.31 -r1.32
--- main.c	10 Apr 2003 22:37:25 -0000	1.31
+++ main.c	14 May 2003 17:23:11 -0000	1.32
@@ -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 @@
 
         mail_storage_init();
 	mail_storage_register_all();
+	commands_init();
 	clients_init();
 
 	mail = getenv("MAIL");
@@ -143,6 +145,7 @@
 		i_warning("Killed with signal %d", lib_signal_kill);
 
 	clients_deinit();
+	commands_deinit();
         mail_storage_deinit();
 
 	closelog();



More information about the dovecot-cvs mailing list