dovecot-2.0: doveconf: With -p only protocol-specific settings a...

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 30 22:02:53 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/f8460b27db00
changeset: 9179:f8460b27db00
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 30 15:02:44 2009 -0400
description:
doveconf: With -p only protocol-specific settings are returned. -n and -a return human-readable output.

diffstat:

14 files changed, 486 insertions(+), 266 deletions(-)
src/config/Makefile.am             |    2 
src/config/common.h                |    8 -
src/config/config-connection.c     |  205 +++++++++++++++++++++++++++----
src/config/config-connection.h     |    7 -
src/config/config-parser.c         |  223 ++--------------------------------
src/config/config-parser.h         |    3 
src/config/config-request.c        |  236 ++++++++++++++++++++++++++++++++++++
src/config/config-request.h        |   15 ++
src/config/main.c                  |   21 +--
src/config/settings-get.pl         |    3 
src/imap/imap-settings.c           |    8 +
src/lib-lda/lda-settings.c         |   11 +
src/lib-settings/settings-parser.h |    2 
src/pop3/pop3-settings.c           |    8 +

diffs (truncated from 1034 to 300 lines):

diff -r 13bbdd7b15b8 -r f8460b27db00 src/config/Makefile.am
--- a/src/config/Makefile.am	Thu Apr 30 14:48:54 2009 -0400
+++ b/src/config/Makefile.am	Thu Apr 30 15:02:44 2009 -0400
@@ -22,11 +22,11 @@ doveconf_SOURCES = \
 	all-settings.c \
 	config-connection.c \
 	config-parser.c \
+	config-request.c \
 	main.c
 
 noinst_HEADERS = \
 	all-settings.h \
-	common.h \
 	config-connection.h \
 	config-parser.h
 
