]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added --exec-mail option to master. It can be used to parse Dovecot config
authorTimo Sirainen <tss@iki.fi>
Fri, 9 Jul 2004 19:59:02 +0000 (22:59 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 9 Jul 2004 19:59:02 +0000 (22:59 +0300)
file and exec() imap/pop3 process directly. Moved --inetd option into
environment as it's only for internal use.

--HG--
branch : HEAD

src/login-common/master.c
src/master/mail-process.c
src/master/mail-process.h
src/master/main.c
src/master/master-settings.c
src/master/master-settings.h

index 9f68449d6aac47d77607c5ebe7110ce0059ce46e..dc22ba1bd6145af4da8d562a859c517c5bcb42d0 100644 (file)
@@ -104,7 +104,7 @@ void master_close(void)
 
 static void master_exec(int fd)
 {
-       char *argv[] = { "dovecot", "--inetd", NULL };
+       char *argv[] = { "dovecot", NULL };
 
        switch (fork()) {
        case -1:
@@ -117,6 +117,7 @@ static void master_exec(int fd)
                if (setsid() < 0)
                        i_fatal("setsid() failed: %m");
 
+               env_put("DOVECOT_INETD=1");
                execv(SBINDIR"/dovecot", argv);
                i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
                               SBINDIR"/dovecot");
index 6207ccfc0c9b4374986a9d08942b7de6bb698688..72813220e9a39494c71e0279fe0d35034601f384 100644 (file)
@@ -75,10 +75,9 @@ static int validate_chroot(struct settings *set, const char *dir)
 }
 
 static const struct var_expand_table *
-get_var_expand_table(enum process_type process_type,
+get_var_expand_table(const char *protocol,
                     const char *user, const char *home,
-                    const struct ip_addr *local_ip,
-                    const struct ip_addr *remote_ip, pid_t pid)
+                    const char *local_ip, const char *remote_ip, pid_t pid)
 {
        static struct var_expand_table static_tab[] = {
                { 'u', NULL },
@@ -100,10 +99,10 @@ get_var_expand_table(enum process_type process_type,
        tab[1].value = t_strcut(user, '@');
        tab[2].value = strchr(user, '@');
        if (tab[2].value != NULL) tab[2].value++;
-       tab[3].value = t_str_ucase(process_names[process_type]);
+       tab[3].value = t_str_ucase(protocol);
        tab[4].value = home;
-       tab[5].value = net_ip2addr(local_ip);
-       tab[6].value = net_ip2addr(remote_ip);
+       tab[5].value = local_ip;
+       tab[6].value = remote_ip;
        tab[7].value = dec2str(pid);
 
        return tab;
@@ -180,6 +179,133 @@ env_put_namespace(struct namespace_settings *ns, const char *default_location,
        }
 }
 
+static void
+mail_process_set_environment(struct settings *set, const char *mail,
+                            const struct var_expand_table *var_expand_table)
+{
+       env_put(t_strconcat("MAIL_CACHE_FIELDS=",
+                           set->mail_cache_fields, NULL));
+       env_put(t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
+                           set->mail_never_cache_fields, NULL));
+       env_put(t_strdup_printf("MAILBOX_CHECK_INTERVAL=%u",
+                               set->mailbox_check_interval));
+       env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u",
+                               set->mailbox_idle_check_interval));
+       env_put(t_strconcat("CLIENT_WORKAROUNDS=",
+                           set->client_workarounds, NULL));
+       env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u",
+                               set->mail_max_keyword_length));
+       env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u",
+                               set->imap_max_line_length));
+       env_put(t_strconcat("IMAP_CAPABILITY=",
+                           set->imap_capability, NULL));
+
+       if (set->mail_save_crlf)
+               env_put("MAIL_SAVE_CRLF=1");
+       if (set->mail_read_mmaped)
+               env_put("MAIL_READ_MMAPED=1");
+       if (set->mmap_disable)
+               env_put("MMAP_DISABLE=1");
+       if (set->mmap_no_write)
+               env_put("MMAP_NO_WRITE=1");
+       if (set->fcntl_locks_disable)
+               env_put("FCNTL_LOCKS_DISABLE=1");
+       if (set->maildir_stat_dirs)
+               env_put("MAILDIR_STAT_DIRS=1");
+       if (set->maildir_copy_with_hardlinks)
+               env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
+       if (set->maildir_check_content_changes)
+               env_put("MAILDIR_CHECK_CONTENT_CHANGES=1");
+       if (set->mail_full_filesystem_access)
+               env_put("FULL_FILESYSTEM_ACCESS=1");
+       if (set->pop3_mails_keep_recent)
+               env_put("POP3_MAILS_KEEP_RECENT=1");
+       (void)umask(set->umask);
+
+       env_put(t_strconcat("MBOX_READ_LOCKS=", set->mbox_read_locks, NULL));
+       env_put(t_strconcat("MBOX_WRITE_LOCKS=", set->mbox_write_locks, NULL));
+       env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
+                               set->mbox_lock_timeout));
+       env_put(t_strdup_printf("MBOX_DOTLOCK_CHANGE_TIMEOUT=%u",
+                               set->mbox_dotlock_change_timeout));
+
+       if (set->mail_use_modules &&
+           set->mail_modules != NULL && *set->mail_modules != '\0') {
+               env_put(t_strconcat("MODULE_DIR=",
+                                   set->mail_modules, NULL));
+       }
+
+       /* user given environment - may be malicious. virtual_user comes from
+          auth process, but don't trust that too much either. Some auth
+          mechanism might allow leaving extra data there. */
+       if ((mail == NULL || *mail == '\0') && set->default_mail_env != NULL)
+               mail = expand_mail_env(set->default_mail_env, var_expand_table);
+       env_put(t_strconcat("MAIL=", mail, NULL));
+
+       if (set->server->namespaces != NULL) {
+               env_put_namespace(set->server->namespaces,
+                                 mail, var_expand_table);
+       }
+}
+
+static void mail_process_exec_set(struct settings *set, const char *title)
+{
+       const char *executable, *p, *argv[4];
+       int i;
+
+       /* very simple argument splitting. */
+       i = 0;
+       argv[i++] = executable = t_strcut(set->mail_executable, ' ');
+       argv[i] = strchr(set->mail_executable, ' ');
+       if (argv[i] != NULL) {
+               argv[i]++;
+               i++;
+       }
+       if (title[0] != '\0')
+               argv[i++] = title;
+       argv[i] = NULL;
+
+       /* hide the path, it's ugly */
+       p = strrchr(argv[0], '/');
+       if (p != NULL) argv[0] = p+1;
+
+       execv(executable, (char **) argv);
+}
+
+void mail_process_exec(const char *protocol, const char *section)
+{
+       struct server_settings *server = settings_root;
+       const struct var_expand_table *var_expand_table;
+       struct settings *set;
+
+       if (section != NULL) {
+               for (; server != NULL; server = server->next) {
+                       if (strcmp(server->name, section) == 0)
+                               break;
+               }
+               if (server == NULL)
+                       i_fatal("Section not found: '%s'", section);
+       }
+
+       if (strcmp(protocol, "imap") == 0)
+               set = server->imap;
+       else if (strcmp(protocol, "pop3") == 0)
+               set = server->pop3;
+       else
+               i_fatal("Unknown protocol: '%s'", protocol);
+
+       var_expand_table =
+               get_var_expand_table(protocol, getenv("USER"), getenv("HOME"),
+                                    getenv("TCPLOCALIP"),
+                                    getenv("TCPREMOTEIP"), getpid());
+
+       mail_process_set_environment(set, getenv("MAIL"), var_expand_table);
+       mail_process_exec_set(set, "");
+
+       i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
+                      set->mail_executable);
+}
+
 int create_mail_process(struct login_group *group, int socket,
                        const struct ip_addr *local_ip,
                        const struct ip_addr *remote_ip,
@@ -187,11 +313,9 @@ int create_mail_process(struct login_group *group, int socket,
 {
        struct settings *set = group->set;
        const struct var_expand_table *var_expand_table;
-       const char *argv[4];
        const char *addr, *mail, *user, *chroot_dir, *home_dir, *full_home_dir;
-       const char *executable, *p;
-       struct log_io *log;
        char title[1024];
+       struct log_io *log;
        string_t *str;
        pid_t pid;
        int i, err, ret, log_fd;
@@ -231,8 +355,10 @@ int create_mail_process(struct login_group *group, int socket,
        }
 
        var_expand_table =
-               get_var_expand_table(group->process_type, user, home_dir,
-                                    local_ip, remote_ip,
+               get_var_expand_table(process_names[group->process_type],
+                                    user, home_dir,
+                                    net_ip2addr(local_ip),
+                                    net_ip2addr(remote_ip),
                                     pid != 0 ? pid : getpid());
        str = t_str_new(128);
 
@@ -271,7 +397,7 @@ int create_mail_process(struct login_group *group, int socket,
                                set->first_valid_gid, set->last_valid_gid,
                                set->mail_extra_groups);
 
-       restrict_process_size(group->set->mail_process_size, (unsigned int)-1);
+       restrict_process_size(set->mail_process_size, (unsigned int)-1);
 
        if (*home_dir == '\0')
                ret = -1;
@@ -302,73 +428,10 @@ int create_mail_process(struct login_group *group, int socket,
                        i_fatal("chdir(/tmp) failed: %m");
        }
 
+        mail_process_set_environment(set, mail, var_expand_table);
+
        env_put("LOGGED_IN=1");
        env_put(t_strconcat("HOME=", home_dir, NULL));
-       env_put(t_strconcat("MAIL_CACHE_FIELDS=",
-                           set->mail_cache_fields, NULL));
-       env_put(t_strconcat("MAIL_NEVER_CACHE_FIELDS=",
-                           set->mail_never_cache_fields, NULL));
-       env_put(t_strdup_printf("MAILBOX_CHECK_INTERVAL=%u",
-                               set->mailbox_check_interval));
-       env_put(t_strdup_printf("MAILBOX_IDLE_CHECK_INTERVAL=%u",
-                               set->mailbox_idle_check_interval));
-       env_put(t_strconcat("CLIENT_WORKAROUNDS=",
-                           set->client_workarounds, NULL));
-       env_put(t_strdup_printf("MAIL_MAX_KEYWORD_LENGTH=%u",
-                               set->mail_max_keyword_length));
-       env_put(t_strdup_printf("IMAP_MAX_LINE_LENGTH=%u",
-                               set->imap_max_line_length));
-       env_put(t_strconcat("IMAP_CAPABILITY=",
-                           set->imap_capability, NULL));
-
-       if (set->mail_save_crlf)
-               env_put("MAIL_SAVE_CRLF=1");
-       if (set->mail_read_mmaped)
-               env_put("MAIL_READ_MMAPED=1");
-       if (set->mmap_disable)
-               env_put("MMAP_DISABLE=1");
-       if (set->mmap_no_write)
-               env_put("MMAP_NO_WRITE=1");
-       if (set->fcntl_locks_disable)
-               env_put("FCNTL_LOCKS_DISABLE=1");
-       if (set->maildir_stat_dirs)
-               env_put("MAILDIR_STAT_DIRS=1");
-       if (set->maildir_copy_with_hardlinks)
-               env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
-       if (set->maildir_check_content_changes)
-               env_put("MAILDIR_CHECK_CONTENT_CHANGES=1");
-       if (set->mail_full_filesystem_access)
-               env_put("FULL_FILESYSTEM_ACCESS=1");
-       if (set->pop3_mails_keep_recent)
-               env_put("POP3_MAILS_KEEP_RECENT=1");
-       (void)umask(set->umask);
-
-       env_put(t_strconcat("MBOX_READ_LOCKS=", set->mbox_read_locks, NULL));
-       env_put(t_strconcat("MBOX_WRITE_LOCKS=", set->mbox_write_locks, NULL));
-       env_put(t_strdup_printf("MBOX_LOCK_TIMEOUT=%u",
-                               set->mbox_lock_timeout));
-       env_put(t_strdup_printf("MBOX_DOTLOCK_CHANGE_TIMEOUT=%u",
-                               set->mbox_dotlock_change_timeout));
-
-       if (group->set->mail_use_modules &&
-           group->set->mail_modules != NULL &&
-           *group->set->mail_modules != '\0') {
-               env_put(t_strconcat("MODULE_DIR=",
-                                   group->set->mail_modules, NULL));
-       }
-
-       /* user given environment - may be malicious. virtual_user comes from
-          auth process, but don't trust that too much either. Some auth
-          mechanism might allow leaving extra data there. */
-       if (*mail == '\0' && set->default_mail_env != NULL)
-               mail = expand_mail_env(set->default_mail_env, var_expand_table);
-
-       if (set->server->namespaces != NULL) {
-               env_put_namespace(set->server->namespaces,
-                                 mail, var_expand_table);
-       }
-
-       env_put(t_strconcat("MAIL=", mail, NULL));
        env_put(t_strconcat("USER=", data + reply->virtual_user_idx, NULL));
 
        addr = net_ip2addr(remote_ip);
@@ -391,23 +454,7 @@ int create_mail_process(struct login_group *group, int socket,
        if (set->mail_drop_priv_before_exec)
                restrict_access_by_env(TRUE);
 
-       /* very simple argument splitting. */
-       i = 0;
-       argv[i++] = executable = t_strcut(group->set->mail_executable, ' ');
-       argv[i] = strchr(group->set->mail_executable, ' ');
-       if (argv[i] != NULL) {
-               argv[i]++;
-               i++;
-       }
-       if (title[0] != '\0')
-               argv[i++] = title;
-       argv[i] = NULL;
-
-       /* hide the path, it's ugly */
-       p = strrchr(argv[0], '/');
-       if (p != NULL) argv[0] = p+1;
-
-       execv(executable, (char **) argv);
+       mail_process_exec_set(set, title);
        err = errno;
 
        for (i = 0; i < 3; i++)
@@ -415,7 +462,7 @@ int create_mail_process(struct login_group *group, int socket,
 
        errno = err;
        i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
-                      group->set->mail_executable);
+                      set->mail_executable);
 
        /* not reached */
        return FALSE;
index 3f6a61b94f803ef37d1202c2d79e448dc182cac5..93af306faced79a8ec03fdacfd9d9e3f471d34ab 100644 (file)
@@ -4,6 +4,8 @@
 struct login_group;
 struct auth_master_reply;
 
+void mail_process_exec(const char *protocol, const char *section);
+
 int create_mail_process(struct login_group *group, int socket,
                        const struct ip_addr *local_ip,
                        const struct ip_addr *remote_ip,
index 6fe66ffb0767775675736d55aeffd24a078bce12..d3faaf0226ee9060b5198181040a88a7200a29f0 100644 (file)
@@ -99,7 +99,7 @@ static void settings_reload(void)
         login_processes_destroy_all();
         auth_processes_destroy_all();
 
-       if (!master_settings_read(configfile))
+       if (!master_settings_read(configfile, FALSE))
                i_warning("Invalid configuration, keeping old one");
        else {
                listen_fds_close(old_set);
@@ -482,9 +482,13 @@ static void print_help(void)
 int main(int argc, char *argv[])
 {
        /* parse arguments */
+       const char *exec_protocol = NULL, *exec_section = NULL;
        int foreground = FALSE;
        int i;
 
+#ifdef DEBUG
+       gdb = getenv("GDB") != NULL;
+#endif
        lib_init();
 
        master_uid = geteuid();
@@ -498,13 +502,14 @@ int main(int argc, char *argv[])
                        i++;
                        if (i == argc) i_fatal("Missing config file argument");
                        configfile = argv[i];
-               } else if (strcmp(argv[i], "--inetd") == 0) {
-                       /* starting through inetd. */
-                       inetd_login_fd = dup(0);
-                       if (inetd_login_fd == -1)
-                               i_fatal("dup(0) failed: %m");
-                       fd_close_on_exec(inetd_login_fd, TRUE);
-                       foreground = TRUE;
+               } else if (strcmp(argv[i], "--exec-mail") == 0) {
+                       /* <protocol> [<server section>]
+                          read configuration and execute mail process */
+                       i++;
+                       if (i == argc) i_fatal("Missing protocol argument");
+                       exec_protocol = argv[i];
+                       if (i+1 != argc) 
+                               exec_section = argv[i++];
                } else if (strcmp(argv[i], "--version") == 0) {
                        printf("%s\n", VERSION);
                        return 0;
@@ -514,18 +519,28 @@ int main(int argc, char *argv[])
                }
        }
 
+       if (getenv("DOVECOT_INETD") != NULL) {
+               /* starting through inetd. */
+               inetd_login_fd = dup(0);
+               if (inetd_login_fd == -1)
+                       i_fatal("dup(0) failed: %m");
+               fd_close_on_exec(inetd_login_fd, TRUE);
+               foreground = TRUE;
+       }
+
        /* read and verify settings before forking */
        master_settings_init();
-       if (!master_settings_read(configfile))
+       if (!master_settings_read(configfile, exec_protocol != NULL))
                exit(FATAL_DEFAULT);
-       open_fds();
 
-#ifdef DEBUG
-       gdb = getenv("GDB") != NULL;
-#endif
-       /* we don't need any environment */
+       if (exec_protocol != NULL)
+               mail_process_exec(exec_protocol, exec_section);
+
+       /* we don't need any environment anymore */
        env_clean();
 
+       open_fds();
+
        if (!foreground)
                daemonize(settings_root->defaults);
 
index 47bc75e423f561e9360f68e39c633407a9c4f21c..ea29566adf2965857a2716155f2cbf4d7a282dc6 100644 (file)
@@ -908,7 +908,7 @@ static int parse_section(const char *type, const char *name, void *context,
        return FALSE;
 }
 
-int master_settings_read(const char *path)
+int master_settings_read(const char *path, int nochecks)
 {
        struct settings_parse_ctx ctx;
        struct server_settings *server, *prev;
@@ -949,7 +949,7 @@ int master_settings_read(const char *path)
                if (!settings_is_active(server->imap))
                        server->imap = NULL;
                else {
-                       if (!settings_verify(server->imap))
+                       if (!nochecks && !settings_verify(server->imap))
                                return FALSE;
                        server->defaults = server->imap;
                }
@@ -957,7 +957,7 @@ int master_settings_read(const char *path)
                if (!settings_is_active(server->pop3))
                        server->pop3 = NULL;
                else {
-                       if (!settings_verify(server->pop3))
+                       if (!nochecks && !settings_verify(server->pop3))
                                return FALSE;
                        if (server->defaults == NULL)
                                server->defaults = server->pop3;
@@ -976,14 +976,16 @@ int master_settings_read(const char *path)
                                return FALSE;
                        }
 
-                       for (; auth != NULL; auth = auth->next) {
-                               if (!auth_settings_verify(auth))
-                                       return FALSE;
-                       }
-                        ns = server->namespaces;
-                       for (; ns != NULL; ns = ns->next) {
-                               if (!namespace_settings_verify(ns))
-                                       return FALSE;
+                       if (!nochecks) {
+                               for (; auth != NULL; auth = auth->next) {
+                                       if (!auth_settings_verify(auth))
+                                               return FALSE;
+                               }
+                               ns = server->namespaces;
+                               for (; ns != NULL; ns = ns->next) {
+                                       if (!namespace_settings_verify(ns))
+                                               return FALSE;
+                               }
                        }
                        prev = server;
                }
index 6907e1613512df2614c4354b95ff502ff35c3916..f639cee45a20f02993abcfbee2e642b011b66aa6 100644 (file)
@@ -171,7 +171,7 @@ struct server_settings {
 
 extern struct server_settings *settings_root;
 
-int master_settings_read(const char *path);
+int master_settings_read(const char *path, int nochecks);
 
 void master_settings_init(void);
 void master_settings_deinit(void);