changeset 1058:3b8fb7bf7ecc HEAD

Moved settings parsing to lib-settings.
author Timo Sirainen <tss@iki.fi>
date Thu, 30 Jan 2003 21:01:40 +0200
parents c5ab972db48c
children d805c2f1d6a9
files configure.in src/lib-settings/.cvsignore src/lib-settings/Makefile.am src/lib-settings/settings.c src/lib-settings/settings.h src/master/Makefile.am src/master/common.h src/master/main.c src/master/master-settings.c src/master/master-settings.h src/master/settings.c src/master/settings.h
diffstat 12 files changed, 787 insertions(+), 733 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Thu Jan 30 20:27:09 2003 +0200
+++ b/configure.in	Thu Jan 30 21:01:40 2003 +0200
@@ -881,6 +881,7 @@
 src/lib-index/maildir/Makefile
 src/lib-index/mbox/Makefile
 src/lib-mail/Makefile
+src/lib-settings/Makefile
 src/lib-storage/Makefile
 src/lib-storage/index/Makefile
 src/lib-storage/index/maildir/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-settings/.cvsignore	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,8 @@
+*.la
+*.lo
+*.o
+.deps
+.libs
+Makefile
+Makefile.in
+so_locations
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-settings/Makefile.am	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,10 @@
+noinst_LIBRARIES = libsettings.a
+
+INCLUDES = \
+	-I$(top_srcdir)/src/lib
+
+libsettings_a_SOURCES = \
+	settings.c
+
+noinst_HEADERS = \
+	settings.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-settings/settings.c	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,127 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "lib.h"
+#include "istream.h"
+#include "settings.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+
+static const char *get_bool(const char *value, int *result)
+{
+	if (strcasecmp(value, "yes") == 0)
+		*result = TRUE;
+	else if (strcasecmp(value, "no") == 0)
+		*result = FALSE;
+	else
+		return t_strconcat("Invalid boolean: ", value, NULL);
+
+	return NULL;
+}
+
+static const char *get_uint(const char *value, unsigned int *result)
+{
+	int num;
+
+	if (!sscanf(value, "%i", &num) || num < 0)
+		return t_strconcat("Invalid number: ", value, NULL);
+	*result = num;
+	return NULL;
+}
+
+const char *
+parse_setting_from_defs(pool_t pool, struct setting_def *defs, void *base,
+			const char *key, const char *value)
+{
+	struct setting_def *def;
+
+	for (def = defs; def->name != NULL; def++) {
+		if (strcmp(def->name, key) == 0) {
+			void *ptr = STRUCT_MEMBER_P(base, def->offset);
+
+			switch (def->type) {
+			case SET_STR:
+				*((char **) ptr) =
+					p_strdup_empty(pool, value);
+				return NULL;
+			case SET_INT:
+				/* use %i so we can handle eg. 0600
+				   as octal value with umasks */
+				return get_uint(value, (unsigned int *) ptr);
+			case SET_BOOL:
+				return get_bool(value, (int *) ptr);
+			}
+		}
+	}
+
+	return t_strconcat("Unknown setting: ", key, NULL);
+}
+
+#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
+
+void settings_read(const char *path,
+		   const char *(*callback)(const char *key, const char *value))
+{
+	struct istream *input;
+	const char *errormsg;
+	char *line, *key, *p;
+	int fd, linenum;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		i_fatal("Can't open configuration file %s: %m", path);
+
+	linenum = 0;
+	input = i_stream_create_file(fd, default_pool, 2048, TRUE);
+	for (;;) {
+		line = i_stream_next_line(input);
+		if (line == NULL) {
+			if (i_stream_read(input) <= 0)
+				break;
+                        continue;
+		}
+		linenum++;
+
+		/* @UNSAFE: line is modified */
+
+		/* skip whitespace */
+		while (IS_WHITE(*line))
+			line++;
+
+		/* ignore comments or empty lines */
+		if (*line == '#' || *line == '\0')
+			continue;
+
+		/* all lines must be in format "key = value" */
+		key = line;
+		while (!IS_WHITE(*line) && *line != '\0')
+			line++;
+		if (IS_WHITE(*line)) {
+			*line++ = '\0';
+			while (IS_WHITE(*line)) line++;
+		}
+
+		if (*line != '=') {
+			errormsg = "Missing value";
+		} else {
+			/* skip whitespace after '=' */
+			*line++ = '\0';
+			while (IS_WHITE(*line)) line++;
+
+			/* skip trailing whitespace */
+			p = line + strlen(line);
+			while (p > line && IS_WHITE(p[-1]))
+				p--;
+			*p = '\0';
+
+			errormsg = callback(key, line);
+		}
+
+		if (errormsg != NULL) {
+			i_fatal("Error in configuration file %s line %d: %s",
+				path, linenum, errormsg);
+		}
+	};
+
+	i_stream_unref(input);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-settings/settings.h	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,23 @@
+#ifndef __SETTINGS_H
+#define __SETTINGS_H
+
+enum setting_type {
+	SET_STR,
+	SET_INT,
+	SET_BOOL
+};
+
+struct setting_def {
+	enum setting_type type;
+	const char *name;
+	size_t offset;
+};
+
+const char *
+parse_setting_from_defs(pool_t pool, struct setting_def *defs, void *base,
+			const char *key, const char *value);
+
+void settings_read(const char *path,
+		   const char *(*callback)(const char *key, const char *value));
+
+#endif
--- a/src/master/Makefile.am	Thu Jan 30 20:27:09 2003 +0200
+++ b/src/master/Makefile.am	Thu Jan 30 21:01:40 2003 +0200
@@ -4,6 +4,7 @@
 
 INCLUDES = \
 	-I$(top_srcdir)/src/lib \
+	-I$(top_srcdir)/src/lib-settings \
 	-DSYSCONFDIR=\""$(sysconfdir)"\" \
 	-DPKG_RUNDIR=\""$(localstatedir)/run/$(PACKAGE)"\" \
 	-DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
@@ -11,6 +12,7 @@
 
 dovecot_LDADD = \
 	../lib/liblib.a \
+	../lib-settings/libsettings.a \
 	$(SSL_LIBS)
 
 dovecot_SOURCES = \
@@ -18,7 +20,7 @@
 	login-process.c \
 	mail-process.c \
 	main.c \
-	settings.c \
+	master-settings.c \
 	ssl-init.c \
 	ssl-init-gnutls.c \
 	ssl-init-openssl.c
@@ -29,5 +31,5 @@
 	login-process.h \
 	mail-process.h \
 	master-login-interface.h \
-	settings.h \
+	master-settings.h \
 	ssl-init.h
--- a/src/master/common.h	Thu Jan 30 20:27:09 2003 +0200
+++ b/src/master/common.h	Thu Jan 30 21:01:40 2003 +0200
@@ -5,7 +5,7 @@
 
 #include "lib.h"
 #include "hash.h"
-#include "settings.h"
+#include "master-settings.h"
 
 #include "../auth/auth-master-interface.h"
 
--- a/src/master/main.c	Thu Jan 30 20:27:09 2003 +0200
+++ b/src/master/main.c	Thu Jan 30 21:01:40 2003 +0200
@@ -78,7 +78,7 @@
 {
 	i_warning("SIGHUP received - reloading configuration");
 
-	settings_read(configfile);
+	master_settings_read(configfile);
 
 	/* restart auth and login processes */
         login_processes_destroy_all();
@@ -389,8 +389,8 @@
 	}
 
 	/* read and verify settings before forking */
-	settings_init();
-	settings_read(configfile);
+	master_settings_init();
+	master_settings_read(configfile);
 	open_fds();
 
 	if (!foreground)
@@ -402,6 +402,7 @@
         io_loop_run(ioloop);
 	main_deinit();
 
+	master_settings_deinit();
 	io_loop_destroy(ioloop);
 	lib_deinit();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/master/master-settings.c	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,500 @@
+/* Copyright (C) 2002 Timo Sirainen */
+
+#include "common.h"
+#include "istream.h"
+#include "safe-mkdir.h"
+#include "unlink-directory.h"
+#include "settings.h"
+
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
+
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct settings, name) }
+
+static struct setting_def setting_defs[] = {
+	/* common */
+	DEF(SET_STR, base_dir),
+	DEF(SET_STR, log_path),
+	DEF(SET_STR, info_log_path),
+	DEF(SET_STR, log_timestamp),
+
+	/* general */
+	DEF(SET_STR, protocols),
+	DEF(SET_STR, imap_listen),
+	DEF(SET_STR, imaps_listen),
+	DEF(SET_STR, pop3_listen),
+	DEF(SET_STR, pop3s_listen),
+
+	DEF(SET_BOOL, ssl_disable),
+	DEF(SET_STR, ssl_cert_file),
+	DEF(SET_STR, ssl_key_file),
+	DEF(SET_STR, ssl_parameters_file),
+	DEF(SET_STR, ssl_parameters_regenerate),
+	DEF(SET_BOOL, disable_plaintext_auth),
+
+	/* login */
+	DEF(SET_STR, login_dir),
+	DEF(SET_BOOL, login_chroot),
+
+	/* mail */
+	DEF(SET_STR, valid_chroot_dirs),
+	DEF(SET_INT, max_mail_processes),
+	DEF(SET_BOOL, verbose_proctitle),
+
+	DEF(SET_INT, first_valid_uid),
+	DEF(SET_INT, last_valid_uid),
+	DEF(SET_INT, first_valid_gid),
+	DEF(SET_INT, last_valid_gid),
+
+	DEF(SET_STR, default_mail_env),
+	DEF(SET_STR, mail_cache_fields),
+	DEF(SET_STR, mail_never_cache_fields),
+	DEF(SET_STR, mailbox_check_interval),
+	DEF(SET_STR, mail_save_crlf),
+	DEF(SET_STR, mail_read_mmaped),
+	DEF(SET_STR, maildir_copy_with_hardlinks),
+	DEF(SET_STR, maildir_check_content_changes),
+	DEF(SET_STR, mbox_locks),
+	DEF(SET_STR, mbox_read_dotlock),
+	DEF(SET_STR, mbox_lock_timeout),
+	DEF(SET_STR, mbox_dotlock_change_timeout),
+	DEF(SET_STR, overwrite_incompatible_index),
+	DEF(SET_STR, umask),
+
+	/* imap */
+	DEF(SET_STR, imap_executable),
+	DEF(SET_INT, imap_process_size),
+
+	/* pop3 */
+	DEF(SET_STR, pop3_executable),
+	DEF(SET_INT, pop3_process_size),
+
+	{ 0, NULL, 0 }
+};
+
+#undef DEF
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct login_settings, name) }
+
+static struct setting_def login_setting_defs[] = {
+	DEF(SET_STR, executable),
+	DEF(SET_STR, user),
+
+	DEF(SET_BOOL, process_per_connection),
+
+	DEF(SET_INT, process_size),
+	DEF(SET_INT, processes_count),
+	DEF(SET_INT, max_processes_count),
+	DEF(SET_INT, max_logging_users),
+
+	{ 0, NULL, 0 }
+};
+
+#undef DEF
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct auth_settings, name) }
+
+static struct setting_def auth_setting_defs[] = {
+	DEF(SET_STR, mechanisms),
+	DEF(SET_STR, realms),
+	DEF(SET_STR, userdb),
+	DEF(SET_STR, passdb),
+	DEF(SET_STR, executable),
+	DEF(SET_STR, user),
+	DEF(SET_STR, chroot),
+
+	DEF(SET_BOOL, use_cyrus_sasl),
+	DEF(SET_BOOL, verbose),
+
+	DEF(SET_INT, count),
+	DEF(SET_INT, process_size),
+
+	{ 0, NULL, 0 }
+};
+
+struct settings default_settings = {
+	/* common */
+	MEMBER(base_dir) PKG_RUNDIR,
+	MEMBER(log_path) NULL,
+	MEMBER(info_log_path) NULL,
+	MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
+
+	/* general */
+	MEMBER(protocols) "imap imaps",
+	MEMBER(imap_listen) "*",
+	MEMBER(imaps_listen) NULL,
+	MEMBER(pop3_listen) "*",
+	MEMBER(pop3s_listen) NULL,
+
+	MEMBER(ssl_disable) FALSE,
+	MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
+	MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
+	MEMBER(ssl_parameters_file) "ssl-parameters.dat",
+	MEMBER(ssl_parameters_regenerate) 24,
+	MEMBER(disable_plaintext_auth) FALSE,
+
+	/* login */
+	MEMBER(login_dir) "login",
+	MEMBER(login_chroot) TRUE,
+
+	/* mail */
+	MEMBER(valid_chroot_dirs) NULL,
+	MEMBER(max_mail_processes) 1024,
+	MEMBER(verbose_proctitle) FALSE,
+
+	MEMBER(first_valid_uid) 500,
+	MEMBER(last_valid_uid) 0,
+	MEMBER(first_valid_gid) 1,
+	MEMBER(last_valid_gid) 0,
+
+	MEMBER(default_mail_env) NULL,
+	MEMBER(mail_cache_fields) "MessagePart",
+	MEMBER(mail_never_cache_fields) NULL,
+	MEMBER(mailbox_check_interval) 0,
+	MEMBER(mail_save_crlf) FALSE,
+	MEMBER(mail_read_mmaped) FALSE,
+	MEMBER(maildir_copy_with_hardlinks) FALSE,
+	MEMBER(maildir_check_content_changes) FALSE,
+	MEMBER(mbox_locks) "dotlock fcntl flock",
+	MEMBER(mbox_read_dotlock) FALSE,
+	MEMBER(mbox_lock_timeout) 300,
+	MEMBER(mbox_dotlock_change_timeout) 30,
+	MEMBER(overwrite_incompatible_index) FALSE,
+	MEMBER(umask) 0077,
+
+	/* imap */
+	MEMBER(imap_executable) PKG_LIBEXECDIR"/imap",
+	MEMBER(imap_process_size) 256,
+
+	/* pop3 */
+	MEMBER(pop3_executable) PKG_LIBEXECDIR"/pop3",
+	MEMBER(pop3_process_size) 256,
+
+	MEMBER(login_gid) 0,
+	MEMBER(auths) NULL,
+	MEMBER(logins) NULL
+};
+
+struct login_settings default_login_settings = {
+	MEMBER(next) NULL,
+	MEMBER(name) NULL,
+
+	MEMBER(executable) NULL,
+	MEMBER(user) "dovecot",
+
+	MEMBER(process_per_connection) TRUE,
+
+	MEMBER(process_size) 16,
+	MEMBER(processes_count) 3,
+	MEMBER(max_processes_count) 128,
+	MEMBER(max_logging_users) 256,
+
+	MEMBER(uid) 0 /* generated */
+};
+
+static pool_t settings_pool;
+struct settings *set = NULL;
+
+static void fix_base_path(struct settings *set, const char **str)
+{
+	if (*str != NULL && **str != '\0' && **str != '/') {
+		*str = p_strconcat(settings_pool,
+				   set->base_dir, "/", *str, NULL);
+	}
+}
+
+static void get_login_uid(struct settings *set,
+			  struct login_settings *login_set)
+{
+	struct passwd *pw;
+
+	if ((pw = getpwnam(login_set->user)) == NULL)
+		i_fatal("Login user doesn't exist: %s", login_set->user);
+
+	if (set->login_gid == 0)
+		set->login_gid = pw->pw_gid;
+	else if (set->login_gid != pw->pw_gid) {
+		i_fatal("All login process users must belong to same group "
+			"(%s vs %s)", dec2str(set->login_gid),
+			dec2str(pw->pw_gid));
+	}
+
+	login_set->uid = pw->pw_uid;
+}
+
+static void auth_settings_verify(struct auth_settings *auth)
+{
+	if (access(auth->executable, X_OK) < 0)
+		i_fatal("Can't use auth executable %s: %m", auth->executable);
+
+	fix_base_path(set, &auth->chroot);
+	if (auth->chroot != NULL && access(auth->chroot, X_OK) < 0) {
+		i_fatal("Can't access auth chroot directory %s: %m",
+			auth->chroot);
+	}
+}
+
+static void login_settings_verify(struct login_settings *login)
+{
+	if (access(login->executable, X_OK) < 0)
+		i_fatal("Can't use login executable %s: %m", login->executable);
+
+	if (login->processes_count < 1)
+		i_fatal("login_processes_count must be at least 1");
+	if (login->max_logging_users < 1)
+		i_fatal("max_logging_users must be at least 1");
+}
+
+static const char *get_directory(const char *path)
+{
+	char *str, *p;
+
+	str = t_strdup_noconst(path);
+	p = strrchr(str, '/');
+	if (p == NULL)
+		return ".";
+	else {
+		*p = '\0';
+		return str;
+	}
+}
+
+static void settings_verify(struct settings *set)
+{
+	struct login_settings *login;
+	struct auth_settings *auth;
+	const char *const *str;
+	const char *dir;
+	int dotlock_got, fcntl_got, flock_got;
+
+	for (login = set->logins; login != NULL; login = login->next) {
+		get_login_uid(set, login);
+		login_settings_verify(login);
+	}
+
+	if (strstr(set->protocols, "imap") != NULL) {
+		if (access(set->imap_executable, X_OK) < 0) {
+			i_fatal("Can't use imap executable %s: %m",
+				set->imap_executable);
+		}
+	}
+
+	if (strstr(set->protocols, "pop3") != NULL) {
+		if (access(set->pop3_executable, X_OK) < 0) {
+			i_fatal("Can't use pop3 executable %s: %m",
+				set->pop3_executable);
+		}
+	}
+
+	if (set->log_path != NULL) {
+		dir = get_directory(set->log_path);
+		if (access(dir, W_OK) < 0)
+			i_fatal("Can't access log directory %s: %m", dir);
+	}
+
+	if (set->info_log_path != NULL) {
+		dir = get_directory(set->info_log_path);
+		if (access(dir, W_OK) < 0)
+			i_fatal("Can't access info log directory %s: %m", dir);
+	}
+
+#ifdef HAVE_SSL
+	if (!set->ssl_disable) {
+		if (access(set->ssl_cert_file, R_OK) < 0) {
+			i_fatal("Can't use SSL certificate %s: %m",
+				set->ssl_cert_file);
+		}
+
+		if (access(set->ssl_key_file, R_OK) < 0) {
+			i_fatal("Can't use SSL key file %s: %m",
+				set->ssl_key_file);
+		}
+	}
+#endif
+
+	/* fix relative paths */
+	fix_base_path(set, &set->ssl_parameters_file);
+	fix_base_path(set, &set->login_dir);
+
+	/* since they're under /var/run by default, they may have been
+	   deleted. */
+	if (safe_mkdir(set->base_dir, 0700, geteuid(), getegid()) == 0) {
+		i_warning("Corrected permissions for base directory %s",
+			  PKG_RUNDIR);
+	}
+
+	/* wipe out contents of login directory, if it exists */
+	if (unlink_directory(set->login_dir, FALSE) < 0)
+		i_fatal("unlink_directory() failed for %s: %m", set->login_dir);
+
+	if (safe_mkdir(set->login_dir, 0750, geteuid(), set->login_gid) == 0) {
+		i_warning("Corrected permissions for login directory %s",
+			  set->login_dir);
+	}
+
+	if (set->max_mail_processes < 1)
+		i_fatal("max_mail_processes must be at least 1");
+
+	if (set->last_valid_uid != 0 &&
+	    set->first_valid_uid > set->last_valid_uid)
+		i_fatal("first_valid_uid can't be larger than last_valid_uid");
+	if (set->last_valid_gid != 0 &&
+	    set->first_valid_gid > set->last_valid_gid)
+		i_fatal("first_valid_gid can't be larger than last_valid_gid");
+
+	dotlock_got = fcntl_got = flock_got = FALSE;
+	for (str = t_strsplit(set->mbox_locks, " "); *str != NULL; str++) {
+		if (strcasecmp(*str, "dotlock") == 0)
+			dotlock_got = TRUE;
+		else if (strcasecmp(*str, "fcntl") == 0)
+			fcntl_got = TRUE;
+		else if (strcasecmp(*str, "flock") == 0)
+			flock_got = TRUE;
+		else
+			i_fatal("mbox_locks: Invalid value %s", *str);
+	}
+
+#ifndef HAVE_FLOCK
+	if (fcntl_got && !dotlock_got && !flock_got) {
+		i_fatal("mbox_locks: Only flock selected, "
+			"and flock() isn't supported in this system");
+	}
+	flock_got = FALSE;
+#endif
+
+	if (!dotlock_got && !fcntl_got && !flock_got)
+		i_fatal("mbox_locks: No mbox locking methods selected");
+
+	if (dotlock_got && !set->mbox_read_dotlock &&
+	    !fcntl_got && !flock_got) {
+		i_warning("mbox_locks: Only dotlock selected, forcing "
+			  "mbox_read_dotlock = yes to avoid corruption.");
+                set->mbox_read_dotlock = TRUE;
+	}
+
+	for (auth = set->auths; auth != NULL; auth = auth->next)
+		auth_settings_verify(auth);
+}
+
+static void auth_settings_new(struct settings *set, const char *name)
+{
+	struct auth_settings *auth;
+
+	auth = p_new(settings_pool, struct auth_settings, 1);
+	auth->name = p_strdup(settings_pool, name);
+	auth->executable = p_strdup(settings_pool,
+				    PKG_LIBEXECDIR"/dovecot-auth");
+	auth->count = 1;
+
+	auth->next = set->auths;
+        set->auths = auth;
+}
+
+static const char *parse_new_auth(struct settings *set, const char *name)
+{
+	struct auth_settings *auth;
+
+	if (strchr(name, '/') != NULL)
+		return "Authentication process name must not contain '/'";
+
+	for (auth = set->auths; auth != NULL; auth = auth->next) {
+		if (strcmp(auth->name, name) == 0) {
+			return "Authentication process already exists "
+				"with the same name";
+		}
+	}
+
+	auth_settings_new(set, name);
+	return NULL;
+}
+
+static void login_settings_new(struct settings *set, const char *name)
+{
+	struct login_settings *login;
+
+	login = p_new(settings_pool, struct login_settings, 1);
+
+	/* copy defaults */
+	*login = set->logins != NULL ? *set->logins :
+		default_login_settings;
+
+	if (strcasecmp(name, "imap") == 0) {
+		login->name = "imap";
+		login->executable = PKG_LIBEXECDIR"/imap-login";
+	} else if (strcasecmp(name, "pop3") == 0) {
+		login->name = "pop3";
+		login->executable = PKG_LIBEXECDIR"/pop3-login";
+	} else {
+		i_fatal("Unknown login process type '%s'", name);
+	}
+
+	login->next = set->logins;
+	set->logins = login;
+}
+
+static const char *parse_new_login(struct settings *set, const char *name)
+{
+	struct login_settings *login;
+
+	for (login = set->logins; login != NULL; login = login->next) {
+		if (strcmp(login->name, name) == 0) {
+			return "Login process already exists "
+				"with the same name";
+		}
+	}
+
+	login_settings_new(set, name);
+	return NULL;
+}
+
+static const char *parse_setting(const char *key, const char *value)
+{
+	if (strcmp(key, "auth") == 0)
+		return parse_new_auth(set, value);
+	if (strncmp(key, "auth_", 5) == 0) {
+		if (set->auths == NULL)
+			return "Authentication process name not defined yet";
+
+		return parse_setting_from_defs(settings_pool, auth_setting_defs,
+					       set->auths, key + 5, value);
+	}
+
+	if (strcmp(key, "login") == 0)
+		return parse_new_login(set, value);
+	if (strncmp(key, "login_", 6) == 0) {
+		if (set->logins == NULL)
+			return "Login process name not defined yet";
+
+		return parse_setting_from_defs(settings_pool,
+					       login_setting_defs,
+					       set->logins, key + 6, value);
+	}
+
+	return parse_setting_from_defs(settings_pool, setting_defs,
+				       set, key, value);
+}
+
+void master_settings_read(const char *path)
+{
+	p_clear(settings_pool);
+	set = p_new(settings_pool, struct settings, 1);
+	*set = default_settings;
+
+	settings_read(path, parse_setting);
+
+        settings_verify(set);
+}
+
+void master_settings_init(void)
+{
+	settings_pool = pool_alloconly_create("settings", 1024);
+}
+
+void master_settings_deinit(void)
+{
+	pool_unref(settings_pool);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/master/master-settings.h	Thu Jan 30 21:01:40 2003 +0200
@@ -0,0 +1,109 @@
+#ifndef __MASTER_SETTINGS_H
+#define __MASTER_SETTINGS_H
+
+struct settings {
+	/* common */
+	const char *base_dir;
+	const char *log_path;
+	const char *info_log_path;
+	const char *log_timestamp;
+
+	/* general */
+	const char *protocols;
+	const char *imap_listen;
+	const char *imaps_listen;
+	const char *pop3_listen;
+	const char *pop3s_listen;
+
+	int ssl_disable;
+	const char *ssl_cert_file;
+	const char *ssl_key_file;
+	const char *ssl_parameters_file;
+	unsigned int ssl_parameters_regenerate;
+	int disable_plaintext_auth;
+
+	/* login */
+	const char *login_dir;
+	int login_chroot;
+
+	/* mail */
+	const char *valid_chroot_dirs;
+	unsigned int max_mail_processes;
+	int verbose_proctitle;
+
+	unsigned int first_valid_uid, last_valid_uid;
+	unsigned int first_valid_gid, last_valid_gid;
+
+	const char *default_mail_env;
+	const char *mail_cache_fields;
+	const char *mail_never_cache_fields;
+	unsigned int mailbox_check_interval;
+	int mail_save_crlf;
+	int mail_read_mmaped;
+	int maildir_copy_with_hardlinks;
+	int maildir_check_content_changes;
+	char *mbox_locks;
+	int mbox_read_dotlock;
+	unsigned int mbox_lock_timeout;
+	unsigned int mbox_dotlock_change_timeout;
+	int overwrite_incompatible_index;
+	unsigned int umask;
+
+	/* imap */
+	const char *imap_executable;
+	unsigned int imap_process_size;
+
+	/* imap */
+	const char *pop3_executable;
+	unsigned int pop3_process_size;
+
+	/* .. */
+	gid_t login_gid;
+
+	struct auth_settings *auths;
+	struct login_settings *logins;
+};
+
+struct login_settings {
+	struct login_settings *next;
+
+	const char *name;
+	const char *executable;
+	const char *user;
+
+	int process_per_connection;
+
+	unsigned int process_size;
+	unsigned int processes_count;
+	unsigned int max_processes_count;
+	unsigned int max_logging_users;
+
+	uid_t uid; /* gid must be always same with all login processes */
+};
+
+struct auth_settings {
+	struct auth_settings *next;
+
+	const char *name;
+	const char *mechanisms;
+	const char *realms;
+	const char *userdb;
+	const char *passdb;
+	const char *executable;
+	const char *user;
+	const char *chroot;
+
+	int use_cyrus_sasl, verbose;
+
+	unsigned int count;
+	unsigned int process_size;
+};
+
+extern struct settings *set;
+
+void master_settings_read(const char *path);
+
+void master_settings_init(void);
+void master_settings_deinit(void);
+
+#endif
--- a/src/master/settings.c	Thu Jan 30 20:27:09 2003 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "istream.h"
-#include "safe-mkdir.h"
-#include "unlink-directory.h"
-#include "settings.h"
-
-#include <stdio.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pwd.h>
-
-enum setting_type {
-	SET_STR,
-	SET_INT,
-	SET_BOOL
-};
-
-struct setting_def {
-	enum setting_type type;
-	const char *name;
-	size_t offset;
-};
-
-#define DEF(type, name) \
-	{ type, #name, offsetof(struct settings, name) }
-
-static struct setting_def setting_defs[] = {
-	/* common */
-	DEF(SET_STR, base_dir),
-	DEF(SET_STR, log_path),
-	DEF(SET_STR, info_log_path),
-	DEF(SET_STR, log_timestamp),
-
-	/* general */
-	DEF(SET_STR, protocols),
-	DEF(SET_STR, imap_listen),
-	DEF(SET_STR, imaps_listen),
-	DEF(SET_STR, pop3_listen),
-	DEF(SET_STR, pop3s_listen),
-
-	DEF(SET_BOOL, ssl_disable),
-	DEF(SET_STR, ssl_cert_file),
-	DEF(SET_STR, ssl_key_file),
-	DEF(SET_STR, ssl_parameters_file),
-	DEF(SET_STR, ssl_parameters_regenerate),
-	DEF(SET_BOOL, disable_plaintext_auth),
-
-	/* login */
-	DEF(SET_STR, login_dir),
-	DEF(SET_BOOL, login_chroot),
-
-	/* mail */
-	DEF(SET_STR, valid_chroot_dirs),
-	DEF(SET_INT, max_mail_processes),
-	DEF(SET_BOOL, verbose_proctitle),
-
-	DEF(SET_INT, first_valid_uid),
-	DEF(SET_INT, last_valid_uid),
-	DEF(SET_INT, first_valid_gid),
-	DEF(SET_INT, last_valid_gid),
-
-	DEF(SET_STR, default_mail_env),
-	DEF(SET_STR, mail_cache_fields),
-	DEF(SET_STR, mail_never_cache_fields),
-	DEF(SET_STR, mailbox_check_interval),
-	DEF(SET_STR, mail_save_crlf),
-	DEF(SET_STR, mail_read_mmaped),
-	DEF(SET_STR, maildir_copy_with_hardlinks),
-	DEF(SET_STR, maildir_check_content_changes),
-	DEF(SET_STR, mbox_locks),
-	DEF(SET_STR, mbox_read_dotlock),
-	DEF(SET_STR, mbox_lock_timeout),
-	DEF(SET_STR, mbox_dotlock_change_timeout),
-	DEF(SET_STR, overwrite_incompatible_index),
-	DEF(SET_STR, umask),
-
-	/* imap */
-	DEF(SET_STR, imap_executable),
-	DEF(SET_INT, imap_process_size),
-
-	/* pop3 */
-	DEF(SET_STR, pop3_executable),
-	DEF(SET_INT, pop3_process_size),
-
-	{ 0, NULL, 0 }
-};
-
-#undef DEF
-#define DEF(type, name) \
-	{ type, #name, offsetof(struct login_settings, name) }
-
-static struct setting_def login_setting_defs[] = {
-	DEF(SET_STR, executable),
-	DEF(SET_STR, user),
-
-	DEF(SET_BOOL, process_per_connection),
-
-	DEF(SET_INT, process_size),
-	DEF(SET_INT, processes_count),
-	DEF(SET_INT, max_processes_count),
-	DEF(SET_INT, max_logging_users),
-
-	{ 0, NULL, 0 }
-};
-
-#undef DEF
-#define DEF(type, name) \
-	{ type, #name, offsetof(struct auth_settings, name) }
-
-static struct setting_def auth_setting_defs[] = {
-	DEF(SET_STR, mechanisms),
-	DEF(SET_STR, realms),
-	DEF(SET_STR, userdb),
-	DEF(SET_STR, passdb),
-	DEF(SET_STR, executable),
-	DEF(SET_STR, user),
-	DEF(SET_STR, chroot),
-
-	DEF(SET_BOOL, use_cyrus_sasl),
-	DEF(SET_BOOL, verbose),
-
-	DEF(SET_INT, count),
-	DEF(SET_INT, process_size),
-
-	{ 0, NULL, 0 }
-};
-
-struct settings default_settings = {
-	/* common */
-	MEMBER(base_dir) PKG_RUNDIR,
-	MEMBER(log_path) NULL,
-	MEMBER(info_log_path) NULL,
-	MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
-
-	/* general */
-	MEMBER(protocols) "imap imaps",
-	MEMBER(imap_listen) "*",
-	MEMBER(imaps_listen) NULL,
-	MEMBER(pop3_listen) "*",
-	MEMBER(pop3s_listen) NULL,
-
-	MEMBER(ssl_disable) FALSE,
-	MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
-	MEMBER(ssl_key_file) SSLDIR"/private/dovecot.pem",
-	MEMBER(ssl_parameters_file) "ssl-parameters.dat",
-	MEMBER(ssl_parameters_regenerate) 24,
-	MEMBER(disable_plaintext_auth) FALSE,
-
-	/* login */
-	MEMBER(login_dir) "login",
-	MEMBER(login_chroot) TRUE,
-
-	/* mail */
-	MEMBER(valid_chroot_dirs) NULL,
-	MEMBER(max_mail_processes) 1024,
-	MEMBER(verbose_proctitle) FALSE,
-
-	MEMBER(first_valid_uid) 500,
-	MEMBER(last_valid_uid) 0,
-	MEMBER(first_valid_gid) 1,
-	MEMBER(last_valid_gid) 0,
-
-	MEMBER(default_mail_env) NULL,
-	MEMBER(mail_cache_fields) "MessagePart",
-	MEMBER(mail_never_cache_fields) NULL,
-	MEMBER(mailbox_check_interval) 0,
-	MEMBER(mail_save_crlf) FALSE,
-	MEMBER(mail_read_mmaped) FALSE,
-	MEMBER(maildir_copy_with_hardlinks) FALSE,
-	MEMBER(maildir_check_content_changes) FALSE,
-	MEMBER(mbox_locks) "dotlock fcntl flock",
-	MEMBER(mbox_read_dotlock) FALSE,
-	MEMBER(mbox_lock_timeout) 300,
-	MEMBER(mbox_dotlock_change_timeout) 30,
-	MEMBER(overwrite_incompatible_index) FALSE,
-	MEMBER(umask) 0077,
-
-	/* imap */
-	MEMBER(imap_executable) PKG_LIBEXECDIR"/imap",
-	MEMBER(imap_process_size) 256,
-
-	/* pop3 */
-	MEMBER(pop3_executable) PKG_LIBEXECDIR"/pop3",
-	MEMBER(pop3_process_size) 256,
-
-	MEMBER(login_gid) 0,
-	MEMBER(auths) NULL,
-	MEMBER(logins) NULL
-};
-
-struct login_settings default_login_settings = {
-	MEMBER(next) NULL,
-	MEMBER(name) NULL,
-
-	MEMBER(executable) NULL,
-	MEMBER(user) "dovecot",
-
-	MEMBER(process_per_connection) TRUE,
-
-	MEMBER(process_size) 16,
-	MEMBER(processes_count) 3,
-	MEMBER(max_processes_count) 128,
-	MEMBER(max_logging_users) 256,
-
-	MEMBER(uid) 0 /* generated */
-};
-
-static pool_t settings_pool;
-struct settings *set = NULL;
-
-static void fix_base_path(struct settings *set, const char **str)
-{
-	if (*str != NULL && **str != '\0' && **str != '/') {
-		*str = p_strconcat(settings_pool,
-				   set->base_dir, "/", *str, NULL);
-	}
-}
-
-static void get_login_uid(struct settings *set,
-			  struct login_settings *login_set)
-{
-	struct passwd *pw;
-
-	if ((pw = getpwnam(login_set->user)) == NULL)
-		i_fatal("Login user doesn't exist: %s", login_set->user);
-
-	if (set->login_gid == 0)
-		set->login_gid = pw->pw_gid;
-	else if (set->login_gid != pw->pw_gid) {
-		i_fatal("All login process users must belong to same group "
-			"(%s vs %s)", dec2str(set->login_gid),
-			dec2str(pw->pw_gid));
-	}
-
-	login_set->uid = pw->pw_uid;
-}
-
-static const char *get_bool(const char *value, int *result)
-{
-	if (strcasecmp(value, "yes") == 0)
-		*result = TRUE;
-	else if (strcasecmp(value, "no") == 0)
-		*result = FALSE;
-	else
-		return t_strconcat("Invalid boolean: ", value, NULL);
-
-	return NULL;
-}
-
-static const char *get_uint(const char *value, unsigned int *result)
-{
-	int num;
-
-	if (!sscanf(value, "%i", &num) || num < 0)
-		return t_strconcat("Invalid number: ", value, NULL);
-	*result = num;
-	return NULL;
-}
-
-static void auth_settings_verify(struct auth_settings *auth)
-{
-	if (access(auth->executable, X_OK) < 0)
-		i_fatal("Can't use auth executable %s: %m", auth->executable);
-
-	fix_base_path(set, &auth->chroot);
-	if (auth->chroot != NULL && access(auth->chroot, X_OK) < 0) {
-		i_fatal("Can't access auth chroot directory %s: %m",
-			auth->chroot);
-	}
-}
-
-static void login_settings_verify(struct login_settings *login)
-{
-	if (access(login->executable, X_OK) < 0)
-		i_fatal("Can't use login executable %s: %m", login->executable);
-
-	if (login->processes_count < 1)
-		i_fatal("login_processes_count must be at least 1");
-	if (login->max_logging_users < 1)
-		i_fatal("max_logging_users must be at least 1");
-}
-
-static const char *get_directory(const char *path)
-{
-	char *str, *p;
-
-	str = t_strdup_noconst(path);
-	p = strrchr(str, '/');
-	if (p == NULL)
-		return ".";
-	else {
-		*p = '\0';
-		return str;
-	}
-}
-
-static void settings_verify(struct settings *set)
-{
-	struct login_settings *login;
-	struct auth_settings *auth;
-	const char *const *str;
-	const char *dir;
-	int dotlock_got, fcntl_got, flock_got;
-
-	for (login = set->logins; login != NULL; login = login->next) {
-		get_login_uid(set, login);
-		login_settings_verify(login);
-	}
-
-	if (strstr(set->protocols, "imap") != NULL) {
-		if (access(set->imap_executable, X_OK) < 0) {
-			i_fatal("Can't use imap executable %s: %m",
-				set->imap_executable);
-		}
-	}
-
-	if (strstr(set->protocols, "pop3") != NULL) {
-		if (access(set->pop3_executable, X_OK) < 0) {
-			i_fatal("Can't use pop3 executable %s: %m",
-				set->pop3_executable);
-		}
-	}
-
-	if (set->log_path != NULL) {
-		dir = get_directory(set->log_path);
-		if (access(dir, W_OK) < 0)
-			i_fatal("Can't access log directory %s: %m", dir);
-	}
-
-	if (set->info_log_path != NULL) {
-		dir = get_directory(set->info_log_path);
-		if (access(dir, W_OK) < 0)
-			i_fatal("Can't access info log directory %s: %m", dir);
-	}
-
-#ifdef HAVE_SSL
-	if (!set->ssl_disable) {
-		if (access(set->ssl_cert_file, R_OK) < 0) {
-			i_fatal("Can't use SSL certificate %s: %m",
-				set->ssl_cert_file);
-		}
-
-		if (access(set->ssl_key_file, R_OK) < 0) {
-			i_fatal("Can't use SSL key file %s: %m",
-				set->ssl_key_file);
-		}
-	}
-#endif
-
-	/* fix relative paths */
-	fix_base_path(set, &set->ssl_parameters_file);
-	fix_base_path(set, &set->login_dir);
-
-	/* since they're under /var/run by default, they may have been
-	   deleted. */
-	if (safe_mkdir(set->base_dir, 0700, geteuid(), getegid()) == 0) {
-		i_warning("Corrected permissions for base directory %s",
-			  PKG_RUNDIR);
-	}
-
-	/* wipe out contents of login directory, if it exists */
-	if (unlink_directory(set->login_dir, FALSE) < 0)
-		i_fatal("unlink_directory() failed for %s: %m", set->login_dir);
-
-	if (safe_mkdir(set->login_dir, 0750, geteuid(), set->login_gid) == 0) {
-		i_warning("Corrected permissions for login directory %s",
-			  set->login_dir);
-	}
-
-	if (set->max_mail_processes < 1)
-		i_fatal("max_mail_processes must be at least 1");
-
-	if (set->last_valid_uid != 0 &&
-	    set->first_valid_uid > set->last_valid_uid)
-		i_fatal("first_valid_uid can't be larger than last_valid_uid");
-	if (set->last_valid_gid != 0 &&
-	    set->first_valid_gid > set->last_valid_gid)
-		i_fatal("first_valid_gid can't be larger than last_valid_gid");
-
-	dotlock_got = fcntl_got = flock_got = FALSE;
-	for (str = t_strsplit(set->mbox_locks, " "); *str != NULL; str++) {
-		if (strcasecmp(*str, "dotlock") == 0)
-			dotlock_got = TRUE;
-		else if (strcasecmp(*str, "fcntl") == 0)
-			fcntl_got = TRUE;
-		else if (strcasecmp(*str, "flock") == 0)
-			flock_got = TRUE;
-		else
-			i_fatal("mbox_locks: Invalid value %s", *str);
-	}
-
-#ifndef HAVE_FLOCK
-	if (fcntl_got && !dotlock_got && !flock_got) {
-		i_fatal("mbox_locks: Only flock selected, "
-			"and flock() isn't supported in this system");
-	}
-	flock_got = FALSE;
-#endif
-
-	if (!dotlock_got && !fcntl_got && !flock_got)
-		i_fatal("mbox_locks: No mbox locking methods selected");
-
-	if (dotlock_got && !set->mbox_read_dotlock &&
-	    !fcntl_got && !flock_got) {
-		i_warning("mbox_locks: Only dotlock selected, forcing "
-			  "mbox_read_dotlock = yes to avoid corruption.");
-                set->mbox_read_dotlock = TRUE;
-	}
-
-	for (auth = set->auths; auth != NULL; auth = auth->next)
-		auth_settings_verify(auth);
-}
-
-static void auth_settings_new(struct settings *set, const char *name)
-{
-	struct auth_settings *auth;
-
-	auth = p_new(settings_pool, struct auth_settings, 1);
-	auth->name = p_strdup(settings_pool, name);
-	auth->executable = p_strdup(settings_pool,
-				    PKG_LIBEXECDIR"/dovecot-auth");
-	auth->count = 1;
-
-	auth->next = set->auths;
-        set->auths = auth;
-}
-
-static const char *parse_new_auth(struct settings *set, const char *name)
-{
-	struct auth_settings *auth;
-
-	if (strchr(name, '/') != NULL)
-		return "Authentication process name must not contain '/'";
-
-	for (auth = set->auths; auth != NULL; auth = auth->next) {
-		if (strcmp(auth->name, name) == 0) {
-			return "Authentication process already exists "
-				"with the same name";
-		}
-	}
-
-	auth_settings_new(set, name);
-	return NULL;
-}
-
-static void login_settings_new(struct settings *set, const char *name)
-{
-	struct login_settings *login;
-
-	login = p_new(settings_pool, struct login_settings, 1);
-
-	/* copy defaults */
-	*login = set->logins != NULL ? *set->logins :
-		default_login_settings;
-
-	if (strcasecmp(name, "imap") == 0) {
-		login->name = "imap";
-		login->executable = PKG_LIBEXECDIR"/imap-login";
-	} else if (strcasecmp(name, "pop3") == 0) {
-		login->name = "pop3";
-		login->executable = PKG_LIBEXECDIR"/pop3-login";
-	} else {
-		i_fatal("Unknown login process type '%s'", name);
-	}
-
-	login->next = set->logins;
-	set->logins = login;
-}
-
-static const char *parse_new_login(struct settings *set, const char *name)
-{
-	struct login_settings *login;
-
-	for (login = set->logins; login != NULL; login = login->next) {
-		if (strcmp(login->name, name) == 0) {
-			return "Login process already exists "
-				"with the same name";
-		}
-	}
-
-	login_settings_new(set, name);
-	return NULL;
-}
-
-static const char *
-parse_setting_from_defs(struct setting_def *defs, void *base,
-			const char *key, const char *value)
-{
-	struct setting_def *def;
-
-	for (def = defs; def->name != NULL; def++) {
-		if (strcmp(def->name, key) == 0) {
-			void *ptr = STRUCT_MEMBER_P(base, def->offset);
-
-			switch (def->type) {
-			case SET_STR:
-				*((char **) ptr) =
-					p_strdup_empty(settings_pool, value);
-				return NULL;
-			case SET_INT:
-				/* use %i so we can handle eg. 0600
-				   as octal value with umasks */
-				return get_uint(value, (unsigned int *) ptr);
-			case SET_BOOL:
-				return get_bool(value, (int *) ptr);
-			}
-		}
-	}
-
-	return t_strconcat("Unknown setting: ", key, NULL);
-}
-
-static const char *parse_setting(struct settings *set,
-				 const char *key, const char *value)
-{
-	if (strcmp(key, "auth") == 0)
-		return parse_new_auth(set, value);
-	if (strncmp(key, "auth_", 5) == 0) {
-		if (set->auths == NULL)
-			return "Authentication process name not defined yet";
-
-		return parse_setting_from_defs(auth_setting_defs,
-					       set->auths, key + 5, value);
-	}
-
-	if (strcmp(key, "login") == 0)
-		return parse_new_login(set, value);
-	if (strncmp(key, "login_", 6) == 0) {
-		if (set->logins == NULL)
-			return "Login process name not defined yet";
-
-		return parse_setting_from_defs(login_setting_defs,
-					       set->logins, key + 6, value);
-	}
-
-	return parse_setting_from_defs(setting_defs, set, key, value);
-}
-
-#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
-
-void settings_read(const char *path)
-{
-	struct istream *input;
-	const char *errormsg;
-	char *line, *key, *p;
-	int fd, linenum;
-
-	p_clear(settings_pool);
-	set = p_new(settings_pool, struct settings, 1);
-	*set = default_settings;
-
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		i_fatal("Can't open configuration file %s: %m", path);
-
-	linenum = 0;
-	input = i_stream_create_file(fd, default_pool, 2048, TRUE);
-	for (;;) {
-		line = i_stream_next_line(input);
-		if (line == NULL) {
-			if (i_stream_read(input) <= 0)
-				break;
-                        continue;
-		}
-		linenum++;
-
-		/* @UNSAFE: line is modified */
-
-		/* skip whitespace */
-		while (IS_WHITE(*line))
-			line++;
-
-		/* ignore comments or empty lines */
-		if (*line == '#' || *line == '\0')
-			continue;
-
-		/* all lines must be in format "key = value" */
-		key = line;
-		while (!IS_WHITE(*line) && *line != '\0')
-			line++;
-		if (IS_WHITE(*line)) {
-			*line++ = '\0';
-			while (IS_WHITE(*line)) line++;
-		}
-
-		if (*line != '=') {
-			errormsg = "Missing value";
-		} else {
-			/* skip whitespace after '=' */
-			*line++ = '\0';
-			while (IS_WHITE(*line)) line++;
-
-			/* skip trailing whitespace */
-			p = line + strlen(line);
-			while (p > line && IS_WHITE(p[-1]))
-				p--;
-			*p = '\0';
-
-			errormsg = parse_setting(set, key, line);
-		}
-
-		if (errormsg != NULL) {
-			i_fatal("Error in configuration file %s line %d: %s",
-				path, linenum, errormsg);
-		}
-	};
-
-	i_stream_unref(input);
-
-        settings_verify(set);
-}
-
-void settings_init(void)
-{
-	settings_pool = pool_alloconly_create("settings", 1024);
-}
--- a/src/master/settings.h	Thu Jan 30 20:27:09 2003 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-#ifndef __SETTINGS_H
-#define __SETTINGS_H
-
-struct settings {
-	/* common */
-	const char *base_dir;
-	const char *log_path;
-	const char *info_log_path;
-	const char *log_timestamp;
-
-	/* general */
-	const char *protocols;
-	const char *imap_listen;
-	const char *imaps_listen;
-	const char *pop3_listen;
-	const char *pop3s_listen;
-
-	int ssl_disable;
-	const char *ssl_cert_file;
-	const char *ssl_key_file;
-	const char *ssl_parameters_file;
-	unsigned int ssl_parameters_regenerate;
-	int disable_plaintext_auth;
-
-	/* login */
-	const char *login_dir;
-	int login_chroot;
-
-	/* mail */
-	const char *valid_chroot_dirs;
-	unsigned int max_mail_processes;
-	int verbose_proctitle;
-
-	unsigned int first_valid_uid, last_valid_uid;
-	unsigned int first_valid_gid, last_valid_gid;
-
-	const char *default_mail_env;
-	const char *mail_cache_fields;
-	const char *mail_never_cache_fields;
-	unsigned int mailbox_check_interval;
-	int mail_save_crlf;
-	int mail_read_mmaped;
-	int maildir_copy_with_hardlinks;
-	int maildir_check_content_changes;
-	char *mbox_locks;
-	int mbox_read_dotlock;
-	unsigned int mbox_lock_timeout;
-	unsigned int mbox_dotlock_change_timeout;
-	int overwrite_incompatible_index;
-	unsigned int umask;
-
-	/* imap */
-	const char *imap_executable;
-	unsigned int imap_process_size;
-
-	/* imap */
-	const char *pop3_executable;
-	unsigned int pop3_process_size;
-
-	/* .. */
-	gid_t login_gid;
-
-	struct auth_settings *auths;
-	struct login_settings *logins;
-};
-
-struct login_settings {
-	struct login_settings *next;
-
-	const char *name;
-	const char *executable;
-	const char *user;
-
-	int process_per_connection;
-
-	unsigned int process_size;
-	unsigned int processes_count;
-	unsigned int max_processes_count;
-	unsigned int max_logging_users;
-
-	uid_t uid; /* gid must be always same with all login processes */
-};
-
-struct auth_settings {
-	struct auth_settings *next;
-
-	const char *name;
-	const char *mechanisms;
-	const char *realms;
-	const char *userdb;
-	const char *passdb;
-	const char *executable;
-	const char *user;
-	const char *chroot;
-
-	int use_cyrus_sasl, verbose;
-
-	unsigned int count;
-	unsigned int process_size;
-};
-
-extern struct settings *set;
-
-void settings_read(const char *path);
-
-void settings_init(void);
-
-#endif