]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master, global: Restructure import_environment as strlist
authorKarl Fleischmann <karl.fleischmann@open-xchange.com>
Tue, 23 Jan 2024 09:36:41 +0000 (10:36 +0100)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:12 +0000 (12:34 +0200)
As master_service_import_environment() requires a key=value concatenated
string of environment variables, the config parser as well as the master
process need to concatenate the strlist setting appropriately.

src/config/config-parser.c
src/lib-master/master-service-settings.c
src/lib-master/master-service-settings.h
src/lib-master/master-service.c
src/master/main.c

index 40df5edd8c9e17f830e1c4bd29bb996c7c44548f..9fd4554e9db7554f112f4157b0a334a7b096796c 100644 (file)
@@ -18,6 +18,7 @@
 #include "config-request.h"
 #include "config-dump-full.h"
 #include "config-parser-private.h"
+#include "strfuncs.h"
 
 #include <unistd.h>
 #include <fcntl.h>
@@ -2322,6 +2323,25 @@ config_module_parsers_get_setting(const struct config_module_parser *module_pars
        }
 
        const struct setting_define *def = &l->info->defines[key_idx];
+
+       /* Custom handler for the import_environment strlist setting. The
+          calling function expects a string of key=value pairs. See
+          master_service_get_import_environment_keyvals() for the original
+          implementation. */
+       if (strcmp(key, "import_environment") == 0) {
+               unsigned int len = array_count(l->settings[key_idx].array);
+               string_t *keyvals = t_str_new(64);
+               for (unsigned int i = 0; i < len; i += 2) {
+                       const char *const *key = array_idx(l->settings[key_idx].array, i);
+                       const char *const *val = array_idx(l->settings[key_idx].array, i + 1);
+                       str_append(keyvals, t_strdup_printf("%s=%s", *key, *val));
+
+                       if (i + 2 < len)
+                               str_append_c(keyvals, ' ');
+               }
+               return str_c(keyvals);
+       }
+
        i_assert(def->type != SET_STRLIST && def->type != SET_BOOLLIST &&
                 def->type != SET_FILTER_ARRAY);
        if (l->change_counters[key_idx] != 0)
