]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added dovecof --exec and made deliver use it instead of forking.
authorTimo Sirainen <tss@iki.fi>
Tue, 10 Feb 2009 00:38:02 +0000 (19:38 -0500)
committerTimo Sirainen <tss@iki.fi>
Tue, 10 Feb 2009 00:38:02 +0000 (19:38 -0500)
--HG--
branch : HEAD

src/config/config-connection.c
src/config/config-connection.h
src/config/config-parser.c
src/config/main.c
src/deliver/deliver-settings.c
src/deliver/deliver-settings.h
src/deliver/deliver.c
src/master/master-settings.c

index 8499f6aafab72806201fcc6ef4125772384e0b01..a8c2ebc86f64f4c2826e8372c0c71a5498c9c75e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Timo Sirainen */
+/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "common.h"
 #include "str.h"
@@ -6,6 +6,7 @@
 #include "network.h"
 #include "istream.h"
 #include "ostream.h"
+#include "env-util.h"
 #include "config-connection.h"
 
 #include <stdlib.h>
@@ -121,3 +122,23 @@ void config_connection_dump_request(int fd, const char *service)
         config_connection_request(conn, args);
        config_connection_destroy(conn);
 }
+
+void config_connection_putenv(void)
+{
+       const char *env, *p, *key, *value;
+
+       env = str_c(config_string);
+       for (; *env != '\0'; env = p + 1) {
+               p = strchr(env, '\n');
+               if (env == p || p == NULL)
+                       break;
+
+               T_BEGIN {
+                       value = strchr(env, '=');
+                       i_assert(value != NULL && value < p);
+                       key = t_str_ucase(t_strdup_until(env, value));
+                       value = t_strdup_until(value, p);
+                       env_put(t_strconcat(key, value, NULL));
+               } T_END;
+       }
+}
index e5e9cf19e2af83dfa89df4d07c39a30c06342ffb..c451efd75b23eac6481038c787caa38faadfab31 100644 (file)
@@ -5,5 +5,6 @@ struct config_connection *config_connection_create(int fd);
 void config_connection_destroy(struct config_connection *conn);
 
 void config_connection_dump_request(int fd, const char *service);
+void config_connection_putenv(void);
 
 #endif
index d355bb63afed7ca5158d725aabac8d497f9a47c7..6fd0ab298ccba328e0dcab906669d29c762d96d1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 Timo Sirainen */
+/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
 #include "array.h"
index 4ceefef47473009b8cf7d82a82ceb0adfb99dc55..5f3fde0388aa9d693d99805338d36123f399900b 100644 (file)
@@ -1,8 +1,9 @@
-/* Copyright (C) 2005-2008 Timo Sirainen */
+/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
 
 #include "common.h"
 #include "lib-signals.h"
 #include "ioloop.h"
+#include "env-util.h"
 #include "str.h"
 #include "config-connection.h"
 #include "config-parser.h"