diff -r 13bbdd7b15b8 -r f8460b27db00 src/config/common.h
--- a/src/config/common.h	Thu Apr 30 14:48:54 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include "lib.h"
-
-extern ARRAY_TYPE(const_string) config_strings;
-
-#endif
diff -r 13bbdd7b15b8 -r f8460b27db00 src/config/config-connection.c
--- a/src/config/config-connection.c	Thu Apr 30 14:48:54 2009 -0400
+++ b/src/config/config-connection.c	Thu Apr 30 15:02:44 2009 -0400
@@ -1,19 +1,18 @@
 /* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
 
-#include "common.h"
+#include "lib.h"
 #include "array.h"
-#include "str.h"
 #include "llist.h"
 #include "ioloop.h"
 #include "network.h"
 #include "istream.h"
 #include "ostream.h"
 #include "env-util.h"
+#include "config-request.h"
 #include "config-connection.h"
 
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 
 #define MAX_INBUF_SIZE 1024
 
@@ -46,24 +45,176 @@ config_connection_next_line(struct confi
 	return t_strsplit(line, "\t");
 }
 
+static void
+config_request_output(const char *key, const char *value,
+		      bool list ATTR_UNUSED, void *context)
+{
+	struct ostream *output = context;
+
+	o_stream_send_str(output, key);
+	o_stream_send_str(output, "=");
+	o_stream_send_str(output, value);
+	o_stream_send_str(output, "\n");
+}
+
+struct config_request_get_string_ctx {
+	pool_t pool;
+	ARRAY_TYPE(const_string) strings;
+};
+
+static void
+config_request_get_strings(const char *key, const char *value,
+			   bool list, void *context)
+{
+	struct config_request_get_string_ctx *ctx = context;
+
+	value = p_strdup_printf(ctx->pool, list ? "-%s=%s" : "%s=%s",
+				key, value);
+	array_append(&ctx->strings, &value, 1);
+}
+
+static int config_string_cmp(const void *p1, const void *p2)
+{
+	const char *s1 = *(const char *const *)p1;
+	const char *s2 = *(const char *const *)p2;
+	unsigned int i = 0;
+
+	while (s1[i] == s2[i]) {
+		if (s1[i] == '\0' || s1[i] == '=')
+			return 0;
+		i++;
+	}
+
+	if (s1[i] == '=')
+		return -1;
+	if (s2[i] == '=')
+		return 1;
+	return s1[i] - s2[i];
+}
+
+static unsigned int prefix_stack_pop(ARRAY_TYPE(uint) *stack)
+{
+	const unsigned int *indexes;
+	unsigned int idx, count;
+
+	indexes = array_get(stack, &count);
+	idx = count <= 1 ? -1U : indexes[count-2];
+	array_delete(stack, count-1, 1);
+	return idx;
+}
+
+static void config_connection_request_human(struct ostream *output,
+					    const char *service,
+					    enum config_dump_flags flags)
+{
+	static const char *ident_str = "               ";
+	ARRAY_TYPE(const_string) prefixes_arr;
+	ARRAY_TYPE(uint) prefix_idx_stack;
+	struct config_request_get_string_ctx ctx;
+	const char **strings, *const *args, *p, *str, *const *prefixes;
+	const char *key, *value;
+	unsigned int i, j, count, len, prefix_count, skip_len;
+	unsigned int indent = 0, prefix_idx = -1U;
+
+	ctx.pool = pool_alloconly_create("config human strings", 10240);
+	i_array_init(&ctx.strings, 256);
+	config_request_handle(service, flags, config_request_get_strings, &ctx);
+
+	strings = array_get_modifiable(&ctx.strings, &count);
+	qsort(strings, count, sizeof(*strings), config_string_cmp);
+
+	p_array_init(&prefixes_arr, ctx.pool, 32);
+	for (i = 0; i < count && strings[i][0] == '-'; i++) T_BEGIN {
+		p = strchr(strings[i], '=');
+		i_assert(p != NULL);
+		for (args = t_strsplit(p + 1, " "); *args != NULL; args++) {
+			str = p_strdup_printf(ctx.pool, "%s/%s/",
+					      t_strcut(strings[i]+1, '='),
+					      *args);
+			array_append(&prefixes_arr, &str, 1);
+		}
+	} T_END;
+	prefixes = array_get(&prefixes_arr, &prefix_count);
+
+	p_array_init(&prefix_idx_stack, ctx.pool, 8);
+	for (; i < count; i++) T_BEGIN {
+		value = strchr(strings[i], '=');
+		i_assert(value != NULL);
+		key = t_strdup_until(strings[i], value);
+		value++;
+
+		j = 0;
+		while (prefix_idx != -1U) {
+			len = strlen(prefixes[prefix_idx]);
+			if (strncmp(prefixes[prefix_idx], key, len) != 0) {
+				prefix_idx = prefix_stack_pop(&prefix_idx_stack);
+				indent--;
+				o_stream_send(output, ident_str, indent*2);
+				o_stream_send_str(output, "}\n");
+			} else if (strchr(key + len, '/') == NULL) {
+				/* keep the prefix */
+				j = prefix_count;
+				break;
+			} else {
+				/* subprefix */
+				break;
+			}
+		}
+		for (; j < prefix_count; j++) {
+			len = strlen(prefixes[j]);
+			if (strncmp(prefixes[j], key, len) == 0 &&
+			    strchr(key + len, '/') == NULL) {
+				key += prefix_idx == -1U ? 0 :
+					strlen(prefixes[prefix_idx]);
+				o_stream_send(output, ident_str, indent*2);
+				o_stream_send_str(output, t_strcut(key, '/'));
+				o_stream_send_str(output, " {\n");
+				indent++;
+				prefix_idx = j;
+				array_append(&prefix_idx_stack, &prefix_idx, 1);
+				break;
+			}
+		}
+		skip_len = prefix_idx == -1U ? 0 : strlen(prefixes[prefix_idx]);
+		i_assert(strncmp(prefixes[prefix_idx], strings[i], skip_len) == 0);
+		o_stream_send(output, ident_str, indent*2);
+		key = strings[i] + skip_len;
+		value = strchr(key, '=');
+		o_stream_send(output, key, value-key);
+		o_stream_send_str(output, " = ");
+		o_stream_send_str(output, value+1);
+		o_stream_send(output, "\n", 1);
+	} T_END;
+
+	while (prefix_idx != -1U) {
+		prefix_idx = prefix_stack_pop(&prefix_idx_stack);
+		indent--;
+		o_stream_send(output, ident_str, indent*2);
+		o_stream_send_str(output, "}\n");
+	}
+
+	array_free(&ctx.strings);
+	pool_unref(&ctx.pool);
+}
+
 static void config_connection_request(struct config_connection *conn,
 				      const char *const *args,
 				      enum config_dump_flags flags)
 {
-	const char *const *strings;
-	unsigned int i, count;
-	string_t *str;
-
-	/* <process> [<args>] */
-	str = t_str_new(256);
-	strings = array_get(&config_strings, &count);
+	const char *service = "";
+
+	/* [<service> [<args>]] */
+	if (args[0] != NULL)
+		service = args[0];
+
 	o_stream_cork(conn->output);
-	for (i = 0; i < count; i += 2) {
-		str_truncate(str, 0);
-		str_printfa(str, "%s=%s\n", strings[i], strings[i+1]);
-		o_stream_send(conn->output, str_data(str), str_len(str));
-	}
-	o_stream_send_str(conn->output, "\n");
+	if ((flags & CONFIG_DUMP_FLAG_HUMAN) == 0) {
+		config_request_handle(service, flags, config_request_output,
+				      conn->output);
+		o_stream_send_str(conn->output, "\n");
+	} else {
+		config_connection_request_human(conn->output, service, flags);
+	}
 	o_stream_uncork(conn->output);
 }
 