index 758ec6f004aae45714c980ac0dbc76aa463f45e2..ffcb077c8ed9e9eb9a8063ce844bdfe62a390c8c 100644 (file)
@@ -45,7 +45,6 @@ static const struct setting_define master_service_setting_defines[] = {
        DEF(STR, log_core_filter),
        DEF(STR, process_shutdown_filter),
        DEF(STR, syslog_facility),
-       DEF(STR, import_environment),
        DEF(STR, stats_writer_socket_path),
        DEF(STR, dovecot_storage_version),
        DEF(BOOL, version_ignore),
@@ -55,22 +54,12 @@ static const struct setting_define master_service_setting_defines[] = {
        DEF(STR, haproxy_trusted_networks),
        DEF(TIME, haproxy_timeout),
 
+       { .type = SET_STRLIST, .key = "import_environment",
+         .offset = offsetof(struct master_service_settings, import_environment) },
+
        SETTING_DEFINE_LIST_END
 };
 
-/* <settings checks> */
-#ifdef HAVE_LIBSYSTEMD
-#  define ENV_SYSTEMD " LISTEN_PID LISTEN_FDS NOTIFY_SOCKET"
-#else
-#  define ENV_SYSTEMD ""
-#endif
-#ifdef DEBUG
-#  define ENV_GDB " GDB DEBUG_SILENT"
-#else
-#  define ENV_GDB ""
-#endif
-/* </settings checks> */
-
 static const struct master_service_settings master_service_default_settings = {
        .base_dir = PKG_RUNDIR,
        .state_dir = PKG_STATEDIR,
@@ -83,7 +72,7 @@ static const struct master_service_settings master_service_default_settings = {
        .log_core_filter = "",
        .process_shutdown_filter = "",
        .syslog_facility = "mail",
-       .import_environment = "TZ CORE_OUTOFMEM CORE_ERROR PATH" ENV_SYSTEMD ENV_GDB,
+       .import_environment = ARRAY_INIT,
        .stats_writer_socket_path = "stats-writer",
        .dovecot_storage_version = "",
        .version_ignore = FALSE,
@@ -94,11 +83,29 @@ static const struct master_service_settings master_service_default_settings = {
        .haproxy_timeout = 3
 };
 
+static const struct setting_keyvalue master_service_default_settings_keyvalue[] = {
+       { "import_environment/TZ", "%{env:TZ}" },
+       { "import_environment/CORE_OUTOFMEM", "%{env:CORE_OUTOFMEM}" },
+       { "import_environment/CORE_ERROR", "%{env:CORE_ERROR}" },
+       { "import_environment/PATH", "%{env:PATH}" },
+#ifdef HAVE_LIBSYSTEMD
+       { "import_environment/LISTEN_PID", "%{env:LISTEN_PID}" },
+       { "import_environment/LISTEN_FDS", "%{env:LISTEN_FDS}" },
+       { "import_environment/NOTIFY_SOCKET", "%{env:NOTIFY_SOCKET}" },
+#endif
+#ifdef DEBUG
+       { "import_environment/GDB", "%{env:GDB}" },
+       { "import_environment/DEBUG_SILENT", "%{env:DEBUG_SILENT}" },
+#endif
+       { NULL, NULL },
+};
+
 const struct setting_parser_info master_service_setting_parser_info = {
        .name = "master_service",
 
        .defines = master_service_setting_defines,
        .defaults = &master_service_default_settings,
+       .default_settings = master_service_default_settings_keyvalue,
 
        .pool_offset1 = 1 + offsetof(struct master_service_settings, pool),
        .struct_size = sizeof(struct master_service_settings),
@@ -555,3 +562,20 @@ master_service_get_service_settings(struct master_service *service)
 {
        return service->set;
 }
+
+const char *
+master_service_get_import_environment_keyvals(struct master_service *service)
+{
+       ARRAY_TYPE(const_string) arr = service->set->import_environment;
+       unsigned int len = array_count(&arr);
+       string_t *keyvals = t_str_new(64);
+       for (unsigned int i = 0; i < len; i += 2) {
+               const char *const *key = array_idx(&arr, i);
+               const char *const *val = array_idx(&arr, i + 1);
+               str_append(keyvals, t_strdup_printf("%s=%s", *key, *val));
+
+               if (i + 2 < len)
+                       str_append_c(keyvals, ' ');
+       }
+       return str_c(keyvals);
+}
index 67a41c5f2a1af1c742dbabab5fc6900cef28daf0..cde0f3df11659c6724386f1759007f8593625a3e 100644 (file)
@@ -16,9 +16,9 @@ struct master_service_settings {
        const char *log_core_filter;
        const char *process_shutdown_filter;
        const char *syslog_facility;
-       const char *import_environment;
        const char *stats_writer_socket_path;
        const char *dovecot_storage_version;
+       ARRAY_TYPE(const_string) import_environment;
        bool version_ignore;
        bool shutdown_clients;
        bool verbose_proctitle;
@@ -82,5 +82,9 @@ int master_service_settings_read_simple(struct master_service *service,
 
 const struct master_service_settings *
 master_service_get_service_settings(struct master_service *service);
+/* Return the import_environment setting as a space-separated concatenated
+   string of key=value pairs. The values might contain %variables to expand. */
+const char *
+master_service_get_import_environment_keyvals(struct master_service *service);
 
 #endif
index 6b088508fc0ae30fed2003c1e7fe942b7ae81bf8..aef332cfabd582a23616cb720f98bc325bf89276 100644 (file)
@@ -1035,7 +1035,8 @@ static void master_service_import_environment_real(const char *import_environmen
 #ifdef HAVE_LIBSYSTEMD
        /* Always import systemd variables, otherwise it is possible to break
           systemd startup in obscure ways. */
-       value = "NOTIFY_SOCKET LISTEN_FDS LISTEN_PID";
+       value = "NOTIFY_SOCKET=%{env:NOTIFY_SOCKET} "
+               "LISTEN_FDS=%{env:LISTEN_FDS} LISTEN_PID=%{env:LISTEN_PID}";
        array_push_back(&keys, &value);
 #endif
        /* add new environments */
index 13dffce1efebf84122ebf6c44fdab0eefc6040c7..c1e108d00d14222897bdc0b2b2dcf5172e65f6e6 100644 (file)
@@ -930,9 +930,9 @@ int main(int argc, char *argv[])
        master_settings_do_fixes(set);
        fatal_log_check(set);
 
-       const struct master_service_settings *service_set =
-               master_service_get_service_settings(master_service);
-       master_service_import_environment(service_set->import_environment);
+       const char *import_environment =
+               master_service_get_import_environment_keyvals(master_service);
+       master_service_import_environment(import_environment);
        master_service_env_clean();
 
        /* create service structures from settings. if there are any errors in