@@ -17,7 +18,8 @@ static const char *config_path = SYSCONFDIR "/" PACKAGE ".conf";
 
 static void main_init(const char *service)
 {
-       i_set_failure_internal();
+       if (getenv("LOG_TO_MASTER") != NULL)
+               i_set_failure_internal();
 
        parsers_pool = pool_alloconly_create("parent parsers", 2048);
        config_parsers_fix_parents(parsers_pool);
@@ -30,39 +32,51 @@ static void main_init(const char *service)
 int main(int argc, char *argv[])
 {
        struct ioloop *ioloop;
-       const char *path, *service = "";
+       const char *service = "";
+       char **exec_args = NULL;
        bool dump_nondefaults = FALSE, human_readable = FALSE;
-       int c;
+       int i;
 
        lib_init();
 
-       path = getenv("CONFIG_FILE_PATH");
-       if (path != NULL)
-               config_path = path;
-
-       while ((c = getopt(argc, argv, "c:s:na")) > 0) {
-               switch (c) {
-               case 'c':
-                       config_path = optarg;
-                       break;
-               case 's':
-                       service = optarg;
-                       break;
-               case 'n':
-                       dump_nondefaults = TRUE;
-                       /* fall through */
-               case 'a':
+       for (i = 1; i < argc; i++) {
+               if (strcmp(argv[i], "-a") == 0) {
                        /* FIXME: make it work */
                        human_readable = TRUE;
+               } else if (strcmp(argv[i], "-c") == 0) {
+                       /* config file */
+                       i++;
+                       if (i == argc) i_fatal("Missing config file argument");
+                       config_path = argv[i];
+               } else if (strcmp(argv[i], "-n") == 0) {
+                       dump_nondefaults = TRUE;
+                       human_readable = TRUE;
+               } else if (strcmp(argv[i], "-s") == 0) {
+                       /* service */
+                       i++;
+                       if (i == argc) i_fatal("Missing service argument");
+                       service = argv[i];
+               } else if (strcmp(argv[i], "--exec") == 0) {
+                       /* <command> [<args>] */
+                       i++;
+                       if (i == argc) i_fatal("Missing exec binary argument");
+                       exec_args = &argv[i];
                        break;
-               default:
-                       i_fatal("Unknown parameter: %c", c);
+               } else {
+                       i_fatal("Unknown parameter: %s", argv[i]);
                }
        }
 
        main_init(service);
        ioloop = io_loop_create();
-       config_connection_dump_request(STDOUT_FILENO, "master");
+       if (exec_args == NULL)
+               config_connection_dump_request(STDOUT_FILENO, "master");
+       else {
+               config_connection_putenv();
+               env_put("DOVECONF_ENV=1");
+               execvp(exec_args[0], exec_args);
+               i_fatal("execvp(%s) failed: %m", exec_args[0]);
+       }
        io_loop_destroy(&ioloop);
        lib_deinit();
         return 0;
index 59b50aa61f364cf43615e54745bbab469110a164..8e1cb20e070cd1b7b5e543eefc82524f9814f05b 100644 (file)
@@ -9,8 +9,7 @@
 #include "deliver-settings.h"
 
 #include <stddef.h>
-
-#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
+#include <stdlib.h>
 
 #undef DEF
 #undef DEFLIST
@@ -89,8 +88,7 @@ static void fix_base_path(struct deliver_settings *set, const char **str)
 }
 
 struct setting_parser_context *
-deliver_settings_read(const char *path,
-                     struct deliver_settings **set_r,
+deliver_settings_read(struct deliver_settings **set_r,
                      struct mail_user_settings **user_set_r)
 {
        static const struct setting_parser_info *roots[] = {
@@ -111,8 +109,8 @@ deliver_settings_read(const char *path,
        parser = settings_parser_init_list(settings_pool,
                                roots, N_ELEMENTS(roots),
                                SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-       if (settings_parse_exec(parser, DOVECOT_CONFIG_BIN_PATH,
-                               path, "lda") < 0) {
+
+       if (settings_parse_environ(parser) < 0) {
                i_fatal_status(EX_CONFIG, "Error reading configuration: %s",
                               settings_parser_get_error(parser));
        }
index ce16d8ec26a00d000a5d160141a8d876693d81e0..103fe2fbe171b0680829518209a5bf2b4a7f034b 100644 (file)
@@ -29,8 +29,7 @@ struct deliver_settings {
 };
 
 struct setting_parser_context *
-deliver_settings_read(const char *path,
-                     struct deliver_settings **set_r,
+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);
index bd7775768d396a74312c3b349bc38805d629a0b7..658b026300fdf7f95350bce8346f51571c8310bf 100644 (file)
@@ -488,6 +488,7 @@ int main(int argc, char *argv[])
        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;
@@ -594,10 +595,29 @@ int main(int argc, char *argv[])
                }
        }
 
+       doveconf_env = getenv("DOVECONF_ENV") != NULL;
        if (user == NULL)
                user = getenv("USER");
-       if (!keep_environment)
+       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]);
+       }
 
        process_euid = geteuid();
        if (user_auth)
@@ -627,7 +647,7 @@ int main(int argc, char *argv[])
        mail_storage_register_all();
        mailbox_list_register_all();
 
-       parser = deliver_settings_read(config_path, &deliver_set, &user_set);
+       parser = deliver_settings_read(&deliver_set, &user_set);
        open_logfile(user);
 
        mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
index 1e39e72c2acb81dc6a46d186b9588f2509f9e0c0..a8b3c4215999c82cb0d315d942c6b09ea416b7cc 100644 (file)
@@ -882,6 +882,8 @@ static int config_exec(const char *path, const char *service,
        string_t *all_settings;
        int ret;
 
+       env_put("LOG_TO_MASTER=1");
+
        all_settings = str_new(default_pool, 10240);
        parser = settings_parser_init(settings_pool,
                                      &master_setting_parser_info,