From: Karl Fleischmann Date: Tue, 23 Jan 2024 09:36:41 +0000 (+0100) Subject: lib-master, global: Restructure import_environment as strlist X-Git-Tag: 2.4.1~1041 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf5fe5a341eed3598ce48fe5ea88f26c15064775;p=thirdparty%2Fdovecot%2Fcore.git lib-master, global: Restructure import_environment as strlist 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. --- diff --git a/src/config/config-parser.c b/src/config/config-parser.c index 40df5edd8c..9fd4554e9d 100644 --- a/src/config/config-parser.c +++ b/src/config/config-parser.c @@ -18,6 +18,7 @@ #include "config-request.h" #include "config-dump-full.h" #include "config-parser-private.h" +#include "strfuncs.h" #include #include @@ -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) diff --git a/src/lib-master/master-service-settings.c b/src/lib-master/master-service-settings.c index 758ec6f004..ffcb077c8e 100644 --- a/src/lib-master/master-service-settings.c +++ b/src/lib-master/master-service-settings.c @@ -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 }; -/* */ -#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 -/* */ - 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); +} diff --git a/src/lib-master/master-service-settings.h b/src/lib-master/master-service-settings.h index 67a41c5f2a..cde0f3df11 100644 --- a/src/lib-master/master-service-settings.h +++ b/src/lib-master/master-service-settings.h @@ -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 diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index 6b088508fc..aef332cfab 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -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 */ diff --git a/src/master/main.c b/src/master/main.c index 13dffce1ef..c1e108d00d 100644 --- a/src/master/main.c +++ b/src/master/main.c @@ -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