]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added lib-master and mail-storage-service code that makes it easier to build new...
authorTimo Sirainen <tss@iki.fi>
Fri, 10 Apr 2009 00:24:51 +0000 (20:24 -0400)
committerTimo Sirainen <tss@iki.fi>
Fri, 10 Apr 2009 00:24:51 +0000 (20:24 -0400)
Currently only the standalone applications (e.g. deliver) uses this.

--HG--
branch : HEAD

50 files changed:
configure.in
src/Makefile.am
src/deliver/Makefile.am
src/deliver/deliver-settings.c
src/deliver/deliver-settings.h
src/deliver/deliver.c
src/deliver/deliver.h
src/deliver/smtp-client.c
src/dict/main.c
src/imap/Makefile.am
src/imap/imap-settings.c
src/imap/imap-settings.h
src/imap/main.c
src/lib-auth/auth-master.h
src/lib-dovecot/Makefile.am
src/lib-master/Makefile.am [new file with mode: 0644]
src/lib-master/master-service-private.h [new file with mode: 0644]
src/lib-master/master-service-settings.c [new file with mode: 0644]
src/lib-master/master-service-settings.h [new file with mode: 0644]
src/lib-master/master-service.c [new file with mode: 0644]
src/lib-master/master-service.h [new file with mode: 0644]
src/lib-master/syslog-util.c [new file with mode: 0644]
src/lib-master/syslog-util.h [new file with mode: 0644]
src/lib-settings/settings-parser.c
src/lib-settings/settings-parser.h
src/lib-sql/Makefile.am
src/lib-storage/Makefile.am
src/lib-storage/mail-namespace.c
src/lib-storage/mail-storage-service.c [new file with mode: 0644]
src/lib-storage/mail-storage-service.h [new file with mode: 0644]
src/lib-storage/mail-storage-settings.c
src/lib-storage/mail-storage-settings.h
src/lib-storage/mail-user.c
src/lib-storage/mail-user.h
src/master/Makefile.am
src/master/child-process.c
src/plugins/convert/Makefile.am
src/plugins/convert/convert-settings.c [deleted file]
src/plugins/convert/convert-settings.h [deleted file]
src/plugins/convert/convert-tool.c
src/plugins/expire/Makefile.am
src/plugins/expire/auth-client.c
src/plugins/expire/expire-settings.c [deleted file]
src/plugins/expire/expire-settings.h [deleted file]
src/plugins/expire/expire-tool.c
src/pop3/Makefile.am
src/pop3/main.c
src/pop3/pop3-settings.c
src/pop3/pop3-settings.h
src/util/Makefile.am

index 3750e44db547e71575f3259b7538d0dc94fc317f..f37af3b13ab4dcb64285a2729f192da1fe3af7e0 100644 (file)
@@ -2380,6 +2380,7 @@ src/lib-dict/Makefile
 src/lib-imap/Makefile
 src/lib-index/Makefile
 src/lib-mail/Makefile
+src/lib-master/Makefile
 src/lib-ntlm/Makefile
 src/lib-otp/Makefile
 src/lib-dovecot/Makefile
index a4e52731afa71a7fc49e10802291bd69bd538719..89915e27491e3ec1658441eb29d14328e87dfe6e 100644 (file)
@@ -12,6 +12,7 @@ LIBDOVECOT_SUBDIRS = \
        lib-charset \
        lib-mail \
        lib-imap \
+       lib-master \
        lib-dict \
        lib-settings
 
@@ -24,7 +25,6 @@ SUBDIRS = \
        lib-ntlm \
        lib-otp \
        auth \
-       config \
        dict \
        master \
        login-common \
@@ -32,6 +32,7 @@ SUBDIRS = \
        imap \
        $(POP3D) \
        $(DELIVER) \
+       config \
        tests \
        util \
        plugins
index 3a727abbc50fa4c1c84a89d02ab5d9df2c5a4bb5..c3d2d0add55203b2078d94d40c5412f102f482cc 100644 (file)
@@ -4,20 +4,15 @@ pkglibexec_PROGRAMS = deliver
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
-       -I$(top_srcdir)/src/lib-auth \
        -I$(top_srcdir)/src/lib-settings \
-       -I$(top_srcdir)/src/lib-dict \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-index \
-       -I$(top_srcdir)/src/lib-settings \
+       -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-storage \
        -I$(top_srcdir)/src/lib-storage/index \
        -I$(top_srcdir)/src/lib-storage/index/raw \
-       -DBINDIR=\""$(bindir)"\" \
-       -DSYSCONFDIR=\""$(sysconfdir)"\" \
-       -DPKG_RUNDIR=\""$(rundir)"\" \
-       -DMODULEDIR=\""$(moduledir)"\"
+       -DPKG_RUNDIR=\""$(rundir)"\"
 
 deliver_LDFLAGS = -export-dynamic
 
@@ -30,7 +25,6 @@ deliver_LDADD = $(libs)
 deliver_DEPENDENCIES = $(libs)
 
 deliver_SOURCES = \
-       auth-client.c \
        deliver.c \
        deliver-settings.c \
        duplicate.c \
@@ -38,7 +32,6 @@ deliver_SOURCES = \
        smtp-client.c
 
 headers = \
-       auth-client.h \
        deliver.h \
        deliver-settings.h \
        duplicate.h \
index ea74a3e968a2c6a10e79fce7024b6f2c8915d640..858008f87d665536bbd9fd1db6a8d0158e9106fd 100644 (file)
@@ -11,6 +11,8 @@
 #include <stddef.h>
 #include <stdlib.h>
 
+static bool deliver_settings_check(void *_set, pool_t pool, const char **error_r);
+
 #undef DEF
 #undef DEFLIST
 #define DEF(type, name) \
        { SET_DEFLIST, name, offsetof(struct deliver_settings, field), defines }
 
 static struct setting_define deliver_setting_defines[] = {
-       DEF(SET_STR, base_dir),
-       DEF(SET_STR, log_path),
-       DEF(SET_STR, info_log_path),
-       DEF(SET_STR, log_timestamp),
-       DEF(SET_STR, syslog_facility),
-       DEF(SET_BOOL, version_ignore),
-
-       DEF(SET_STR, mail_plugins),
-       DEF(SET_STR, mail_plugin_dir),
-
-       DEF(SET_STR, mail_uid),
-       DEF(SET_STR, mail_gid),
-       DEF(SET_STR, mail_chroot),
-       DEF(SET_STR, mail_access_groups),
-
        DEF(SET_STR, postmaster_address),
        DEF(SET_STR, hostname),
        DEF(SET_STR, sendmail_path),
        DEF(SET_STR, rejection_subject),
        DEF(SET_STR, rejection_reason),
-       DEF(SET_STR, auth_socket_path),
        DEF(SET_STR, deliver_log_format),
        DEF(SET_BOOL, quota_full_tempfail),
 
@@ -49,28 +35,12 @@ static struct setting_define deliver_setting_defines[] = {
 };
 
 static struct deliver_settings deliver_default_settings = {
-       MEMBER(base_dir) PKG_RUNDIR,
-       MEMBER(log_path) "",
-       MEMBER(info_log_path) "",
-       MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
-       MEMBER(syslog_facility) "mail",
-       MEMBER(version_ignore) FALSE,
-
-       MEMBER(mail_plugins) "",
-       MEMBER(mail_plugin_dir) MODULEDIR,
-
-       MEMBER(mail_uid) "",
-       MEMBER(mail_gid) "",
-       MEMBER(mail_chroot) "",
-       MEMBER(mail_access_groups) "",
-
        MEMBER(postmaster_address) "",
        MEMBER(hostname) "",
        MEMBER(sendmail_path) "/usr/lib/sendmail",
        MEMBER(rejection_subject) "Rejected: %s",
        MEMBER(rejection_reason)
                "Your message to <%t> was automatically rejected:%n%r",
-       MEMBER(auth_socket_path) "auth-master",
        MEMBER(deliver_log_format) "msgid=%m: %$",
        MEMBER(quota_full_tempfail) FALSE
 };
@@ -84,82 +54,22 @@ struct setting_parser_info deliver_setting_parser_info = {
 
        MEMBER(parent_offset) (size_t)-1,
        MEMBER(type_offset) (size_t)-1,
-       MEMBER(struct_size) sizeof(struct deliver_settings)
+       MEMBER(struct_size) sizeof(struct deliver_settings),
+#ifdef CONFIG_BINARY
+       MEMBER(check_func) NULL
+#else
+       MEMBER(check_func) deliver_settings_check
+#endif
 };
 
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct deliver_settings *set, const char **str)
-{
-       if (*str != NULL && **str != '\0' && **str != '/') {
-               *str = p_strconcat(settings_pool,
-                                  set->base_dir, "/", *str, NULL);
-       }
-}
-
-struct setting_parser_context *
-deliver_settings_read(struct deliver_settings **set_r,
-                     struct mail_user_settings **user_set_r)
+static bool deliver_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+                                  const char **error_r)
 {
-       static const struct setting_parser_info *roots[] = {
-                &deliver_setting_parser_info,
-                &mail_user_setting_parser_info
-       };
-       void **sets;
-       struct deliver_settings *deliver_set;
-       struct setting_parser_context *parser;
-
-       if (settings_pool == NULL)
-               settings_pool = pool_alloconly_create("deliver settings", 1024);
-       else
-               p_clear(settings_pool);
+       struct deliver_settings *set = _set;
 
-       mail_storage_namespace_defines_init(settings_pool);
-
-       parser = settings_parser_init_list(settings_pool,
-                               roots, N_ELEMENTS(roots),
-                               SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
-       if (settings_parse_environ(parser) < 0) {
-               i_fatal_status(EX_CONFIG, "Error reading configuration: %s",
-                              settings_parser_get_error(parser));
-       }
-
-       sets = settings_parser_get_list(parser);
-
-       deliver_set = sets[0];
-       if (*deliver_set->hostname == '\0')
-               deliver_set->hostname = my_hostname;
-       fix_base_path(deliver_set, &deliver_set->auth_socket_path);
-
-       if (*deliver_set->postmaster_address == '\0') {
-               i_fatal_status(EX_CONFIG,
-                              "postmaster_address setting not given");
+       if (*set->postmaster_address == '\0') {
+               *error_r = "postmaster_address setting not given";
+               return FALSE;
        }
-
-       *set_r = deliver_set;
-       *user_set_r = sets[1];
-       return parser;
-}
-
-void deliver_settings_add(struct setting_parser_context *parser,
-                         const ARRAY_TYPE(const_string) *extra_fields)
-{
-       const char *const *str, *p, *line;
-       unsigned int i, count;
-
-       str = array_get(extra_fields, &count);
-       for (i = 0; i < count; i++) T_BEGIN {
-               p = strchr(str[i], '=');
-               if (p != NULL)
-                       line = str[i];
-               else
-                       line = t_strconcat(str[i], "=yes", NULL);
-               if (settings_parse_line(parser, str[i]) < 0) {
-                       i_fatal_status(EX_CONFIG,
-                                      "Invalid userdb input '%s': %s", str[i],
-                                      settings_parser_get_error(parser));
-               }
-       } T_END;
-
+       return TRUE;
 }
index 998a8591427a147a2f0aa045f2acde085a127cd6..92a8d50fa305f891b5f70cbeda25b8bd43b13c72 100644 (file)
@@ -4,38 +4,17 @@
 struct mail_user_settings;
 
 struct deliver_settings {
-       const char *base_dir;
-       const char *log_path;
-       const char *info_log_path;
-       const char *log_timestamp;
-       const char *syslog_facility;
-       bool version_ignore;
-
-       const char *mail_plugins;
-       const char *mail_plugin_dir;
-
-       const char *mail_uid;
-       const char *mail_gid;
-       const char *mail_chroot;
-       const char *mail_access_groups;
-
-       /* deliver: */
        const char *postmaster_address;
        const char *hostname;
        const char *sendmail_path;
        const char *rejection_subject;
        const char *rejection_reason;
-       const char *auth_socket_path;
        const char *deliver_log_format;
        bool quota_full_tempfail;
 
        ARRAY_DEFINE(plugin_envs, const char *);
 };
 
-struct setting_parser_context *
-deliver_settings_read(struct deliver_settings **set_r,
-                     struct mail_user_settings **user_set_r);
-void deliver_settings_add(struct setting_parser_context *parser,
-                         const ARRAY_TYPE(const_string) *extra_fields);
+extern struct setting_parser_info deliver_setting_parser_info;
 
 #endif
index 0a121002505c656fee519fdd80bdffc0e8ac25b5..b58580e9759b01fe61e7840ec3597a5c03e5d045 100644 (file)
@@ -1,49 +1,32 @@
 /* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
 
-/* This is getting pretty horrible. Especially the config file parsing.
-   Dovecot v2.0 should have a config file handling process which should help
-   with this.. */
-
 #include "lib.h"
 #include "lib-signals.h"
-#include "file-lock.h"
-#include "array.h"
 #include "ioloop.h"
-#include "hostpid.h"
-#include "home-expand.h"
 #include "env-util.h"
 #include "fd-set-nonblock.h"
 #include "istream.h"
 #include "istream-seekable.h"
-#include "module-dir.h"
 #include "str.h"
 #include "str-sanitize.h"
 #include "strescape.h"
 #include "var-expand.h"
 #include "rfc822-parser.h"
 #include "message-address.h"
+#include "imap-utf7.h"
+#include "master-service.h"
+#include "mail-storage-service.h"
 #include "mail-namespace.h"
 #include "raw-storage.h"
-#include "imap-utf7.h"
-#include "settings-parser.h"
-#include "dict.h"
-#include "auth-client.h"
 #include "mail-send.h"
 #include "duplicate.h"
 #include "mbox-from.h"
-#include "../master/syslog-util.h"
-#include "../master/syslog-util.c" /* ugly, ugly.. */
 #include "deliver.h"
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <pwd.h>
-#include <syslog.h>
 
-#define DEFAULT_CONFIG_FILE SYSCONFDIR"/dovecot.conf"
-#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
 #define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
 
 /* After buffer grows larger than this, create a temporary file to /tmp
@@ -55,7 +38,7 @@ static const char *wanted_headers[] = {
        NULL
 };
 
-struct deliver_settings *deliver_set;
+const struct deliver_settings *deliver_set;
 deliver_mail_func_t *deliver_mail = NULL;
 bool mailbox_autosubscribe;
 bool mailbox_autocreate;
@@ -66,21 +49,7 @@ static const char *default_mailbox_name = NULL;
 static bool saved_mail = FALSE;
 static char *explicit_envelope_sender = NULL;
 
-static struct module *modules;
-static struct ioloop *ioloop;
-
-static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
-{
-       /* warn about being killed because of some signal, except SIGINT (^C)
-          which is too common at least while testing :) */
-       if (si->si_signo != SIGINT) {
-               i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
-                         si->si_signo, dec2str(si->si_pid),
-                         dec2str(si->si_uid),
-                         lib_signal_code_to_str(si->si_signo, si->si_code));
-       }
-       io_loop_stop(current_ioloop);
-}
+static struct master_service *service;
 
 static const char *deliver_get_address(struct mail *mail, const char *header)
 {
@@ -402,32 +371,6 @@ static void failure_exit_callback(int *status)
        *status = EX_TEMPFAIL;
 }
 
