From: Timo Sirainen Date: Tue, 10 Feb 2009 00:38:02 +0000 (-0500) Subject: Added dovecof --exec and made deliver use it instead of forking. X-Git-Tag: 2.0.alpha1~1037^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a11689fe3fbb3bca11b9cb4ae5faf27db96401cc;p=thirdparty%2Fdovecot%2Fcore.git Added dovecof --exec and made deliver use it instead of forking. --HG-- branch : HEAD --- diff --git a/src/config/config-connection.c b/src/config/config-connection.c index 8499f6aafa..a8c2ebc86f 100644 --- a/src/config/config-connection.c +++ b/src/config/config-connection.c @@ -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 @@ -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; + } +} diff --git a/src/config/config-connection.h b/src/config/config-connection.h index e5e9cf19e2..c451efd75b 100644 --- a/src/config/config-connection.h +++ b/src/config/config-connection.h @@ -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 diff --git a/src/config/config-parser.c b/src/config/config-parser.c index d355bb63af..6fd0ab298c 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -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" diff --git a/src/config/main.c b/src/config/main.c index 4ceefef474..5f3fde0388 100644 --- a/src/config/main.c +++ b/src/config/main.c @@ -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) { + /* [] */ + 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; diff --git a/src/deliver/deliver-settings.c b/src/deliver/deliver-settings.c index 59b50aa61f..8e1cb20e07 100644 --- a/src/deliver/deliver-settings.c +++ b/src/deliver/deliver-settings.c @@ -9,8 +9,7 @@ #include "deliver-settings.h" #include - -#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf" +#include #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)); } diff --git a/src/deliver/deliver-settings.h b/src/deliver/deliver-settings.h index ce16d8ec26..103fe2fbe1 100644 --- a/src/deliver/deliver-settings.h +++ b/src/deliver/deliver-settings.h @@ -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); diff --git a/src/deliver/deliver.c b/src/deliver/deliver.c index bd7775768d..658b026300 100644 --- a/src/deliver/deliver.c +++ b/src/deliver/deliver.c @@ -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"); diff --git a/src/master/master-settings.c b/src/master/master-settings.c index 1e39e72c2a..a8b3c42159 100644 --- a/src/master/master-settings.c +++ b/src/master/master-settings.c @@ -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,