@@ -138,20 +289,22 @@ void config_connection_dump_request(int 
 	const char *args[2] = { service, NULL };
 
 	conn = config_connection_create(fd);
-        config_connection_request(conn, args, flags);
+	config_connection_request(conn, args, flags);
 	config_connection_destroy(conn);
 }
 
-void config_connection_putenv(void)
-{
-	const char *const *strings;
-	unsigned int i, count;
-
-	strings = array_get(&config_strings, &count);
-	for (i = 0; i < count; i += 2) T_BEGIN {
-		env_put(t_strconcat(t_str_ucase(strings[i]), "=",
-				    strings[i+1], NULL));
+static void config_request_putenv(const char *key, const char *value,
+				  bool list ATTR_UNUSED,
+				  void *context ATTR_UNUSED)
+{
+	T_BEGIN {
+		env_put(t_strconcat(t_str_ucase(key), "=", value, NULL));
 	} T_END;
+}
+
+void config_connection_putenv(const char *service)
+{
+	config_request_handle(service, 0, config_request_putenv, NULL);
 }
 
 void config_connections_destroy_all(void)
diff -r 13bbdd7b15b8 -r f8460b27db00 src/config/config-connection.h
--- a/src/config/config-connection.h	Thu Apr 30 14:48:54 2009 -0400
+++ b/src/config/config-connection.h	Thu Apr 30 15:02:44 2009 -0400
@@ -1,17 +1,14 @@
 #ifndef CONFIG_CONNECTION_H
 #define CONFIG_CONNECTION_H
 
-enum config_dump_flags {
-	CONFIG_DUMP_FLAG_HUMAN		= 0x01,
-	CONFIG_DUMP_FLAG_DEFAULTS	= 0x02
-};
+enum config_dump_flags;
 
 struct config_connection *config_connection_create(int fd);
 void config_connection_destroy(struct config_connection *conn);
 
 void config_connection_dump_request(int fd, const char *service,
 				    enum config_dump_flags flags);
-void config_connection_putenv(void);
+void config_connection_putenv(const char *service);
 
 void config_connections_destroy_all(void);
 
diff -r 13bbdd7b15b8 -r f8460b27db00 src/config/config-parser.c


More information about the dovecot-cvs mailing list