-static void open_logfile(const char *username)
-{
-       const char *prefix, *log_path;
-
-       prefix = t_strdup_printf("deliver(%s): ", username);
-       log_path = home_expand(deliver_set->log_path);
-       if (*log_path == '\0') {
-               int facility;
-
-               if (!syslog_facility_find(deliver_set->syslog_facility,
-                                         &facility))
-                       facility = LOG_MAIL;
-               i_set_failure_prefix(prefix);
-               i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
-       } else {
-               /* log to file or stderr */
-               i_set_failure_file(log_path, prefix);
-       }
-
-       log_path = home_expand(deliver_set->info_log_path);
-       if (*log_path != '\0')
-               i_set_info_file(log_path);
-
-       i_set_failure_timestamp_format(deliver_set->log_timestamp);
-}
-
 static void print_help(void)
 {
        printf(
@@ -435,51 +378,11 @@ static void print_help(void)
 "               [-f <envelope sender>] [-m <mailbox>] [-n] [-s] [-e] [-k]\n");
 }
 
-void deliver_env_clean(bool preserve_home)
-{
-       const char *tz, *home;
-
-       tz = getenv("TZ");
-       if (tz != NULL)
-               tz = t_strconcat("TZ=", tz, NULL);
-       home = preserve_home ? getenv("HOME") : NULL;
-       if (home != NULL)
-               home = t_strconcat("HOME=", home, NULL);
-
-       /* Note that if the original environment was set with env_put(), the
-          environment strings will be invalid after env_clean(). That's why
-          we t_strconcat() them above. */
-       env_clean();
-
-       if (tz != NULL) env_put(tz);
-       if (home != NULL) env_put(home);
-}
-
-static void plugin_get_home(void)
-{
-       const char *const *envs;
-       unsigned int i, count;
-
-       /* kludgy. this should be removed some day, but for now don't break
-          existing setups that rely on it. */
-       if (array_is_created(&deliver_set->plugin_envs)) {
-               envs = array_get(&deliver_set->plugin_envs, &count);
-               for (i = 0; i < count; i++) {
-                       if (strncmp(envs[i], "home=", 5) == 0) {
-                               env_put(t_strconcat("HOME=", envs[i]+5, NULL));
-                               break;
-                       }
-               }
-       }
-}
-
 int main(int argc, char *argv[])
 {
-       const char *config_path = DEFAULT_CONFIG_FILE;
+       enum mail_storage_service_flags service_flags = 0;
        const char *mailbox = "INBOX";
-       const char *home, *destaddr, *user, *errstr, *path, *orig_user;
-       ARRAY_TYPE(const_string) extra_fields = ARRAY_INIT;
-       struct setting_parser_context *parser;
+       const char *destaddr, *user, *errstr, *path, *getopt_str;
        struct mail_user *mail_user, *raw_mail_user;
        struct mail_namespace *raw_ns;
        struct mail_namespace_settings raw_ns_set;
@@ -489,18 +392,12 @@ int main(int argc, char *argv[])
        struct istream *input;
        struct mailbox_transaction_context *t;
        struct mailbox_header_lookup_ctx *headers_ctx;
-       struct mail_user_settings *user_set;
-       const struct mail_storage_settings *mail_set;
        struct mail *mail;
        char cwd[PATH_MAX];
        uid_t process_euid;
        bool stderr_rejection = FALSE;
-       bool keep_environment = FALSE;
-       bool user_auth = FALSE;
-       bool doveconf_env;
        time_t mtime;
-       int i, ret;
-       pool_t userdb_pool = NULL;
+       int ret, c;
        string_t *str;
        enum mail_error error;
 
@@ -524,123 +421,87 @@ int main(int argc, char *argv[])
 
        i_set_failure_exit_callback(failure_exit_callback);
 
-       lib_init();
-       ioloop = io_loop_create();
-
-       lib_signals_init();
-        lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
-        lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
-        lib_signals_ignore(SIGPIPE, TRUE);
-        lib_signals_ignore(SIGALRM, FALSE);
+       service = master_service_init("lda", MASTER_SERVICE_FLAG_STANDALONE,
+                                     argc, argv);
 #ifdef SIGXFSZ
         lib_signals_ignore(SIGXFSZ, TRUE);
 #endif
 
-       deliver_set = i_new(struct deliver_settings, 1);
        mailbox_autocreate = TRUE;
-
-       destaddr = user = path = NULL;
-       for (i = 1; i < argc; i++) {
-               if (strcmp(argv[i], "-a") == 0) {
+       destaddr = path = NULL;
+
+       user = getenv("USER");
+       getopt_str = t_strconcat("a:d:p:ekm:nsf:",
+                                master_service_getopt_string(), NULL);
+       while ((c = getopt(argc, argv, getopt_str)) > 0) {
+               switch (c) {
+               case 'a':
                        /* destination address */
-                       i++;
-                       if (i == argc)
-                               i_fatal_status(EX_USAGE, "Missing -a argument");
-                       destaddr = argv[i];
-               } else if (strcmp(argv[i], "-d") == 0) {
+                       destaddr = optarg;
+                       break;
+               case 'd':
                        /* destination user */
-                       i++;
-                       if (i == argc)
-                               i_fatal_status(EX_USAGE, "Missing -d argument");
-                       user = argv[i];
-                       user_auth = TRUE;
-               } else if (strcmp(argv[i], "-p") == 0) {
+                       user = optarg;
+                       service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+                       break;
+               case 'p':
                        /* input path */
-                       i++;
-                       if (i == argc)
-                               i_fatal_status(EX_USAGE, "Missing -p argument");
-                       path = argv[i];
+                       path = optarg;
                        if (*path != '/') {
                                /* expand relative paths before we chdir */
                                if (getcwd(cwd, sizeof(cwd)) == NULL)
                                        i_fatal("getcwd() failed: %m");
                                path = t_strconcat(cwd, "/", path, NULL);
                        }
-               } else if (strcmp(argv[i], "-e") == 0) {
+                       break;
+               case 'e':
                        stderr_rejection = TRUE;
-               } else if (strcmp(argv[i], "-c") == 0) {
-                       /* config file path */
-                       i++;
-                       if (i == argc) {
-                               i_fatal_status(EX_USAGE,
-                                       "Missing config file path argument");
-                       }
-                       config_path = argv[i];
-               } else if (strcmp(argv[i], "-k") == 0) {
-                       keep_environment = TRUE;
-               } else if (strcmp(argv[i], "-m") == 0) {
-                       /* destination mailbox */
-                       i++;
-                       if (i == argc)
-                               i_fatal_status(EX_USAGE, "Missing -m argument");
-                       /* Ignore -m "". This allows doing -m ${extension}
+                       break;
+               case 'm':
+                       /* destination mailbox.
+                          Ignore -m "". This allows doing -m ${extension}
                           in Postfix to handle user+mailbox */
-                       if (*argv[i] != '\0') {
+                       if (*optarg != '\0') {
                                str = t_str_new(256);
-                               if (imap_utf8_to_utf7(argv[i], str) < 0) {
+                               if (imap_utf8_to_utf7(optarg, str) < 0) {
                                        i_fatal("Mailbox name not UTF-8: %s",
                                                mailbox);
                                }
                                mailbox = str_c(str);
                        }
-               } else if (strcmp(argv[i], "-n") == 0) {
+                       break;
+               case 'n':
                        mailbox_autocreate = FALSE;
-               } else if (strcmp(argv[i], "-s") == 0) {
+                       break;
+               case 's':
                        mailbox_autosubscribe = TRUE;
-               } else if (strcmp(argv[i], "-f") == 0) {
+                       break;
+               case 'f':
                        /* envelope sender address */
-                       i++;
-                       if (i == argc)
-                               i_fatal_status(EX_USAGE, "Missing -f argument");
                        explicit_envelope_sender =
-                               i_strdup(address_sanitize(argv[i]));
-               } else if (argv[i][0] != '\0') {
-                       print_help();
-                       i_fatal_status(EX_USAGE,
-                                      "Unknown argument: %s", argv[i]);
+                               i_strdup(address_sanitize(optarg));
+                       break;
+               default:
+                       if (!master_service_parse_option(service, c, optarg)) {
+                               print_help();
+                               i_fatal_status(EX_USAGE,
+                                              "Unknown argument: %c", c);
+                       }
+                       break;
                }
        }
-
-       doveconf_env = getenv("DOVECONF_ENV") != NULL;
-       if (user == NULL)
-               user = getenv("USER");
-       if (!keep_environment && !doveconf_env) {
-               deliver_env_clean(!user_auth);
-               env_put(t_strconcat("USER=", user, NULL));
-       }
-       if (!doveconf_env) {
-               /* currently we need to be executed via doveconf. */
-#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
-               const char **conf_argv;
-
-               conf_argv = i_new(const char *, 6 + (argc + 1) + 1);
-               conf_argv[0] = DOVECOT_CONFIG_BIN_PATH;
-               conf_argv[1] = "-s";
-               conf_argv[2] = "lda";
-               conf_argv[3] = "-c";
-               conf_argv[4] = config_path;
-               conf_argv[5] = "--exec";
-               memcpy(conf_argv+6, argv, (argc+1) * sizeof(argv[0]));
-               execv(conf_argv[0], (char **)conf_argv);
-               i_fatal_status(EX_CONFIG, "execv(%s) failed: %m", conf_argv[0]);
+       if (optind != argc) {
+               print_help();
+               i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
        }
 
        process_euid = geteuid();
-       if (user_auth)
+       if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0)
                ;
        else if (process_euid != 0) {
                /* we're non-root. get our username and possibly our home. */
                struct passwd *pw;
+               const char *home;
 
                home = getenv("HOME");
                if (user != NULL && home != NULL) {
@@ -659,96 +520,18 @@ int main(int argc, char *argv[])
                        "destination user parameter (-d user) not given");
        }
 
-        mail_storage_init();
-       mail_storage_register_all();
-       mailbox_list_register_all();
-
-       parser = deliver_settings_read(&deliver_set, &user_set);
-       open_logfile(user);
-
-       mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
-       if (deliver_set->mail_plugins == '\0')
-               modules = NULL;
-       else {
-               const char *version;
-
-               version = deliver_set->version_ignore ? NULL : PACKAGE_VERSION;
-               modules = module_dir_load(deliver_set->mail_plugin_dir,
-                                         deliver_set->mail_plugins,
-                                         TRUE, version);
-       }
-
-       if (user_auth) {
-               userdb_pool = pool_alloconly_create("userdb lookup replys", 512);
-               orig_user = user;
-               ret = auth_client_lookup_and_restrict(deliver_set->auth_socket_path,
-                                                     mail_set->mail_debug,
-                                                     &user, process_euid,
-                                                     userdb_pool,
-                                                     &extra_fields);
-               if (ret != 0)
-                       return ret;
-
-               if (strcmp(user, orig_user) != 0) {
-                       /* auth lookup changed the user. */
-                       if (mail_set->mail_debug)
-                               i_info("userdb changed username to %s", user);
-                       i_set_failure_prefix(t_strdup_printf("deliver(%s): ",
-                                                            user));
-               }
-               /* if user was changed, it was allocated from userdb_pool
-                  which we'll free soon. */
-               user = t_strdup(user);
-       }
-
-       if (userdb_pool != NULL) {
-               settings_parse_set_expanded(parser, TRUE);
-               deliver_settings_add(parser, &extra_fields);
-               pool_unref(&userdb_pool);
-       }
-
-       home = getenv("HOME");
-       if (home == NULL) {
-               plugin_get_home();
-               home = getenv("HOME");
-       }
-
-       /* If possible chdir to home directory, so that core file
-          could be written in case we crash. */
-       if (home != NULL) {
-               if (chdir(home) < 0) {
-                       if (errno != ENOENT)
-                               i_error("chdir(%s) failed: %m", home);
-                       else if (mail_set->mail_debug)
-                               i_info("Home dir not found: %s", home);
-               }
-       }
-
-       env_put(t_strconcat("USER=", user, NULL));
-       (void)umask(0077);
-
-       dict_drivers_register_builtin();
-        duplicate_init(mail_set);
-       mail_users_init(deliver_set->auth_socket_path, mail_set->mail_debug);
-
-       module_dir_init(modules);
-
-       mail_user = mail_user_alloc(user, user_set);
-       mail_user_set_home(mail_user, home);
-       mail_user_set_vars(mail_user, geteuid(), "deliver", NULL, NULL);
-       if (mail_user_init(mail_user, &errstr) < 0)
-               i_fatal("Mail user initialization failed: %s", errstr);
-       if (mail_namespaces_init(mail_user, &errstr) < 0)
-               i_fatal("Namespace initialization failed: %s", errstr);
+       service_flags |= MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
+       mail_user = mail_storage_service_init_user(service, user,
+                               &deliver_setting_parser_info, service_flags);
+       deliver_set = mail_storage_service_get_settings(service);
+        duplicate_init(mail_user_set_get_storage_set(mail_user->set));
 
        /* create a separate mail user for the internal namespace */
-       raw_mail_user = mail_user_alloc(user, user_set);
+       raw_mail_user = mail_user_alloc(user, mail_user->unexpanded_set);
        mail_user_set_home(raw_mail_user, "/");
        if (mail_user_init(raw_mail_user, &errstr) < 0)
                i_fatal("Raw user initialization failed: %s", errstr);
 
-       settings_parser_deinit(&parser);
-
        memset(&raw_ns_set, 0, sizeof(raw_ns_set));
        raw_ns_set.location = "/tmp";
 
@@ -866,17 +649,9 @@ int main(int argc, char *argv[])
 
        mail_user_unref(&mail_user);
        mail_user_unref(&raw_mail_user);
-
-       module_dir_unload(&modules);
-       mail_storage_deinit();
-       mail_users_deinit();
-
        duplicate_deinit();
-       dict_drivers_unregister_builtin();
-       lib_signals_deinit();
-
-       io_loop_destroy(&ioloop);
-       lib_deinit();
 
+       mail_storage_service_deinit_user();
+       master_service_deinit(&service);
         return EX_OK;
 }
index 398326c3eb90cfcda56d3d1a09975f25352cdeda..5c4bafd48f9a3060865e43fe0fe0f90328c6fe99 100644 (file)
@@ -11,7 +11,7 @@
 #include "mail-storage.h"
 #include "deliver-settings.h"
 
-extern struct deliver_settings *deliver_set;
+extern const struct deliver_settings *deliver_set;
 extern bool mailbox_autosubscribe;
 extern bool mailbox_autocreate;
 extern bool tried_default_save;
@@ -23,8 +23,6 @@ typedef int deliver_mail_func_t(struct mail_namespace *namespaces,
 
 extern deliver_mail_func_t *deliver_mail;
 
-void deliver_env_clean(bool preserve_home);
-
 /* Save a mail into given mailbox with given flags and keywords. */
 int deliver_save(struct mail_namespace *namespaces,
                 struct mail_storage **storage_r, const char *mailbox,
index 4cb89f6fe83ef2a8e9ec8c3e0c13375a441104ee..fb3ad80ba97013caf31d4c02def67c90429783bf 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "deliver.h"
+#include "master-service.h"
 #include "smtp-client.h"
 
 #include <unistd.h>
@@ -46,7 +47,7 @@ smtp_client_run_sendmail(const char *destination,
        if (dup2(fd, STDIN_FILENO) < 0)
                i_fatal("dup2() failed: %m");
 
-       deliver_env_clean(TRUE);
+       master_service_env_clean(TRUE);
 
        (void)execv(sendmail_path, (void *)argv);
        i_fatal("execv(%s) failed: %m", sendmail_path);
index 7273af9d901fe63f74b1eaedf8b59f73a838a978..816d6bc4895dd6f7f2866798baba7c46313b3c84 100644 (file)
@@ -58,6 +58,7 @@ static void drop_privileges(void)
        sql_drivers_register_all();
 
        restrict_access_by_env(NULL, FALSE);
+       restrict_access_allow_coredumps(TRUE);
 }
 
 static void main_init(void)
index 9ca4086e8bc2f057fe5503995810e57e294f1c46..dbc6c17497126f08c4ecb3fc1723c554205e65e4 100644 (file)
@@ -9,9 +9,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-index \
-       -I$(top_srcdir)/src/lib-storage \
-       -DPKG_RUNDIR=\""$(rundir)"\" \
-       -DMODULEDIR=\""$(moduledir)"\"
+       -I$(top_srcdir)/src/lib-storage
 
 imap_LDFLAGS = -export-dynamic
 
index cb8582f9cac96fd15ad42979fbb56527bc4af704..f90d1ae5ffc3c1dcd45d8ad5a3c90818a3802d8e 100644 (file)
@@ -9,8 +9,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-static bool imap_settings_check(void *_set, pool_t pool, const char **error_r);
-
 #undef DEF
 #undef DEFLIST
 #define DEF(type, name) \
@@ -19,16 +17,10 @@ static bool imap_settings_check(void *_set, pool_t pool, const char **error_r);
        { SET_DEFLIST, name, offsetof(struct imap_settings, field), defines }
 
 static struct setting_define imap_setting_defines[] = {
-       DEF(SET_STR, base_dir),
-       DEF(SET_STR, auth_socket_path),
-
        DEF(SET_BOOL, mail_debug),
        DEF(SET_BOOL, shutdown_clients),
        DEF(SET_BOOL, verbose_proctitle),
 
-       DEF(SET_STR, mail_plugins),
-       DEF(SET_STR, mail_plugin_dir),
-
        DEF(SET_UINT, imap_max_line_length),
        DEF(SET_STR, imap_capability),
        DEF(SET_STR, imap_client_workarounds),
@@ -40,16 +32,10 @@ static struct setting_define imap_setting_defines[] = {
 };
 
 static struct imap_settings imap_default_settings = {
-       MEMBER(base_dir) PKG_RUNDIR,
-       MEMBER(auth_socket_path) "auth-master",
-
        MEMBER(mail_debug) FALSE,
        MEMBER(shutdown_clients) FALSE,
        MEMBER(verbose_proctitle) FALSE,
 
-       MEMBER(mail_plugins) "",
-       MEMBER(mail_plugin_dir) MODULEDIR,
-
        /* RFC-2683 recommends at least 8000 bytes. Some clients however don't
           break large message sets to multiple commands, so we're pretty
           liberal by default. */
@@ -71,40 +57,11 @@ struct setting_parser_info imap_setting_parser_info = {
        MEMBER(parent_offset) (size_t)-1,
        MEMBER(type_offset) (size_t)-1,
        MEMBER(struct_size) sizeof(struct imap_settings),
-       MEMBER(check_func) imap_settings_check
+       MEMBER(check_func) NULL
 };
 
 static pool_t settings_pool = NULL;
 
-static void fix_base_path(struct imap_settings *set, const char **str)
-{
-       if (*str != NULL && **str != '\0' && **str != '/') {
-               *str = p_strconcat(settings_pool,
-                                  set->base_dir, "/", *str, NULL);
-       }
-}
-
-/* <settings checks> */
-static bool imap_settings_check(void *_set, pool_t pool ATTR_UNUSED,
-                               const char **error_r)
-{
-       struct imap_settings *set = _set;
-
-#ifndef CONFIG_BINARY
-       fix_base_path(set, &set->auth_socket_path);
-#endif
-
-       if (*set->mail_plugins != '\0' &&
-           access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
-               *error_r = t_strdup_printf(
-                       "mail_plugin_dir: access(%s) failed: %m",
-                       set->mail_plugin_dir);
-               return FALSE;
-       }
-       return TRUE;
-}
-/* </settings checks> */
-
 static void
 parse_expand_vars(struct setting_parser_context *parser, const char *value)
 {
@@ -143,7 +100,8 @@ void imap_settings_read(const struct imap_settings **set_r,
        else
                p_clear(settings_pool);
 
-       mail_storage_namespace_defines_init(settings_pool);
+       settings_parser_info_update(settings_pool,
+                                   mail_storage_get_dynamic_parsers());
 
        parser = settings_parser_init_list(settings_pool,
                                roots, N_ELEMENTS(roots),
index 5226d13844458b88d0e75b30c80f4bc65d00444c..3d7fd2170c580c5a6fe3b7363f4de1ed1312e2d8 100644 (file)
@@ -4,16 +4,10 @@
 struct mail_user_settings;
 
 struct imap_settings {
-       const char *base_dir;
-       const char *auth_socket_path;
-
        bool mail_debug;
        bool shutdown_clients;
        bool verbose_proctitle;
 
-       const char *mail_plugins;
-       const char *mail_plugin_dir;
-
        /* imap: */
        unsigned int imap_max_line_length;
        const char *imap_capability;
index 212afc0e2dd02ef67334479c191de8766157be80..7225b0bbc875a99455921035f785c29938b0cde7 100644 (file)
@@ -155,9 +155,9 @@ static void main_preinit(const struct imap_settings **set_r,
        imap_settings_read(set_r, user_set_r);
 
        /* Load the plugins before chrooting. Their init() is called later. */
-       modules = *(*set_r)->mail_plugins == '\0' ? NULL :
-               module_dir_load((*set_r)->mail_plugin_dir,
-                               (*set_r)->mail_plugins, TRUE, version);
+       modules = *(*user_set_r)->mail_plugins == '\0' ? NULL :
+               module_dir_load((*user_set_r)->mail_plugin_dir,
+                               (*user_set_r)->mail_plugins, TRUE, version);
 
        restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
        restrict_access_allow_coredumps(TRUE);
@@ -202,13 +202,12 @@ static void main_init(const struct imap_settings *set,
                                log_error_callback, NULL);
        }
 
+       module_dir_init(modules);
        dict_drivers_register_builtin();
-       mail_users_init(set->auth_socket_path, set->mail_debug);
+       mail_users_init(user_set->auth_socket_path, set->mail_debug);
        clients_init();
        commands_init();
 
-       module_dir_init(modules);
-
        user = mail_user_alloc(username, user_set);
        mail_user_set_home(user, home);
        if (mail_user_init(user, &error) < 0)
index 4198fa27fd25b35210342a37ef73c54c3d6da357..27219dbdc457298ffeb6d3037df82bea4c4ff256 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef AUTH_MASTER_H
 #define AUTH_MASTER_H
 
-#define AUTH_SERVICE_INTERNAL "internal"
-
 struct auth_user_reply {
        uid_t uid;
        gid_t gid;
index df6f56ebb09b503c315564d579cf30fe5425551e..83894b1c6fc95b901f48a04e0aef040f6fe0f82d 100644 (file)
@@ -9,6 +9,7 @@ libs = \
        ../lib-mail/libmail.la \
        ../lib-auth/libauth.la \
        ../lib-charset/libcharset.la \
+       ../lib-master/libmaster.la \
        ../lib/liblib.la
 
 libdovecot_la_LIBADD = \
diff --git a/src/lib-master/Makefile.am b/src/lib-master/Makefile.am
new file mode 100644 (file)
index 0000000..a0afbe0
--- /dev/null
@@ -0,0 +1,19 @@
+noinst_LTLIBRARIES = libmaster.la
+
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-settings \
+       -DSYSCONFDIR=\""$(sysconfdir)"\" \
+       -DBINDIR=\""$(bindir)"\" \
+       -DPKG_RUNDIR=\""$(rundir)"\"
+
+libmaster_la_SOURCES = \
+       master-service.c \
+       master-service-settings.c \
+       syslog-util.c
+
+noinst_HEADERS = \
+       master-service.h \
+       master-service-private.h \
+       master-service-settings.h \
+       syslog-util.h
diff --git a/src/lib-master/master-service-private.h b/src/lib-master/master-service-private.h
new file mode 100644 (file)
index 0000000..ac500e6
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef MASTER_SERVICE_PRIVATE_H
+#define MASTER_SERVICE_PRIVATE_H
+
+#include "master-service.h"
+
+struct master_service {
+       struct ioloop *ioloop;
+
+       char *name;
+        enum master_service_flags flags;
+
+       int argc;
+       char **argv;
+
+       const char *version_string;
+       const char *config_path;
+       int syslog_facility;
+
+       pool_t set_pool;
+       const struct master_service_settings *set;
+       struct setting_parser_context *set_parser;
+
+       unsigned int keep_environment:1;
+       unsigned int log_directly:1;
+};
+
+#endif
diff --git a/src/lib-master/master-service-settings.c b/src/lib-master/master-service-settings.c
new file mode 100644 (file)
index 0000000..58332eb
--- /dev/null
@@ -0,0 +1,144 @@
+/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "settings-parser.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
+
+#undef DEF
+#define DEF(type, name) \
+       { type, #name, offsetof(struct master_service_settings, name), NULL }
+
+static struct setting_define master_service_setting_defines[] = {
+       DEF(SET_STR, log_path),
+       DEF(SET_STR, info_log_path),
+       DEF(SET_STR, log_timestamp),
+       DEF(SET_STR, syslog_facility),
+       DEF(SET_BOOL, version_ignore),
+
+       SETTING_DEFINE_LIST_END
+};
+
+static struct master_service_settings master_service_default_settings = {
+       MEMBER(log_path) "",
+       MEMBER(info_log_path) "",
+       MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
+       MEMBER(syslog_facility) "mail",
+       MEMBER(version_ignore) FALSE
+};
+
+struct setting_parser_info master_service_setting_parser_info = {
+       MEMBER(defines) master_service_setting_defines,
+       MEMBER(defaults) &master_service_default_settings,
+
+       MEMBER(parent) NULL,
+       MEMBER(dynamic_parsers) NULL,
+
+       MEMBER(parent_offset) (size_t)-1,
+       MEMBER(type_offset) (size_t)-1,
+       MEMBER(struct_size) sizeof(struct master_service_settings)
+};
+
+static void ATTR_NORETURN
+master_service_exec_config(struct master_service *service, bool preserve_home)
+{
+       const char **conf_argv;
+
+       if (!service->keep_environment)
+               master_service_env_clean(preserve_home);
+
+       /* @UNSAFE */
+       conf_argv = t_new(const char *, 6 + (service->argc + 1) + 1);
+       conf_argv[0] = DOVECOT_CONFIG_BIN_PATH;
+       conf_argv[1] = "-s";
+       conf_argv[2] = service->name;
+       conf_argv[3] = "-c";
+       conf_argv[4] = service->config_path;
+       conf_argv[5] = "--exec";
+       memcpy(conf_argv+6, service->argv,
+              (service->argc+1) * sizeof(conf_argv[0]));
+       execv(conf_argv[0], (char **)conf_argv);
+       i_fatal("execv(%s) failed: %m", conf_argv[0]);
+}
+
+int master_service_settings_read(struct master_service *service,
+                                const struct setting_parser_info *roots[],
+                                const struct dynamic_settings_parser *dyn_parsers,
+                                bool preserve_home, const char **error_r)
+{
+       ARRAY_DEFINE(all_roots, const struct setting_parser_info *);
+       const struct setting_parser_info *tmp_root;
+       struct setting_parser_context *parser;
+       const char *error;
+       void **sets;
+       unsigned int i;
+
+       if (getenv("DOVECONF_ENV") == NULL)
+               master_service_exec_config(service, preserve_home);
+
+       if (service->set_pool != NULL)
+               p_clear(service->set_pool);
+       else {
+               service->set_pool =
+                       pool_alloconly_create("master service settings", 4096);
+       }
+
+       if (dyn_parsers != NULL)
+               settings_parser_info_update(service->set_pool, dyn_parsers);
+
+       p_array_init(&all_roots, service->set_pool, 8);
+       tmp_root = &master_service_setting_parser_info;
+       array_append(&all_roots, &tmp_root, 1);
+       for (i = 0; roots[i] != NULL; i++)
+               array_append(&all_roots, &roots[i], 1);
+
+       parser = settings_parser_init_list(service->set_pool,
+                       array_idx(&all_roots, 0), array_count(&all_roots),
+                       SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
+
+       if (settings_parse_environ(parser) < 0) {
+               *error_r = settings_parser_get_error(parser);
+               return -1;
+       }
+
+       if (settings_parser_check(parser, service->set_pool, &error) < 0) {
+               *error_r = t_strdup_printf("Invalid settings: %s", error);
+               return -1;
+       }
+
+       sets = settings_parser_get_list(parser);
+       service->set = sets[0];
+       service->set_parser = parser;
+
+       if (service->set->version_ignore &&
+           (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) {
+               /* running standalone. we want to ignore plugin versions. */
+               service->version_string = NULL;
+       }
+
+       /* if we change any settings afterwards, they're in expanded form.
+          especially all settings from userdb are already expanded. */
+       settings_parse_set_expanded(service->set_parser, TRUE);
+       return 0;
+}
+
+const struct master_service_settings *
+master_service_settings_get(struct master_service *service)
+{
+       void **sets;
+
+       sets = settings_parser_get_list(service->set_parser);
+       return sets[0];
+}
+
+void **master_service_settings_get_others(struct master_service *service)
+{
+       return settings_parser_get_list(service->set_parser) + 1;
+}
diff --git a/src/lib-master/master-service-settings.h b/src/lib-master/master-service-settings.h
new file mode 100644 (file)
index 0000000..439a6b8
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef MASTER_SERVICE_SETTINGS_H
+#define MASTER_SERVICE_SETTINGS_H
+
+struct setting_parser_info;
+struct dynamic_settings_parser;
+
+struct master_service_settings {
+       const char *log_path;
+       const char *info_log_path;
+       const char *log_timestamp;
+       const char *syslog_facility;
+       bool version_ignore;
+};
+
+int master_service_settings_read(struct master_service *service,
+                                const struct setting_parser_info *roots[],
+                                const struct dynamic_settings_parser *dyn_parsers,
+                                bool preserve_home, const char **error_r);
+const struct master_service_settings *
+master_service_settings_get(struct master_service *service);
+void **master_service_settings_get_others(struct master_service *service);
+
+#endif
diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c
new file mode 100644 (file)
index 0000000..eaedf37
--- /dev/null
@@ -0,0 +1,219 @@
+/* Copyright (C) 2005-2009 Timo Sirainen */
+
+#include "lib.h"
+#include "lib-signals.h"
+#include "ioloop.h"
+#include "env-util.h"
+#include "home-expand.h"
+#include "restrict-access.h"
+#include "fd-close-on-exec.h"
+#include "syslog-util.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
+
+/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
+#define MASTER_CONFIG_FILE_ENV "CONFIG_FILE"
+
+/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
+#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
+
+const char *master_service_getopt_string(void)
+{
+       return "c:Lk";
+}
+
+static void sig_die(const siginfo_t *si, void *context)
+{
+       struct master_service *service = context;
+
+       /* warn about being killed because of some signal, except SIGINT (^C)
+          which is too common at least while testing :) */
+       if (si->si_signo != SIGINT) {
+               i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
+                         si->si_signo, dec2str(si->si_pid),
+                         dec2str(si->si_uid),
+                         lib_signal_code_to_str(si->si_signo, si->si_code));
+       }
+       io_loop_stop(service->ioloop);
+}
+
+static void master_service_verify_version(struct master_service *service)
+{
+       if (service->version_string != NULL &&
+           strcmp(service->version_string, PACKAGE_VERSION) != 0) {
+               i_fatal("Dovecot version mismatch: "
+                       "Master is v%s, %s is v"PACKAGE_VERSION" "
+                       "(if you don't care, set version_ignore=yes)",
+                       service->name, service->version_string);
+       }
+}
+
+struct master_service *
+master_service_init(const char *name, enum master_service_flags flags,
+                   int argc, char *argv[])
+{
+       struct master_service *service;
+
+       i_assert(name != NULL);
+
+       /* NOTE: we start rooted, so keep the code minimal until
+          restrict_access_by_env() is called */
+       lib_init();
+       /* Set a logging prefix temporarily. This will be ignored once the log
+          is properly initialized */
+       i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
+
+       if (getenv("LOG_TO_MASTER") == NULL)
+               flags |= MASTER_SERVICE_FLAG_STANDALONE;
+
+       service = i_new(struct master_service, 1);
+       service->argc = argc;
+       service->argv = argv;
+       service->name = i_strdup(name);
+       service->flags = flags;
+       service->ioloop = io_loop_create();
+       service->config_path = getenv(MASTER_CONFIG_FILE_ENV);
+       if (service->config_path == NULL)
+               service->config_path = DEFAULT_CONFIG_FILE_PATH;
+
+       if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0)
+               service->version_string = getenv(MASTER_DOVECOT_VERSION_ENV);
+       else
+               service->version_string = PACKAGE_VERSION;
+
+       /* set up some kind of logging until we know exactly how and where
+          we want to log */
+       if (getenv("LOG_TO_MASTER") != NULL)
+               i_set_failure_internal();
+       if (getenv("USER") != NULL) {
+               i_set_failure_prefix(t_strdup_printf("%s(%s): ",
+                                                    name, getenv("USER")));
+       } else {
+               i_set_failure_prefix(t_strdup_printf("%s: ", name));
+       }
+
+       /* set default signal handlers */
+       lib_signals_init();
+        lib_signals_ignore(SIGPIPE, TRUE);
+        lib_signals_ignore(SIGALRM, FALSE);
+        lib_signals_set_handler(SIGINT, TRUE, sig_die, service);
+       lib_signals_set_handler(SIGTERM, TRUE, sig_die, service);
+
+       master_service_verify_version(service);
+       return service;
+}
+
+void master_service_init_log(struct master_service *service, const char *prefix)
+{
+       const char *path;
+
+       if (getenv("LOG_TO_MASTER") != NULL && !service->log_directly) {
+               /* logging via master process */
+               i_set_failure_internal();
+               i_set_failure_prefix(prefix);
+               return;
+       }
+
+       if (*service->set->log_path == '\0') {
+               /* log to syslog */
+               int facility;
+
+               if (!syslog_facility_find(service->set->syslog_facility,
+                                         &facility))
+                       facility = LOG_MAIL;
+               i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
+               i_set_failure_prefix(prefix);
+       } else {
+               /* log to file or stderr */
+               path = home_expand(service->set->log_path);
+               i_set_failure_file(path, prefix);
+       }
+
+       path = home_expand(service->set->info_log_path);
+       if (*path != '\0')
+               i_set_info_file(path);
+       i_set_failure_timestamp_format(service->set->log_timestamp);
+}
+
+bool master_service_parse_option(struct master_service *service,
+                                int opt, const char *arg)
+{
+       switch (opt) {
+       case 'c':
+               service->config_path = arg;
+               break;
+       case 'k':
+               service->keep_environment = TRUE;
+               break;
+       case 'L':
+               service->log_directly = TRUE;
+               break;
+       default:
+               return FALSE;
+       }
+       return TRUE;
+}
+
+void master_service_env_clean(bool preserve_home)
+{
+       const char *user, *tz, *home;
+
+       user = getenv("USER");
+       if (user != NULL)
+               user = t_strconcat("USER=", user, NULL);
+       tz = getenv("TZ");
+       if (tz != NULL)
+               tz = t_strconcat("TZ=", tz, NULL);
+       home = preserve_home ? getenv("HOME") : NULL;
+       if (home != NULL)
+               home = t_strconcat("HOME=", home, NULL);
+
+       /* Note that if the original environment was set with env_put(), the
+          environment strings will be invalid after env_clean(). That's why
+          we t_strconcat() them above. */
+       env_clean();
+
+       if (user != NULL) env_put(user);
+       if (tz != NULL) env_put(tz);
+       if (home != NULL) env_put(home);
+}
+
+const char *master_service_get_config_path(struct master_service *service)
+{
+       return service->config_path;
+}
+
+const char *master_service_get_version_string(struct master_service *service)
+{
+       return service->version_string;
+}
+
+void master_service_run(struct master_service *service)
+{
+       io_loop_run(service->ioloop);
+}
+
+void master_service_stop(struct master_service *service)
+{
+        io_loop_stop(service->ioloop);
+}
+
+void master_service_deinit(struct master_service **_service)
+{
+       struct master_service *service = *_service;
+
+       *_service = NULL;
+       lib_signals_deinit();
+       io_loop_destroy(&service->ioloop);
+
+       i_free(service->name);
+       i_free(service);
+
+       lib_deinit();
+}
diff --git a/src/lib-master/master-service.h b/src/lib-master/master-service.h
new file mode 100644 (file)
index 0000000..c7839d1
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef MASTER_SERVICE_H
+#define MASTER_SERVICE_H
+
+#include "network.h"
+
+enum master_service_flags {
+       /* stdin/stdout already contains a client which we want to serve */
+       MASTER_SERVICE_FLAG_STD_CLIENT          = 0x01,
+       /* this process is currently running standalone without a master */
+       MASTER_SERVICE_FLAG_STANDALONE          = 0x02
+};
+
+struct master_service;
+
+const char *master_service_getopt_string(void);
+
+/* Start service initialization. */
+struct master_service *
+master_service_init(const char *name, enum master_service_flags flags,
+                   int argc, char *argv[]);
+/* Parser command line option. Returns TRUE if processed. */
+bool master_service_parse_option(struct master_service *service,
+                                int opt, const char *arg);
+
+/* Clean environment from everything except TZ, USER and optionally HOME. */
+void master_service_env_clean(bool preserve_home);
+
+/* Initialize logging. */
+void master_service_init_log(struct master_service *service,
+                            const char *prefix);
+
+/* Returns configuration file path. */
+const char *master_service_get_config_path(struct master_service *service);
+/* Returns PACKAGE_VERSION or NULL if version_ignore=yes. This function is
+   useful mostly as parameter to module_dir_load(). */
+const char *master_service_get_version_string(struct master_service *service);
+
+/* Start the service. Blocks until finished */
+void master_service_run(struct master_service *service);
+/* Stop a running service. */
+void master_service_stop(struct master_service *service);
+
+/* Deinitialize the service. */
+void master_service_deinit(struct master_service **service);
+
+#endif
diff --git a/src/lib-master/syslog-util.c b/src/lib-master/syslog-util.c
new file mode 100644 (file)
index 0000000..3d9a075
--- /dev/null
@@ -0,0 +1,65 @@
+/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "syslog-util.h"
+#include <syslog.h>
+
+struct syslog_facility_list syslog_facilities[] = {
+#ifdef LOG_AUTH
+       { "auth", LOG_AUTH },
+#endif
+#ifdef LOG_AUTHPRIV
+       { "authpriv", LOG_AUTHPRIV },
+#endif
+#ifdef LOG_CRON
+       { "cron", LOG_CRON },
+#endif
+#ifdef LOG_DAEMON
+       { "daemon", LOG_DAEMON },
+#endif
+#ifdef LOG_FTP
+       { "ftp", LOG_FTP },
+#endif
+#ifdef LOG_KERN
+       { "kern", LOG_KERN },
+#endif
+#ifdef LOG_LPR
+       { "lpr", LOG_LPR },
+#endif
+#ifdef LOG_MAIL
+       { "mail", LOG_MAIL },
+#endif
+#ifdef LOG_NEWS
+       { "news", LOG_NEWS },
+#endif
+#ifdef LOG_SYSLOG
+       { "syslog", LOG_SYSLOG },
+#endif
+#ifdef LOG_UUCP
+       { "uucp", LOG_UUCP },
+#endif
+       { "user", LOG_USER },
+       { "local0", LOG_LOCAL0 },
+       { "local1", LOG_LOCAL1 },
+       { "local2", LOG_LOCAL2 },
+       { "local3", LOG_LOCAL3 },
+       { "local4", LOG_LOCAL4 },
+       { "local5", LOG_LOCAL5 },
+       { "local6", LOG_LOCAL6 },
+       { "local7", LOG_LOCAL7 },
+
+       { NULL, 0 }
+};
+
+bool syslog_facility_find(const char *name, int *facility_r)
+{
+       int i;
+
+       for (i = 0; syslog_facilities[i].name != NULL; i++) {
+               if (strcmp(syslog_facilities[i].name, name) == 0) {
+                       *facility_r = syslog_facilities[i].facility;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
diff --git a/src/lib-master/syslog-util.h b/src/lib-master/syslog-util.h
new file mode 100644 (file)
index 0000000..68e1250
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef SYSLOG_UTIL_H
+#define SYSLOG_UTIL_H
+
+struct syslog_facility_list {
+       const char *name;
+       int facility;
+};
+
+extern struct syslog_facility_list syslog_facilities[];
+
+/* Returns TRUE if found. */
+bool syslog_facility_find(const char *name, int *facility_r);
+
+#endif
index 2f012aec940f5d31e92e7a929db081acab2906df..af93f8ba41c300b4a025e83fdf01405b45196f9d 100644 (file)
@@ -899,10 +899,10 @@ void settings_parse_save_input(struct setting_parser_context *ctx,
 }
 
 static void
-info_update_real(pool_t pool, struct setting_parser_info *parent,
-                const struct dynamic_settings_parser *parsers)
+info_update_real(pool_t pool, const struct dynamic_settings_parser *parsers)
 {
        /* @UNSAFE */
+       struct setting_parser_info *parent;
        ARRAY_DEFINE(defines, struct setting_define);
        ARRAY_TYPE(dynamic_settings_parser) dynamic_parsers;
        struct dynamic_settings_parser new_parser;
@@ -912,6 +912,8 @@ info_update_real(pool_t pool, struct setting_parser_info *parent,
        unsigned int i, j;
        size_t offset, new_struct_size;
 
+       parent = parsers[0].info->parent;
+
        t_array_init(&defines, 128);
        /* add existing defines */
        for (j = 0; parent->defines[j].key != NULL; j++)
@@ -971,12 +973,11 @@ info_update_real(pool_t pool, struct setting_parser_info *parent,
        parent->struct_size = new_struct_size;
 }
 
-void
-settings_parser_info_update(pool_t pool, struct setting_parser_info *parent,
-                           const struct dynamic_settings_parser *parsers)
+void settings_parser_info_update(pool_t pool,
+                                const struct dynamic_settings_parser *parsers)
 {
-       T_BEGIN {
-               info_update_real(pool, parent, parsers);
+       if (parsers[0].name != NULL) T_BEGIN {
+               info_update_real(pool, parsers);
        } T_END;
 }
 
index 0efe10add372076f0bcb71316dad363eb1d2d59e..f3447529ea1a8a53566231bd52112323dfbfc6e1 100644 (file)
@@ -143,11 +143,10 @@ bool settings_vars_have_key(const struct setting_parser_info *info, void *set,
 void *settings_dup(const struct setting_parser_info *info,
                   const void *set, pool_t pool);
 /* parsers is a name=NULL -terminated list. The parsers are appended as
-   dynamic_settings_list structures to parent. The new structures are allocated
-   from the given pool. */
-void
-settings_parser_info_update(pool_t pool, struct setting_parser_info *parent,
-                           const struct dynamic_settings_parser *parsers);
+   dynamic_settings_list structures to their parent. All must have the same
+   parent. The new structures are allocated from the given pool. */
+void settings_parser_info_update(pool_t pool,
+                                const struct dynamic_settings_parser *parsers);
 
 /* Return pointer to beginning of settings for given name, or NULL if there is
    no such registered name. */
index 74996324a18778c320587fe5830e51b7f6226408..79946c7560609a1eba8ca9e97431e439ff625684 100644 (file)
@@ -28,7 +28,6 @@ sql_drivers = @sql_drivers@
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
-       -DMODULEDIR=\""$(moduledir)"\" \
        $(SQL_CFLAGS)
 
 dist_sources = \
index 41778895d0540e55e9efd322fe1d5b677c6cc489..4abc221710451535f1878f3bbae006b77a20f3e6 100644 (file)
@@ -5,11 +5,14 @@ pkglib_LTLIBRARIES = libdovecot-storage.la
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
        -I$(top_srcdir)/src/lib-auth \
+       -I$(top_srcdir)/src/lib-dict \
+       -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-settings \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-index \
-       -DPKG_RUNDIR=\""$(rundir)"\"
+       -DPKG_RUNDIR=\""$(rundir)"\" \
+       -DMODULEDIR=\""$(moduledir)"\"
 
 libdovecot_storage_la_SOURCES = \
        mail.c \
@@ -19,6 +22,7 @@ libdovecot_storage_la_SOURCES = \
        mail-search.c \
        mail-search-build.c \
        mail-storage.c \
+       mail-storage-service.c \
        mail-storage-settings.c \
        mail-user.c \
        mailbox-list.c \
@@ -46,6 +50,7 @@ headers = \
        mail-thread.h \
        mail-storage.h \
        mail-storage-private.h \
+       mail-storage-service.h \
        mail-storage-settings.h \
        mail-user.h \
        mailbox-list.h \
index 204c42b3345d793f1d482ac7f70ea0b602c26623..cf846598dbeb40c0464d74a4b7e6a59cb2d7615c 100644 (file)
@@ -217,7 +217,7 @@ int mail_namespaces_init(struct mail_user *user, const char **error_r)
 
         namespaces = NULL; ns_p = &namespaces;
 
-       mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+       mail_set = mail_user_set_get_storage_set(user->set);
        if (array_is_created(&user->set->namespaces))
                ns_set = array_get(&user->set->namespaces, &count);
        else {
@@ -313,7 +313,7 @@ struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user)
        ns->prefix = i_strdup("");
        ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX |
                NAMESPACE_FLAG_SUBSCRIPTIONS;
-       ns->mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+       ns->mail_set = mail_user_set_get_storage_set(user->set);
        user->namespaces = ns;
        return ns;
 }
diff --git a/src/lib-storage/mail-storage-service.c b/src/lib-storage/mail-storage-service.c
new file mode 100644 (file)
index 0000000..7ce54b6
--- /dev/null
@@ -0,0 +1,525 @@
+/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "dict.h"
+#include "module-dir.h"
+#include "restrict-access.h"
+#include "settings-parser.h"
+#include "auth-master.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+#include "mail-user.h"
+#include "mail-namespace.h"
+#include "mail-storage.h"
+#include "mail-storage-service.h"
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+
+struct mail_storage_service_multi_ctx {
+       struct master_service *service;
+       enum mail_storage_service_flags flags;
+
+       unsigned int modules_initialized:1;
+};
+
+static struct module *modules = NULL;
+
+static void
+master_service_set(struct master_service *service,
+                  const char *key, const char *value)
+{
+       const char *str;
+
+       str = t_strconcat(key, "=", value, NULL);
+       if (settings_parse_line(service->set_parser, str) < 0) {
+               i_fatal("Invalid userdb input '%s': %s", str,
+                       settings_parser_get_error(service->set_parser));
+       }
+}
+
+static bool validate_chroot(const struct mail_user_settings *user_set,
+                           const char *dir)
+{
+       const char *const *chroot_dirs;
+
+       if (*dir == '\0')
+               return FALSE;
+
+       if (*user_set->valid_chroot_dirs == '\0')
+               return FALSE;
+
+       chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
+       while (*chroot_dirs != NULL) {
+               if (**chroot_dirs != '\0' &&
+                   strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
+                       return TRUE;
+               chroot_dirs++;
+       }
+       return FALSE;
+}
+
+static int
+user_reply_handle(struct master_service *service,
+                 const struct mail_user_settings *user_set,
+                 const struct auth_user_reply *reply,
+                 const char **system_groups_user_r, const char **error_r)
+{
+       const char *const *str, *p, *line;
+       unsigned int i, count;
+       int ret = 0;
+
+       *system_groups_user_r = NULL;
+
+       if (reply->uid != (uid_t)-1) {
+               if (reply->uid == 0) {
+                       *error_r = "userdb returned 0 as uid";
+                       return -1;
+               }
+               master_service_set(service, "mail_uid", dec2str(reply->uid));
+       }
+       if (reply->gid != (uid_t)-1)
+               master_service_set(service, "mail_gid", dec2str(reply->gid));
+
+       if (reply->home != NULL)
+               master_service_set(service, "mail_home", reply->home);
+
+       if (reply->chroot != NULL) {
+               if (!validate_chroot(user_set, reply->chroot)) {
+                       *error_r = t_strdup_printf(
+                               "userdb returned invalid chroot directory: %s "
+                               "(see valid_chroot_dirs setting)",
+                               reply->chroot);
+                       return -1;
+               }
+               master_service_set(service, "mail_chroot", reply->chroot);
+       }
+
+       str = array_get(&reply->extra_fields, &count);
+       for (i = 0; i < count && ret == 0; i++) T_BEGIN {
+               line = str[i];
+               if (strncmp(line, "system_groups_user=", 19) == 0) {
+                       *system_groups_user_r = line + 19;
+                       continue;
+               }
+               if (strncmp(line, "mail=", 5) == 0)
+                       line = t_strconcat("mail_location=", line + 5, NULL);
+               else if ((p = strchr(str[i], '=')) == NULL)
+                       line = t_strconcat(str[i], "=yes", NULL);
+               else
+                       line = str[i];
+               ret = settings_parse_line(service->set_parser, line);
+       } T_END;
+
+       if (ret < 0) {
+               *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
+                       str[i], settings_parser_get_error(service->set_parser));
+       }
+       return ret;
+}
+
+static int
+service_auth_userdb_lookup(struct master_service *service, bool debug,
+                          const struct mail_user_settings *user_set,
+                          const char **user, const char **system_groups_user_r,
+                          const char **error_r)
+{
+        struct auth_master_connection *conn;
+       struct auth_user_reply reply;
+       const char *system_groups_user, *orig_user = *user;
+       unsigned int len;
+       pool_t pool;
+       int ret;
+
+       pool = pool_alloconly_create("userdb lookup", 1024);
+       conn = auth_master_init(user_set->auth_socket_path, debug);
+       ret = auth_master_user_lookup(conn, *user, service->name,
+                                     pool, &reply);
+       if (ret > 0) {
+               len = reply.chroot == NULL ? 0 : strlen(reply.chroot);
+
+               *user = t_strdup(reply.user);
+               if (user_reply_handle(service, user_set, &reply,
+                                     &system_groups_user, error_r) < 0)
+                       ret = -1;
+               *system_groups_user_r = t_strdup(system_groups_user);
+       } else {
+               if (ret == 0)
+                       *error_r = "unknown user";
+               else
+                       *error_r = "userdb lookup failed";
+               *system_groups_user_r = NULL;
+       }
+
+       if (ret > 0 && strcmp(*user, orig_user) != 0) {
+               if (mail_user_set_get_storage_set(user_set)->mail_debug)
+                       i_info("changed username to %s", *user);
+               i_set_failure_prefix(t_strdup_printf("%s(%s): ", service->name,
+                                                    *user));
+       }
+
+       auth_master_deinit(&conn);
+       pool_unref(&pool);
+       return ret;
+}
+
+static bool parse_uid(const char *str, uid_t *uid_r)
+{
+       struct passwd *pw;
+       char *p;
+
+       if (*str >= '0' && *str <= '9') {
+               *uid_r = (uid_t)strtoul(str, &p, 10);
+               if (*p == '\0')
+                       return TRUE;
+       }
+
+       pw = getpwnam(str);
+       if (pw == NULL)
+               return FALSE;
+
+       *uid_r = pw->pw_uid;
+       return TRUE;
+}
+
+static bool parse_gid(const char *str, gid_t *gid_r)
+{
+       struct group *gr;
+       char *p;
+
+       if (*str >= '0' && *str <= '9') {
+               *gid_r = (gid_t)strtoul(str, &p, 10);
+               if (*p == '\0')
+                       return TRUE;
+       }
+
+       gr = getgrnam(str);
+       if (gr == NULL)
+               return FALSE;
+
+       *gid_r = gr->gr_gid;
+       return TRUE;
+}
+
+static void
+service_drop_privileges(const struct mail_user_settings *set,
+                       const char *system_groups_user,
+                       bool disallow_root, bool keep_setuid_root)
+{
+       struct restrict_access_settings rset;
+       uid_t current_euid, setuid_uid = 0;
+
+       current_euid = geteuid();
+       restrict_access_init(&rset);
+       if (*set->mail_uid != '\0') {
+               if (!parse_uid(set->mail_uid, &rset.uid))
+                       i_fatal("Unknown mail_uid user: %s", set->mail_uid);
+               if (rset.uid < (uid_t)set->first_valid_uid ||
+                   (set->last_valid_uid != 0 &&
+                    rset.uid > (uid_t)set->last_valid_uid)) {
+                       i_fatal("Mail access for users with UID %s "
+                               "not permitted (see first_valid_uid in config file).",
+                               dec2str(rset.uid));
+               }
+       }
+       if (*set->mail_gid != '\0') {
+               if (!parse_gid(set->mail_gid, &rset.gid))
+                       i_fatal("Unknown mail_gid group: %s", set->mail_gid);
+               if (rset.gid < (gid_t)set->first_valid_gid ||
+                   (set->last_valid_gid != 0 &&
+                    rset.gid > (gid_t)set->last_valid_gid)) {
+                       i_fatal("Mail access for users with GID %s "
+                               "not permitted (see first_valid_gid in config file).",
+                               dec2str(rset.gid));
+               }
+       }
+       if (*set->mail_privileged_group != '\0') {
+               if (!parse_uid(set->mail_privileged_group, &rset.privileged_gid))
+                       i_fatal("Unknown mail_gid group: %s", set->mail_gid);
+       }
+       if (*set->mail_access_groups != '\0')
+               rset.extra_groups = set->mail_access_groups;
+
+       rset.first_valid_gid = set->first_valid_gid;
+       rset.last_valid_gid = set->last_valid_gid;
+       /* we can't chroot if we want to switch between users. there's not
+          much point either (from security point of view) */
+       rset.chroot_dir = *set->mail_chroot == '\0' || keep_setuid_root ?
+               NULL : set->mail_chroot;
+       rset.system_groups_user = system_groups_user;
+
+       if (disallow_root &&
+           (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0)))
+               i_fatal("Mail access not allowed for root");
+
+       if (keep_setuid_root && current_euid != rset.uid) {
+               if (current_euid != 0) {
+                       /* we're changing the UID, switch back to root first */
+                       if (seteuid(0) < 0)
+                               i_fatal("seteuid(0) failed: %m");
+               }
+               setuid_uid = rset.uid;
+               rset.uid = (uid_t)-1;
+       }
+       restrict_access(&rset, *set->mail_home == '\0' ? NULL : set->mail_home,
+                       disallow_root);
+       if (keep_setuid_root) {
+               if (seteuid(setuid_uid) < 0)
+                       i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
+       }
+}
+
+static void
+mail_storage_service_init_settings(struct master_service *service,
+                                  const struct setting_parser_info *set_root,
+                                  bool preserve_home)
+{
+       const struct setting_parser_info *set_roots[3];
+       const char *error;
+
+       (void)umask(0077);
+
+        mail_storage_init();
+       mail_storage_register_all();
+       mailbox_list_register_all();
+
+       set_roots[0] = &mail_user_setting_parser_info;
+       set_roots[1] = set_root;
+       set_roots[2] = NULL;
+
+       /* read settings after registering storages so they can have their
+          own setting definitions too */
+       if (master_service_settings_read(service, set_roots,
+                                        mail_storage_get_dynamic_parsers(),
+                                        preserve_home, &error) < 0)
+               i_fatal("Error reading configuration: %s", error);
+}
+
+static int
+mail_storage_service_init_post(struct master_service *service, const char *user,
+                              const struct mail_user_settings *user_set,
+                              struct mail_user **mail_user_r,
+                              const char **error_r)
+{
+       const struct mail_storage_settings *mail_set;
+       struct mail_user *mail_user;
+       const char *home;
+
+       mail_set = mail_user_set_get_storage_set(user_set);
+
+       /* If possible chdir to home directory, so that core file
+          could be written in case we crash. */
+       home = user_set->mail_home;
+       if (*home != '\0') {
+               if (chdir(home) < 0) {
+                       if (errno != ENOENT)
+                               i_error("chdir(%s) failed: %m", home);
+                       else if (mail_set->mail_debug)
+                               i_info("Home dir not found: %s", home);
+               }
+       }
+
+       mail_user = mail_user_alloc(user, user_set);
+       if (*home != '\0')
+               mail_user_set_home(mail_user, home);
+       mail_user_set_vars(mail_user, geteuid(), service->name, NULL, NULL);
+       if (mail_user_init(mail_user, error_r) < 0 ||
+           mail_namespaces_init(mail_user, error_r) < 0) {
+               *error_r = t_strdup(*error_r);
+               mail_user_unref(&mail_user);
+               return -1;
+       }
+       *mail_user_r = mail_user;
+       return 0;
+}
+
+struct mail_user *
+mail_storage_service_init_user(struct master_service *service, const char *user,
+                              const struct setting_parser_info *set_root,
+                              enum mail_storage_service_flags flags)
+{
+       const struct master_service_settings *set;
+       const struct mail_user_settings *user_set;
+       const struct mail_storage_settings *mail_set;
+       struct mail_user *mail_user;
+       void **sets;
+       const char *orig_user, *home, *system_groups_user, *error;
+       unsigned int len;
+       bool userdb_lookup;
+
+       userdb_lookup = (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0;
+       mail_storage_service_init_settings(service, set_root, !userdb_lookup);
+
+       /* now that we've read settings, we can set up logging */
+       master_service_init_log(service,
+               t_strdup_printf("%s(%s): ", service->name, user));
+
+       set = master_service_settings_get(service);
+       sets = master_service_settings_get_others(service);
+       user_set = sets[0];
+       mail_set = mail_user_set_get_storage_set(user_set);
+
+       if (userdb_lookup) {
+               /* userdb lookup may change settings, do it as soon as
+                  possible. */
+               orig_user = user;
+               if (service_auth_userdb_lookup(service, mail_set->mail_debug,
+                                              user_set, &user,
+                                              &system_groups_user,
+                                              &error) <= 0) {
+                       i_fatal("%s", error);
+               }
+       } else {
+               home = getenv("HOME");
+               system_groups_user = NULL;
+               if (*user_set->mail_home == '\0' && home != NULL)
+                       master_service_set(service, "mail_home", home);
+       }
+       home = user_set->mail_home;
+
+       len = strlen(user_set->mail_chroot);
+       if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
+           strncmp(home, user_set->mail_chroot, len - 2) == 0) {
+               /* If chroot ends with "/.", strip chroot dir from home dir */
+               home += len - 2;
+               master_service_set(service, "mail_home", home);
+       }
+
+       modules = *user_set->mail_plugins == '\0' ? NULL :
+               module_dir_load(user_set->mail_plugin_dir,
+                               user_set->mail_plugins, TRUE,
+                               master_service_get_version_string(service));
+
+       service_drop_privileges(user_set, system_groups_user,
+               (flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, FALSE);
+       /* privileges are now dropped */
+
+       dict_drivers_register_builtin();
+       module_dir_init(modules);
+       mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
+       if (mail_storage_service_init_post(service, user, user_set,
+                                          &mail_user, &error) < 0)
+               i_fatal("%s", error);
+       return mail_user;
+}
+
+void mail_storage_service_deinit_user(void)
+{
+       module_dir_unload(&modules);
+       mail_storage_deinit();
+       mail_users_deinit();
+       dict_drivers_unregister_builtin();
+}
+
+struct mail_storage_service_multi_ctx *
+mail_storage_service_multi_init(struct master_service *service,
+                               const struct setting_parser_info *set_root,
+                               enum mail_storage_service_flags flags)
+{
+       struct mail_storage_service_multi_ctx *ctx;
+       const struct master_service_settings *set;
+       const struct mail_user_settings *user_set;
+       const struct mail_storage_settings *mail_set;
+       void **sets;
+
+       ctx = i_new(struct mail_storage_service_multi_ctx, 1);
+       ctx->service = service;
+       ctx->flags = flags;
+
+       mail_storage_service_init_settings(service, set_root, FALSE);
+
+       /* do all the global initialization. delay initializing plugins until
+          we drop privileges the first time. */
+       master_service_init_log(service,
+                               t_strdup_printf("%s: ", service->name));
+
+       set = master_service_settings_get(service);
+       sets = master_service_settings_get_others(service);
+       user_set = sets[0];
+       mail_set = mail_user_set_get_storage_set(user_set);
+
+       modules = *user_set->mail_plugins == '\0' ? NULL :
+               module_dir_load(user_set->mail_plugin_dir,
+                               user_set->mail_plugins, TRUE,
+                               master_service_get_version_string(service));
+
+       dict_drivers_register_builtin();
+       mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
+       return ctx;
+}
+
+int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
+                                   const char *user,
+                                   struct mail_user **mail_user_r,
+                                   const char **error_r)
+{
+       const struct mail_user_settings *user_set;
+       const struct mail_storage_settings *mail_set;
+       const char *orig_user, *system_groups_user;
+       void **sets;
+       unsigned int len;
+       int ret;
+
+       sets = master_service_settings_get_others(ctx->service);
+       user_set = sets[0];
+       mail_set = mail_user_set_get_storage_set(user_set);
+
+       if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
+               orig_user = user;
+               ret = service_auth_userdb_lookup(ctx->service,
+                                                mail_set->mail_debug,
+                                                user_set, &user,
+                                                &system_groups_user,
+                                                error_r);
+               if (ret <= 0)
+                       return ret;
+       } else {
+               system_groups_user = NULL;
+       }
+
+       service_drop_privileges(user_set, system_groups_user,
+               (ctx->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, TRUE);
+
+       if (!ctx->modules_initialized) {
+               /* privileges dropped for the first time. initialize the
+                  modules now to avoid code running as root. */
+               module_dir_init(modules);
+               ctx->modules_initialized = TRUE;
+       }
+
+       /* we couldn't do chrooting, so if chrooting was enabled fix
+          the home directory */
+       len = strlen(user_set->mail_chroot);
+       if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
+           strncmp(user_set->mail_home, user_set->mail_chroot, len - 2) == 0) {
+               /* home dir already contains the chroot dir */
+       } else if (len > 0) {
+               master_service_set(ctx->service, "mail_home",
+                                  t_strconcat(user_set->mail_chroot, "/",
+                                              user_set->mail_home, NULL));
+       }
+       if (mail_storage_service_init_post(ctx->service, user,
+                                          user_set, mail_user_r, error_r) < 0)
+               return -1;
+       return 1;
+}
+
+void mail_storage_service_multi_deinit(struct mail_storage_service_multi_ctx **_ctx)
+{
+       struct mail_storage_service_multi_ctx *ctx = *_ctx;
+
+       *_ctx = NULL;
+       i_free(ctx);
+       mail_storage_service_deinit_user();
+}
+
+void *mail_storage_service_get_settings(struct master_service *service)
+{
+       void **sets;
+
+       sets = master_service_settings_get_others(service);
+       return sets[1];
+}
diff --git a/src/lib-storage/mail-storage-service.h b/src/lib-storage/mail-storage-service.h
new file mode 100644 (file)
index 0000000..2e6a035
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef MAIL_STORAGE_SERVICE_H
+#define MAIL_STORAGE_SERVICE_H
+
+enum mail_storage_service_flags {
+       MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT         = 0x01,
+       MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP         = 0x02
+};
+
+struct setting_parser_info;
+
+struct mail_user *
+mail_storage_service_init_user(struct master_service *service, const char *user,
+                              const struct setting_parser_info *set_root,
+                              enum mail_storage_service_flags flags);
+void mail_storage_service_deinit_user(void);
+
+struct mail_storage_service_multi_ctx *
+mail_storage_service_multi_init(struct master_service *service,
+                               const struct setting_parser_info *set_root,
+                               enum mail_storage_service_flags flags);
+/* Returns 1 if ok, 0 if user wasn't found, -1 if error. */
+int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
+                                   const char *user,
+                                   struct mail_user **mail_user_r,
+                                   const char **error_r);
+void mail_storage_service_multi_deinit(struct mail_storage_service_multi_ctx **ctx);
+
+/* Return the settings pointed to by set_root parameter in _init() */
+void *mail_storage_service_get_settings(struct master_service *service);
+
+#endif
index 42ed2c13faef63c78db549112843af6db4d32be3..c5befd02c0426e38191adb76519a6ffabdbbe4a9 100644 (file)
 
 #include <stddef.h>
 
+#define MAIL_STORAGE_SET_DRIVER_NAME "MAIL"
+
 static bool mail_storage_settings_check(void *_set, pool_t pool, const char **error_r);
 static bool namespace_settings_check(void *_set, pool_t pool, const char **error_r);
+static bool mail_user_settings_check(void *_set, pool_t pool, const char **error_r);
 
 #undef DEF
 #define DEF(type, name) \
@@ -127,6 +130,25 @@ struct setting_parser_info mail_namespace_setting_parser_info = {
          offsetof(struct mail_user_settings, field), defines }
 
 static struct setting_define mail_user_setting_defines[] = {
+       DEF(SET_STR, base_dir),
+       DEF(SET_STR, auth_socket_path),
+
+       DEF(SET_STR, mail_uid),
+       DEF(SET_STR, mail_gid),
+       DEF(SET_STR_VARS, mail_home),
+       DEF(SET_STR, mail_chroot),
+       DEF(SET_STR, mail_access_groups),
+       DEF(SET_STR, mail_privileged_group),
+       DEF(SET_STR, valid_chroot_dirs),
+
+       DEF(SET_UINT, first_valid_uid),
+       DEF(SET_UINT, last_valid_uid),
+       DEF(SET_UINT, first_valid_gid),
+       DEF(SET_UINT, last_valid_gid),
+
+       DEF(SET_STR, mail_plugins),
+       DEF(SET_STR, mail_plugin_dir),
+
        DEFLIST(namespaces, "namespace", &mail_namespace_setting_parser_info),
        { SET_STRLIST, "plugin", offsetof(struct mail_user_settings, plugin_envs), NULL },
 
@@ -134,6 +156,25 @@ static struct setting_define mail_user_setting_defines[] = {
 };
 
 static struct mail_user_settings mail_user_default_settings = {
+       MEMBER(base_dir) PKG_RUNDIR,
+       MEMBER(auth_socket_path) "auth-master",
+
+       MEMBER(mail_uid) "",
+       MEMBER(mail_gid) "",
+       MEMBER(mail_home) "",
+       MEMBER(mail_chroot) "",
+       MEMBER(mail_access_groups) "",
+       MEMBER(mail_privileged_group) "",
+       MEMBER(valid_chroot_dirs) "",
+
+       MEMBER(first_valid_uid) 500,
+       MEMBER(last_valid_uid) 0,
+       MEMBER(first_valid_gid) 1,
+       MEMBER(last_valid_gid) 0,
+
+       MEMBER(mail_plugins) "",
+       MEMBER(mail_plugin_dir) MODULEDIR,
+
        MEMBER(namespaces) ARRAY_INIT,
        MEMBER(plugin_envs) ARRAY_INIT
 };
@@ -147,7 +188,8 @@ struct setting_parser_info mail_user_setting_parser_info = {
 
        MEMBER(parent_offset) (size_t)-1,
        MEMBER(type_offset) (size_t)-1,
-       MEMBER(struct_size) sizeof(struct mail_user_settings)
+       MEMBER(struct_size) sizeof(struct mail_user_settings),
+       MEMBER(check_func) mail_user_settings_check
 };
 
 const void *
@@ -165,6 +207,13 @@ mail_user_set_get_driver_settings(const struct mail_user_settings *set,
        return dset;
 }
 
+const struct mail_storage_settings *
+mail_user_set_get_storage_set(const struct mail_user_settings *set)
+{
+       return mail_user_set_get_driver_settings(set,
+                                                MAIL_STORAGE_SET_DRIVER_NAME);
+}
+
 const void *mail_storage_get_driver_settings(struct mail_storage *storage)
 {
        return mail_user_set_get_driver_settings(storage->ns->user->set,
@@ -189,7 +238,7 @@ mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
        return index_flags;
 }
 
-void mail_storage_namespace_defines_init(pool_t pool)
+const struct dynamic_settings_parser *mail_storage_get_dynamic_parsers(void)
 {
        struct dynamic_settings_parser *parsers;
        struct mail_storage *const *storages;
@@ -197,7 +246,7 @@ void mail_storage_namespace_defines_init(pool_t pool)
 
        storages = array_get(&mail_storage_classes, &count);
        parsers = t_new(struct dynamic_settings_parser, count + 1);
-       parsers[0].name = "MAIL";
+       parsers[0].name = MAIL_STORAGE_SET_DRIVER_NAME;
        parsers[0].info = &mail_storage_setting_parser_info;
 
        for (i = 0, j = 1; i < count; i++) {
@@ -208,8 +257,14 @@ void mail_storage_namespace_defines_init(pool_t pool)
                parsers[j].info = storages[i]->v.get_setting_parser_info();
                j++;
        }
+       return parsers;
+}
 
-       settings_parser_info_update(pool, parsers[j-1].info->parent, parsers);
+static void
+fix_base_path(struct mail_user_settings *set, pool_t pool, const char **str)
+{
+       if (*str != NULL && **str != '\0' && **str != '/')
+               *str = p_strconcat(pool, set->base_dir, "/", *str, NULL);
 }
 
 /* <settings checks> */
@@ -269,4 +324,23 @@ static bool namespace_settings_check(void *_set, pool_t pool ATTR_UNUSED,
        }
        return TRUE;
 }
+
+static bool mail_user_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+                                    const char **error_r)
+{
+       struct mail_user_settings *set = _set;
+
+#ifndef CONFIG_BINARY
+       fix_base_path(set, pool, &set->auth_socket_path);
+#endif
+
+       if (*set->mail_plugins != '\0' &&
+           access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
+               *error_r = t_strdup_printf(
+                       "mail_plugin_dir: access(%s) failed: %m",
+                       set->mail_plugin_dir);
+               return FALSE;
+       }
+       return TRUE;
+}
 /* </settings checks> */
index 286ccad5cccb835ad392a04769434ab7016928e4..d6f24d66f73ea5504675caa5ebafababd8868f30 100644 (file)
@@ -40,6 +40,23 @@ struct mail_namespace_settings {
 };
 
 struct mail_user_settings {
+       const char *base_dir;
+       const char *auth_socket_path;
+
+       const char *mail_uid;
+       const char *mail_gid;
+       const char *mail_home;
+       const char *mail_chroot;
+       const char *mail_access_groups;
+       const char *mail_privileged_group;
+       const char *valid_chroot_dirs;
+
+       unsigned int first_valid_uid, last_valid_uid;
+       unsigned int first_valid_gid, last_valid_gid;
+
+       const char *mail_plugins;
+       const char *mail_plugin_dir;
+
        ARRAY_DEFINE(namespaces, struct mail_namespace_settings *);
        ARRAY_DEFINE(plugin_envs, const char *);
 };
@@ -52,11 +69,13 @@ extern struct mail_namespace_settings mail_namespace_default_settings;
 const void *
 mail_user_set_get_driver_settings(const struct mail_user_settings *set,
                                  const char *driver);
+const struct mail_storage_settings *
+mail_user_set_get_storage_set(const struct mail_user_settings *set);
 const void *mail_storage_get_driver_settings(struct mail_storage *storage);
 
 enum mail_index_open_flags
 mail_storage_settings_to_index_flags(const struct mail_storage_settings *set);
 
-void mail_storage_namespace_defines_init(pool_t pool);
+const struct dynamic_settings_parser *mail_storage_get_dynamic_parsers(void);
 
 #endif
index 9a749ae0d94d8b588d3df2b6e5e5e9bf61052f6e..9e898ca489be15b75912d726b3e2a08be25a1ddf 100644 (file)
@@ -8,6 +8,7 @@
 #include "var-expand.h"
 #include "settings-parser.h"
 #include "auth-master.h"
+#include "master-service.h"
 #include "mail-storage-settings.h"
 #include "mail-namespace.h"
 #include "mail-storage.h"
@@ -35,7 +36,7 @@ struct mail_user *mail_user_alloc(const char *username,
        i_assert(username != NULL);
        i_assert(*username != '\0');
 
-       pool = pool_alloconly_create("mail user", 2048);
+       pool = pool_alloconly_create("mail user", 4096);
        user = p_new(pool, struct mail_user, 1);
        user->pool = pool;
        user->refcount = 1;
@@ -97,7 +98,7 @@ int mail_user_init(struct mail_user *user, const char **error_r)
        if (mail_user_expand_plugins_envs(user, error_r) < 0)
                return -1;
 
-       mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+       mail_set = mail_user_set_get_storage_set(user->set);
        user->mail_debug = mail_set->mail_debug;
 
        user->initialized = TRUE;
@@ -248,8 +249,7 @@ int mail_user_get_home(struct mail_user *user, const char **home_r)
 
        userdb_pool = pool_alloconly_create("userdb lookup", 512);
        ret = auth_master_user_lookup(auth_master_conn, user->username,
-                                     AUTH_SERVICE_INTERNAL,
-                                     userdb_pool, &reply);
+                                     "lib-storage", userdb_pool, &reply);
        if (ret < 0)
                *home_r = NULL;
        else {
@@ -264,18 +264,23 @@ int mail_user_get_home(struct mail_user *user, const char **home_r)
 }
 
 const char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
+{
+       return mail_user_set_plugin_getenv(user->set, name);
+}
+
+const char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
+                                       const char *name)
 {
        const char *const *envs;
-       unsigned int i, count, name_len = strlen(name);
+       unsigned int i, count;
 
-       if (!array_is_created(&user->set->plugin_envs))
+       if (!array_is_created(&set->plugin_envs))
                return NULL;
 
-       envs = array_get(&user->set->plugin_envs, &count);
-       for (i = 0; i < count; i++) {
-               if (strncmp(envs[i], name, name_len) == 0 &&
-                   envs[i][name_len] == '=')
-                       return envs[i] + name_len + 1;
+       envs = array_get(&set->plugin_envs, &count);
+       for (i = 0; i < count; i += 2) {
+               if (strcmp(envs[i], name) == 0)
+                       return envs[i+1];
        }
        return NULL;
 }
@@ -313,14 +318,6 @@ const char *mail_user_get_temp_prefix(struct mail_user *user)
 
 void mail_users_init(const char *auth_socket_path, bool debug)
 {
-       const char *base_dir;
-
-       if (auth_socket_path == NULL) {
-               base_dir = getenv("BASE_DIR");
-               if (base_dir == NULL)
-                       base_dir = PKG_RUNDIR;
-               auth_socket_path = t_strconcat(base_dir, "/auth-master", NULL);
-       }
        auth_master_conn = auth_master_init(auth_socket_path, debug);
 }
 
index bfd97f72ecebb7825cf2b189e2f892ba957b72c3..7dd9991ad5c0239d677a9bfeec2f2e1888d0e487 100644 (file)
@@ -91,6 +91,8 @@ int mail_user_get_home(struct mail_user *user, const char **home_r);
 const char *mail_user_get_temp_prefix(struct mail_user *user);
 /* If name exists in plugin_envs, return its value. */
 const char *mail_user_plugin_getenv(struct mail_user *user, const char *name);
+const char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
+                                       const char *name);
 
 /* Add more namespaces to user's namespaces. The ->next pointers may be
    changed, so the namespaces pointer will be updated to user->namespaces. */
index f307fef38607b90adc7a51e8a640e7b03fada1fe..c3306f90c1fc637a8e00b33bfeb3c03dde4990ee 100644 (file)
@@ -6,12 +6,12 @@ pkglibexec_PROGRAMS = ssl-build-param
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
        -I$(top_srcdir)/src/lib-settings \
+       -I$(top_srcdir)/src/lib-master \
        -DSYSCONFDIR=\""$(sysconfdir)"\" \
        -DPKG_RUNDIR=\""$(rundir)"\" \
        -DPKG_STATEDIR=\""$(statedir)"\" \
        -DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
        -DBINDIR=\""$(bindir)"\" \
-       -DMODULEDIR=\""$(moduledir)"\" \
        -DSSLDIR=\""$(ssldir)\""
 
 dovecot_LDADD = \
@@ -31,7 +31,6 @@ dovecot_SOURCES = \
        mail-process.c \
        master-settings.c \
        main.c \
-       syslog-util.c \
        ssl-init.c \
        sysinfo-get.c
 
@@ -49,7 +48,6 @@ noinst_HEADERS = \
        mail-process.h \
        master-login-interface.h \
        master-settings.h \
-       syslog-util.h \
        ssl-init.h \
        sysinfo-get.h
 
index 0851ee7b1a09a35713023d011f1b506b844f4d32..dafbee020ccac844ec311d1ad3d719ec2d8ed67b 100644 (file)
@@ -6,7 +6,6 @@
 #include "hash.h"
 #include "str.h"
 #include "env-util.h"
-#include "syslog-util.h"
 #include "child-process.h"
 
 #include <unistd.h>
@@ -44,8 +43,6 @@ void child_process_remove(pid_t pid)
 
 void child_process_init_env(const struct master_settings *set)
 {
-       int facility;
-
        /* remove all environment, we don't need them */
        env_clean();
 
@@ -54,11 +51,6 @@ void child_process_init_env(const struct master_settings *set)
        if (env_tz != NULL)
                env_put(t_strconcat("TZ=", env_tz, NULL));
 
-       if (master_set == NULL ||
-           !syslog_facility_find(set->syslog_facility, &facility))
-               facility = LOG_MAIL;
-       env_put(t_strdup_printf("SYSLOG_FACILITY=%d", facility));
-
        if (master_set != NULL && !set->version_ignore)
                env_put("DOVECOT_VERSION="PACKAGE_VERSION);
 #ifdef DEBUG
index a8296266c09ca60c5fa4f8aaa453f090473adbc7..5a25bf63b77d1d0c177e96a25ced11732864465b 100644 (file)
@@ -2,11 +2,10 @@ pkglibexecdir = $(libexecdir)/dovecot
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
-       -I$(top_srcdir)/src/lib-settings \
+       -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-index \
        -I$(top_srcdir)/src/lib-storage \
-       -I$(top_srcdir)/src/lib-storage/index \
        -DPKG_RUNDIR=\""$(rundir)"\"
 
 lib20_convert_plugin_la_LDFLAGS = -module -avoid-version
@@ -19,14 +18,12 @@ lib20_convert_plugin_la_SOURCES = \
        convert-plugin.c
 
 noinst_HEADERS = \
-       convert-settings.h \
        convert-storage.h \
        convert-plugin.h
 
 pkglibexec_PROGRAMS = convert-tool
 
 convert_tool_SOURCES = \
-       convert-settings.c \
        convert-tool.c
 
 common_objects = \
diff --git a/src/plugins/convert/convert-settings.c b/src/plugins/convert/convert-settings.c
deleted file mode 100644 (file)
index 16eafce..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "settings-parser.h"
-#include "mail-storage-settings.h"
-#include "convert-settings.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#undef DEF
-#define DEF(type, name) \
-       { type, #name, offsetof(struct convert_settings, name), NULL }
-
-static struct setting_define convert_setting_defines[] = {
-       DEF(SET_STR, base_dir),
-       DEF(SET_STR, auth_socket_path),
-
-       { SET_STRLIST, "plugin", offsetof(struct convert_settings, plugin_envs), NULL },
-
-       SETTING_DEFINE_LIST_END
-};
-
-static struct convert_settings convert_default_settings = {
-       MEMBER(base_dir) PKG_RUNDIR,
-       MEMBER(auth_socket_path) "auth-master"
-};
-
-struct setting_parser_info convert_setting_parser_info = {
-       MEMBER(defines) convert_setting_defines,
-       MEMBER(defaults) &convert_default_settings,
-
-       MEMBER(parent) NULL,
-       MEMBER(dynamic_parsers) NULL,
-
-       MEMBER(parent_offset) (size_t)-1,
-       MEMBER(type_offset) (size_t)-1,
-       MEMBER(struct_size) sizeof(struct convert_settings)
-};
-
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct convert_settings *set, const char **str)
-{
-       if (*str != NULL && **str != '\0' && **str != '/') {
-               *str = p_strconcat(settings_pool,
-                                  set->base_dir, "/", *str, NULL);
-       }
-}
-
-void convert_settings_read(const struct convert_settings **set_r,
-                          const struct mail_user_settings **user_set_r)
-{
-       static const struct setting_parser_info *roots[] = {
-                &convert_setting_parser_info,
-                &mail_user_setting_parser_info
-       };
-       struct setting_parser_context *parser;
-       struct convert_settings *set;
-       void **sets;
-
-       if (settings_pool == NULL)
-               settings_pool = pool_alloconly_create("convert settings", 1024);
-       else
-               p_clear(settings_pool);
-
-       mail_storage_namespace_defines_init(settings_pool);
-
-       parser = settings_parser_init_list(settings_pool,
-                               roots, N_ELEMENTS(roots),
-                               SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
-       if (settings_parse_environ(parser) < 0) {
-               i_fatal("Error reading configuration: %s",
-                       settings_parser_get_error(parser));
-       }
-
-       sets = settings_parser_get_list(parser);
-       set = sets[0];
-       fix_base_path(set, &set->auth_socket_path);
-
-       *set_r = set;
-       *user_set_r = sets[1];
-       settings_parser_deinit(&parser);
-}
diff --git a/src/plugins/convert/convert-settings.h b/src/plugins/convert/convert-settings.h
deleted file mode 100644 (file)
index 8bb2e1e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef CONVERT_SETTINGS_H
-#define CONVERT_SETTINGS_H
-
-struct mail_user_settings;
-
-struct convert_settings {
-       const char *base_dir;
-       const char *auth_socket_path;
-
-       ARRAY_DEFINE(plugin_envs, const char *);
-};
-
-void convert_settings_read(const struct convert_settings **set_r,
-                          const struct mail_user_settings **user_set_r);
-
-#endif
index 1fb51548b633a97a3e4a1f5de06bfb378c4ba652..0ba2de2f4b6d871ce9574fcf9d0d0113eb3b93d2 100644 (file)
@@ -1,64 +1,58 @@
 /* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "ioloop.h"
-#include "randgen.h"
-#include "lib-signals.h"
+#include "env-util.h"
+#include "master-service.h"
 #include "mail-namespace.h"
-#include "mail-storage-private.h"
-#include "convert-settings.h"
+#include "mail-storage.h"
+#include "mail-storage-service.h"
 #include "convert-storage.h"
 
 #include <stdlib.h>
+#include <unistd.h>
 
 #define USAGE_STRING \
 "Usage: <username> <home dir> <source mail env> <dest mail env>\n" \
 "       [skip_broken_mailboxes] [skip_dotfiles] [alt_hierarchy_char=<c>]"
 
-int main(int argc, const char *argv[])
+int main(int argc, char *argv[])
 {
-       struct ioloop *ioloop;
+       struct master_service *service;
        struct mail_user *user;
-       const struct convert_settings *set;
-       const struct mail_user_settings *user_set;
-       const struct mail_storage_settings *mail_set;
-       struct convert_plugin_settings set2;
+       struct convert_plugin_settings set;
        struct mail_namespace *dest_ns;
        struct mail_namespace_settings ns_set;
        const char *error;
-       int i, ret = 0;
+       int i, c, ret = 0;
 
-       lib_init();
-       lib_signals_init();
-       random_init();
-       mail_storage_init();
-       mail_storage_register_all();
-       mailbox_list_register_all();
+       service = master_service_init("convert-tool",
+                                     MASTER_SERVICE_FLAG_STANDALONE,
+                                     argc, argv);
 
-       convert_settings_read(&set, &user_set);
-       mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
-       mail_users_init(set->auth_socket_path, mail_set->mail_debug);
-
-       if (argc <= 4)
+       while ((c = getopt(argc, argv, master_service_getopt_string())) > 0) {
+               if (!master_service_parse_option(service, c, optarg))
+                       i_fatal(USAGE_STRING);
+       }
+       if (argc - optind < 4)
                i_fatal(USAGE_STRING);
 
-       ioloop = io_loop_create();
+       env_put(t_strconcat("HOME=", argv[optind+1], NULL));
 
-       memset(&set2, 0, sizeof(set2));
-       for (i = 5; i < argc; i++) {
+       memset(&set, 0, sizeof(set));
+       for (i = optind + 4; i < argc; i++) {
                if (strcmp(argv[i], "skip_broken_mailboxes") != 0)
-                       set2.skip_broken_mailboxes = TRUE;
+                       set.skip_broken_mailboxes = TRUE;
                else if (strcmp(argv[i], "skip_dotdirs") != 0)
-                       set2.skip_dotdirs = TRUE;
+                       set.skip_dotdirs = TRUE;
                else if (strncmp(argv[i], "alt_hierarchy_char=", 19) != 0)
-                       set2.alt_hierarchy_char = argv[i][19];
+                       set.alt_hierarchy_char = argv[i][19];
+               else
+                       i_fatal(USAGE_STRING);
        }
 
-       user = mail_user_alloc(argv[1], user_set);
-       mail_user_set_home(user, argv[2]);
-       mail_user_set_vars(user, geteuid(), "convert", NULL, NULL);
-       if (mail_user_init(user, &error) < 0)
-               i_fatal("Mail user initialization failed: %s", error);
+       master_service_init_log(service,
+               t_strdup_printf("convert-tool(%s): ", argv[optind]));
+       user = mail_storage_service_init_user(service, argv[optind], NULL, 0);
 
        memset(&ns_set, 0, sizeof(ns_set));
        ns_set.location = argv[4];
@@ -71,19 +65,16 @@ int main(int argc, const char *argv[])
                        "mail storage with data '%s': %s", argv[4], error);
        }
 
-       ret = convert_storage(argv[3], dest_ns, &set2);
+       ret = convert_storage(argv[3], dest_ns, &set);
        if (ret > 0)
                i_info("Successfully converted");
        else if (ret == 0)
                i_error("Source storage not found");
        else
                i_error("Internal failure");
-       mail_user_unref(&user);
 
-       io_loop_destroy(&ioloop);
-       mail_storage_deinit();
-       mail_users_deinit();
-       lib_signals_deinit();
-       lib_deinit();
+       mail_user_unref(&user);
+       mail_storage_service_deinit_user();
+       master_service_deinit(&service);
        return ret <= 0 ? 1 : 0;
 }
index 4a4e7a0c60c3a14aaf8e7a7bc4634eefe714a5bd..0877b17bfeab077cb7f2173ad7faf9cba7850fb4 100644 (file)
@@ -3,8 +3,9 @@ pkglibexecdir = $(libexecdir)/dovecot
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
        -I$(top_srcdir)/src/lib-auth \
-       -I$(top_srcdir)/src/lib-settings \
        -I$(top_srcdir)/src/lib-dict \
+       -I$(top_srcdir)/src/lib-settings \
+       -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-index \
@@ -22,22 +23,18 @@ lib20_expire_plugin_la_SOURCES = \
        expire-plugin.c
 
 noinst_HEADERS = \
-       auth-client.h \
        expire-env.h \
-       expire-plugin.h \
-       expire-settings.h
+       expire-plugin.h
 
 pkglibexec_PROGRAMS = expire-tool
 
 expire_tool_SOURCES = \
-       auth-client.c \
-       expire-settings.c \
        expire-tool.c
 
 libs = \
        $(top_builddir)/src/lib-storage/libdovecot-storage.la \
        $(top_builddir)/src/lib-dovecot/libdovecot.la
 
-expire_tool_LDADD = $(libs)
+expire_tool_LDADD = $(libs) expire-env.o
 
 expire_tool_DEPENDENCIES = $(libs)
index bdae7424fc2ba3b24ecbebd23d7b176e27f9e7c0..86ee2dff26080062c0dbeeee9cc27beb13bc86ba 100644 (file)
@@ -82,7 +82,7 @@ int auth_client_put_user_env(struct auth_master_connection *conn,
        int ret;
 
        pool = pool_alloconly_create("userdb lookup", 512);
-       ret = auth_master_user_lookup(conn, user, AUTH_SERVICE_INTERNAL,
+       ret = auth_master_user_lookup(conn, user, MASTER_SERVICE_INTERNAL,
                                      pool, &reply);
        if (ret > 0)
                auth_set_env(user, &reply);
diff --git a/src/plugins/expire/expire-settings.c b/src/plugins/expire/expire-settings.c
deleted file mode 100644 (file)
index 818085b..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "settings-parser.h"
-#include "mail-storage-settings.h"
-#include "expire-settings.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#undef DEF
-#define DEF(type, name) \
-       { type, #name, offsetof(struct expire_settings, name), NULL }
-
-static struct setting_define expire_setting_defines[] = {
-       DEF(SET_STR, base_dir),
-       DEF(SET_STR, auth_socket_path),
-
-       { SET_STRLIST, "plugin", offsetof(struct expire_settings, plugin_envs), NULL },
-
-       SETTING_DEFINE_LIST_END
-};
-
-static struct expire_settings expire_default_settings = {
-       MEMBER(base_dir) PKG_RUNDIR,
-       MEMBER(auth_socket_path) "auth-master"
-};
-
-struct setting_parser_info expire_setting_parser_info = {
-       MEMBER(defines) expire_setting_defines,
-       MEMBER(defaults) &expire_default_settings,
-
-       MEMBER(parent) NULL,
-       MEMBER(dynamic_parsers) NULL,
-
-       MEMBER(parent_offset) (size_t)-1,
-       MEMBER(type_offset) (size_t)-1,
-       MEMBER(struct_size) sizeof(struct expire_settings)
-};
-
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct expire_settings *set, const char **str)
-{
-       if (*str != NULL && **str != '\0' && **str != '/') {
-               *str = p_strconcat(settings_pool,
-                                  set->base_dir, "/", *str, NULL);
-       }
-}
-
-static void
-parse_expand_vars(struct setting_parser_context *parser, const char *value)
-{
-       const char *const *expanded;
-
-       expanded = t_strsplit(value, " ");
-       settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
-       /* settings from userdb are in the VARS_EXPANDED list. for each
-          unknown setting in the list assume it's a plugin setting. */
-       for (; *expanded != NULL; expanded++) {
-               if (settings_parse_is_valid_key(parser, *expanded))
-                       continue;
-
-               value = getenv(t_str_ucase(*expanded));
-               if (value == NULL)
-                       continue;
-
-               settings_parse_line(parser, t_strconcat("plugin/", *expanded,
-                                                       "=", value, NULL));
-       }
-}
-
-void expire_settings_read(const struct expire_settings **set_r,
-                         const struct mail_user_settings **user_set_r)
-{
-       static const struct setting_parser_info *roots[] = {
-                &expire_setting_parser_info,
-                &mail_user_setting_parser_info
-       };
-       struct setting_parser_context *parser;
-       struct expire_settings *set;
-       const char *value;
-       void **sets;
-
-       if (settings_pool == NULL)
-               settings_pool = pool_alloconly_create("expire settings", 1024);
-       else
-               p_clear(settings_pool);
-
-       mail_storage_namespace_defines_init(settings_pool);
-
-       parser = settings_parser_init_list(settings_pool,
-                               roots, N_ELEMENTS(roots),
-                               SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
-       if (settings_parse_environ(parser) < 0) {
-               i_fatal("Error reading configuration: %s",
-                       settings_parser_get_error(parser));
-       }
-
-       value = getenv("VARS_EXPANDED");
-       if (value != NULL)
-               parse_expand_vars(parser, value);
-
-       sets = settings_parser_get_list(parser);
-       set = sets[0];
-       fix_base_path(set, &set->auth_socket_path);
-
-       *set_r = set;
-       *user_set_r = sets[1];
-       settings_parser_deinit(&parser);
-}
diff --git a/src/plugins/expire/expire-settings.h b/src/plugins/expire/expire-settings.h
deleted file mode 100644 (file)
index 46e5c57..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef CONVERT_SETTINGS_H
-#define CONVERT_SETTINGS_H
-
-struct mail_user_settings;
-
-struct expire_settings {
-       const char *base_dir;
-       const char *auth_socket_path;
-
-       ARRAY_DEFINE(plugin_envs, const char *);
-};
-
-void expire_settings_read(const struct expire_settings **set_r,
-                         const struct mail_user_settings **user_set_r);
-
-#endif
index e0c832c25807692b7fe61c690fe567bfa5110c0b..92a51b2c1c08b00c898c7842e2c2f371111b6843 100644 (file)
@@ -1,73 +1,27 @@
 /* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "ioloop.h"
 #include "env-util.h"
-#include "file-lock.h"
-#include "randgen.h"
-#include "lib-signals.h"
 #include "dict.h"
+#include "master-service.h"
+#include "master-service-settings.h"
 #include "mail-index.h"
 #include "mail-search-build.h"
 #include "mail-storage.h"
+#include "mail-storage-service.h"
 #include "mail-namespace.h"
 #include "auth-client.h"
 #include "auth-master.h"
 #include "expire-env.h"
-#include "expire-settings.h"
 
 #include <stdlib.h>
 
-/* ugly, but automake doesn't like having it built as both static and
-   dynamic object.. */
-#include "expire-env.c"
-
 struct expire_context {
-       struct auth_master_connection *auth_conn;
-
-       char *user;
+       struct mail_storage_service_multi_ctx *multi;
        struct mail_user *mail_user;
-       const struct expire_settings *set;
        bool testrun;
 };
 
-static int user_init(struct expire_context *ctx, const char *user)
-{
-       const struct mail_user_settings *user_set;
-       const char *error;
-       int ret;
-
-       env_clean();
-       if ((ret = auth_client_put_user_env(ctx->auth_conn, user)) <= 0) {
-               if (ret < 0)
-                       return ret;
-
-               /* user no longer exists */
-               return 0;
-       }
-
-       expire_settings_read(&ctx->set, &user_set);
-
-       ctx->mail_user = mail_user_alloc(user, user_set);
-       mail_user_set_home(ctx->mail_user, getenv("HOME"));
-       mail_user_set_vars(ctx->mail_user, geteuid(), "expire", NULL, NULL);
-       if (mail_user_init(ctx->mail_user, &error) < 0) {
-               i_error("Mail user initialization failed: %s", error);
-               return -1;
-       }
-       if (mail_namespaces_init(ctx->mail_user, &error) < 0) {
-               i_error("Namespace initialization failed: %s", error);
-               return -1;
-       }
-       return 1;
-}
-
-static void user_deinit(struct expire_context *ctx)
-{
-       mail_user_unref(&ctx->mail_user);
-       i_free_and_null(ctx->user);
-}
-
 static int
 mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
                         const char *mailbox,
@@ -89,15 +43,20 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
 
        *oldest_r = 0;
 
-       if (ctx->user != NULL && strcmp(user, ctx->user) != 0)
-               user_deinit(ctx);
-       if (ctx->user == NULL) {
-               if ((ret = user_init(ctx, user)) <= 0) {
-                       if (ctx->testrun)
-                               i_info("User lookup failed: %s", user);
+       if (ctx->mail_user != NULL &&
+           strcmp(user, ctx->mail_user->username) != 0)
+               mail_user_unref(&ctx->mail_user);
+       if (ctx->mail_user == NULL) {
+               i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ",
+                                                    user));
+               ret = mail_storage_service_multi_next(ctx->multi, user,
+                                                     &ctx->mail_user, &errstr);
+               if (ret <= 0) {
+                       if (ret < 0 || ctx->testrun)
+                               i_error("User init failed: %s", errstr);
                        return ret;
                }
-               ctx->user = i_strdup(user);
+               i_info("success: %s %d", ctx->mail_user->username, (int)geteuid());
        }
 
        ns_mailbox = mailbox;
@@ -190,61 +149,40 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
        return ret < 0 ? -1 : 0;
 }
 
-static const char *expire_getenv(struct expire_context *ctx, const char *name)
-{
-       const char *const *envs;
-       unsigned int i, count, name_len = strlen(name);
-
-       if (!array_is_created(&ctx->set->plugin_envs))
-               return NULL;
-
-       envs = array_get(&ctx->set->plugin_envs, &count);
-       for (i = 0; i < count; i++) {
-               if (strncmp(envs[i], name, name_len) == 0 &&
-                   envs[i][name_len] == '=')
-                       return envs[i] + name_len + 1;
-       }
-       return NULL;
-}
-
-static void expire_run(bool testrun)
+static void expire_run(struct master_service *service, bool testrun)
 {
        struct expire_context ctx;
        struct dict *dict = NULL;
-       struct dict_transaction_context *trans;
        const struct mail_user_settings *user_set;
-       const struct mail_storage_settings *mail_set;
+       void **sets;
+       struct dict_transaction_context *trans;
        struct dict_iterate_context *iter;
        struct expire_env *env;
        time_t oldest;
        unsigned int expunge_secs, altmove_secs;
-       const char *p, *key, *value;
-       const char *userp, *mailbox;
+       const char *p, *key, *value, *expire, *expire_altmove, *expire_dict;
+       const char *userp = NULL, *mailbox;
        int ret;
 
-       dict_drivers_register_builtin();
-       mail_storage_init();
-       mail_storage_register_all();
-       mailbox_list_register_all();
-
        memset(&ctx, 0, sizeof(ctx));
-       expire_settings_read(&ctx.set, &user_set);
-       mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
-       mail_users_init(ctx.set->auth_socket_path, mail_set->mail_debug);
+       ctx.multi = mail_storage_service_multi_init(service, NULL,
+                               MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP);
+
+       sets = master_service_settings_get_others(service);
+       user_set = sets[0];
 
-       if (expire_getenv(&ctx, "EXPIRE") == NULL &&
-           expire_getenv(&ctx, "EXPIRE_ALTMOVE") == NULL)
+       expire = mail_user_set_plugin_getenv(user_set, "expire");
+       expire_altmove = mail_user_set_plugin_getenv(user_set, "expire_altmove");
+       expire_dict = mail_user_set_plugin_getenv(user_set, "expire_dict");
+
+       if (expire == NULL && expire_altmove == NULL)
                i_fatal("expire and expire_altmove settings not set");
-       if (expire_getenv(&ctx, "EXPIRE_DICT") == NULL)
+       if (expire_dict == NULL)
                i_fatal("expire_dict setting not set");
 
        ctx.testrun = testrun;
-       ctx.auth_conn = auth_master_init(ctx.set->auth_socket_path,
-                                        mail_set->mail_debug);
-       env = expire_env_init(expire_getenv(&ctx, "EXPIRE"),
-                             expire_getenv(&ctx, "EXPIRE_ALTMOVE"));
-       dict = dict_init(expire_getenv(&ctx, "EXPIRE_DICT"),
-                        DICT_DATA_TYPE_UINT32, "");
+       env = expire_env_init(expire, expire_altmove);
+       dict = dict_init(expire_dict, DICT_DATA_TYPE_UINT32, "");
        if (dict == NULL)
                i_fatal("dict_init() failed");
 
@@ -321,6 +259,9 @@ static void expire_run(bool testrun)
                        }
                }
        }
+       if (testrun && userp == NULL)
+               i_info("No entries in dictionary");
+
        dict_iterate_deinit(&iter);
        if (!testrun)
                dict_transaction_commit(&trans);
@@ -328,37 +269,39 @@ static void expire_run(bool testrun)
                dict_transaction_rollback(&trans);
        dict_deinit(&dict);
 
-       if (ctx.user != NULL)
-               user_deinit(&ctx);
-       auth_master_deinit(&ctx.auth_conn);
-
-       mail_storage_deinit();
-       mail_users_deinit();
-       dict_drivers_unregister_builtin();
+       if (ctx.mail_user != NULL)
+               mail_user_unref(&ctx.mail_user);
+       mail_storage_service_multi_deinit(&ctx.multi);
 }
 
-int main(int argc ATTR_UNUSED, const char *argv[])
+int main(int argc, char *argv[])
 {
-       struct ioloop *ioloop;
+       struct master_service *service;
+       const char *getopt_str;
        bool test = FALSE;
+       int c;
 
-       lib_init();
-       lib_signals_init();
-       random_init();
+       service = master_service_init("expire-tool",
+                                     MASTER_SERVICE_FLAG_STANDALONE,
+                                     argc, argv);
 
-       while (argv[1] != NULL) {
-               if (strcmp(argv[1], "--test") == 0)
+       getopt_str = t_strconcat("t", master_service_getopt_string(), NULL);
+       while ((c = getopt(argc, argv, getopt_str)) > 0) {
+               switch (c) {
+               case 't':
                        test = TRUE;
-               else
-                       i_fatal("Unknown parameter: %s", argv[1]);
-               argv++;
+                       break;
+               default:
+                       if (!master_service_parse_option(service, c, optarg))
+                               i_fatal("Unknown parameter: -%c", c);
+                       break;
+               }
        }
+       if (optind != argc)
+               i_fatal("Unknown parameter: %s", argv[optind]);
 
-       ioloop = io_loop_create();
-       expire_run(test);
-       io_loop_destroy(&ioloop);
+       expire_run(service, test);
 
-       lib_signals_deinit();
-       lib_deinit();
+       master_service_deinit(&service);
        return 0;
 }
index 8e9324ea8a041fb7ec9e9a03dca226020c313cf8..bd702a379af8f06da717d95f221dfb4958b3ffa0 100644 (file)
@@ -7,9 +7,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib-settings \
        -I$(top_srcdir)/src/lib-dict \
        -I$(top_srcdir)/src/lib-mail \
-       -I$(top_srcdir)/src/lib-storage \
-       -DPKG_RUNDIR=\""$(rundir)"\" \
-       -DMODULEDIR=\""$(moduledir)"\"
+       -I$(top_srcdir)/src/lib-storage
 
 pop3_LDFLAGS = -export-dynamic
 
index ec5c5e184ad338406369246c70ba7dced75a44ba..a9286b17d8d76d8e5bf3e0412b79a83710a9ed62 100644 (file)
@@ -173,9 +173,9 @@ static void main_preinit(const struct pop3_settings **set_r,
        pop3_settings_read(set_r, user_set_r);
 
        /* Load the plugins before chrooting. Their init() is called later. */
-       modules = *(*set_r)->mail_plugins == '\0' ? NULL :
-               module_dir_load((*set_r)->mail_plugin_dir,
-                               (*set_r)->mail_plugins, TRUE, version);
+       modules = *(*user_set_r)->mail_plugins == '\0' ? NULL :
+               module_dir_load((*user_set_r)->mail_plugin_dir,
+                               (*user_set_r)->mail_plugins, TRUE, version);
 
        restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
        restrict_access_allow_coredumps(TRUE);
@@ -214,7 +214,7 @@ static bool main_init(const struct pop3_settings *set,
        }
 
        dict_drivers_register_builtin();
-       mail_users_init(set->auth_socket_path, set->mail_debug);
+       mail_users_init(user_set->auth_socket_path, set->mail_debug);
        clients_init();
 
        module_dir_init(modules);
index f4c948bde950b6a4f14ac606963749f81e27c977..f74e55daebf09c40536c034e46361e40f96ba0ae 100644 (file)
@@ -9,8 +9,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-static bool pop3_settings_check(void *_set, pool_t pool, const char **error_r);
-
 #undef DEF
 #undef DEFLIST
 #define DEF(type, name) \
@@ -19,16 +17,10 @@ static bool pop3_settings_check(void *_set, pool_t pool, const char **error_r);
        { SET_DEFLIST, name, offsetof(struct pop3_settings, field), defines }
 
 static struct setting_define pop3_setting_defines[] = {
-       DEF(SET_STR, base_dir),
-       DEF(SET_STR, auth_socket_path),
-
        DEF(SET_BOOL, mail_debug),
        DEF(SET_BOOL, shutdown_clients),
        DEF(SET_BOOL, verbose_proctitle),
 
-       DEF(SET_STR, mail_plugins),
-       DEF(SET_STR, mail_plugin_dir),
-
        DEF(SET_BOOL, pop3_no_flag_updates),
        DEF(SET_BOOL, pop3_enable_last),
        DEF(SET_BOOL, pop3_reuse_xuidl),
@@ -41,16 +33,10 @@ static struct setting_define pop3_setting_defines[] = {
 };
 
 static struct pop3_settings pop3_default_settings = {
-       MEMBER(base_dir) PKG_RUNDIR,
-       MEMBER(auth_socket_path) "auth-master",
-
        MEMBER(mail_debug) FALSE,
        MEMBER(shutdown_clients) FALSE,
        MEMBER(verbose_proctitle) FALSE,
 
-       MEMBER(mail_plugins) "",
-       MEMBER(mail_plugin_dir) MODULEDIR,
-
        MEMBER(pop3_no_flag_updates) FALSE,
        MEMBER(pop3_enable_last) FALSE,
        MEMBER(pop3_reuse_xuidl) FALSE,
@@ -70,40 +56,11 @@ struct setting_parser_info pop3_setting_parser_info = {
        MEMBER(parent_offset) (size_t)-1,
        MEMBER(type_offset) (size_t)-1,
        MEMBER(struct_size) sizeof(struct pop3_settings),
-       MEMBER(check_func) pop3_settings_check
+       MEMBER(check_func) NULL
 };
 
 static pool_t settings_pool = NULL;
 
-static void fix_base_path(struct pop3_settings *set, const char **str)
-{
-       if (*str != NULL && **str != '\0' && **str != '/') {
-               *str = p_strconcat(settings_pool,
-                                  set->base_dir, "/", *str, NULL);
-       }
-}
-
-/* <settings checks> */
-static bool pop3_settings_check(void *_set, pool_t pool ATTR_UNUSED,
-                               const char **error_r)
-{
-       struct pop3_settings *set = _set;
-
-#ifndef CONFIG_BINARY
-       fix_base_path(set, &set->auth_socket_path);
-#endif
-
-       if (*set->mail_plugins != '\0' &&
-           access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
-               *error_r = t_strdup_printf(
-                       "mail_plugin_dir: access(%s) failed: %m",
-                       set->mail_plugin_dir);
-               return FALSE;
-       }
-       return TRUE;
-}
-/* </settings checks> */
-
 static void
 parse_expand_vars(struct setting_parser_context *parser, const char *value)
 {
@@ -142,7 +99,8 @@ void pop3_settings_read(const struct pop3_settings **set_r,
        else
                p_clear(settings_pool);
 
-       mail_storage_namespace_defines_init(settings_pool);
+       settings_parser_info_update(settings_pool,
+                                   mail_storage_get_dynamic_parsers());
 
        parser = settings_parser_init_list(settings_pool,
                                roots, N_ELEMENTS(roots),
index 12df00cc1aa3b246e0f69ee173b11a9243c1c686..30bb7b62df05585f2f3b5557e1c602dea3a682be 100644 (file)
@@ -4,16 +4,10 @@
 struct mail_user_settings;
 
 struct pop3_settings {
-       const char *base_dir;
-       const char *auth_socket_path;
-
        bool mail_debug;
        bool shutdown_clients;
        bool verbose_proctitle;
 
-       const char *mail_plugins;
-       const char *mail_plugin_dir;
-
        /* pop3: */
        bool pop3_no_flag_updates;
        bool pop3_enable_last;
index d4d7b141831c2c1d96ef1ce6791687c787646476..968626a925a0a6820867dbd2468085a54badafde 100644 (file)
@@ -10,14 +10,17 @@ pkglibexec_PROGRAMS = \
        maildirlock \
        threadview
 
-sbin_PROGRAMS = dovecotpw
+sbin_PROGRAMS = dovecotpw doveadm
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-auth \
+       -I$(top_srcdir)/src/lib-dict \
+       -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
        -I$(top_srcdir)/src/lib-index \
-       -I$(top_srcdir)/src/lib-storage/index/maildir \
+       -I$(top_srcdir)/src/lib-storage \
        -I$(top_srcdir)/src/auth
 
 rawlog_LDADD = \
@@ -70,3 +73,10 @@ dovecotpw_LDADD = \
 
 dovecotpw_SOURCES = \
        dovecotpw.c
+
+doveadm_LDADD = \
+       ../lib-dovecot/libdovecot.la \
+       ../lib-storage/libdovecot-storage.la
+doveadm_SOURCES = \
+       doveadm.c
+