bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen#include "event-filter.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "path-util.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "istream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "write-full.h"
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen#include "str.h"
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen#include "strescape.h"
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen#include "syslog-util.h"
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen#include "eacces-error.h"
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen#include "env-util.h"
bb308de9d25db75528605eb733a418c996d416adTimo Sirainen#include "execv-const.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "settings-parser.h"
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen#include "stats-client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-private.h"
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen#include "master-service-ssl-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stddef.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <unistd.h>
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen#include <time.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <sys/stat.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen#define DOVECOT_CONFIG_SOCKET_PATH PKG_RUNDIR"/config"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen#define CONFIG_READ_TIMEOUT_SECS 10
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#define CONFIG_HANDSHAKE "VERSION\tconfig\t2\t0\n"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#undef DEF
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define DEF(type, name) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen { type, #name, offsetof(struct master_service_settings, name), NULL }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenstatic bool
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenmaster_service_settings_check(void *_set, pool_t pool, const char **error_r);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenstatic const struct setting_define master_service_setting_defines[] = {
aec5f17494d994cb99b8fff5bff2f022bc3dcbaaTimo Sirainen DEF(SET_STR, base_dir),
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen DEF(SET_STR, state_dir),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_STR, log_path),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_STR, info_log_path),
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen DEF(SET_STR, debug_log_path),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_STR, log_timestamp),
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen DEF(SET_STR, log_debug),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_STR, syslog_facility),
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen DEF(SET_STR, import_environment),
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen DEF(SET_STR, stats_writer_socket_path),
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen DEF(SET_SIZE, config_cache_size),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_BOOL, version_ignore),
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen DEF(SET_BOOL, shutdown_clients),
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen DEF(SET_BOOL, verbose_proctitle),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen DEF(SET_STR, haproxy_trusted_networks),
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen DEF(SET_TIME, haproxy_timeout),
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen SETTING_DEFINE_LIST_END
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen/* <settings checks> */
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#ifdef HAVE_SYSTEMD
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen# define ENV_SYSTEMD " LISTEN_PID LISTEN_FDS"
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#else
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen# define ENV_SYSTEMD ""
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#endif
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#ifdef DEBUG
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen# define ENV_GDB " GDB DEBUG_SILENT"
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#else
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen# define ENV_GDB ""
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen#endif
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen/* </settings checks> */
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenstatic const struct master_service_settings master_service_default_settings = {
aec5f17494d994cb99b8fff5bff2f022bc3dcbaaTimo Sirainen .base_dir = PKG_RUNDIR,
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen .state_dir = PKG_STATEDIR,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen .log_path = "syslog",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .info_log_path = "",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .debug_log_path = "",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .log_timestamp = DEFAULT_FAILURE_STAMP_FORMAT,
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen .log_debug = "",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .syslog_facility = "mail",
8d7c78157f1acd25aa989cf02d9518a85d2c89d4Timo Sirainen .import_environment = "TZ CORE_OUTOFMEM CORE_ERROR" ENV_SYSTEMD ENV_GDB,
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen .stats_writer_socket_path = "stats-writer",
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen .config_cache_size = 1024*1024,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .version_ignore = FALSE,
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen .shutdown_clients = TRUE,
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen .verbose_proctitle = FALSE,
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen .haproxy_trusted_networks = "",
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen .haproxy_timeout = 3
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainenconst struct setting_parser_info master_service_setting_parser_info = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .module_name = "master",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .defines = master_service_setting_defines,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .defaults = &master_service_default_settings,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .type_offset = (size_t)-1,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .struct_size = sizeof(struct master_service_settings),
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen .parent_offset = (size_t)-1,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen .check_func = master_service_settings_check
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen/* <settings checks> */
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainenint master_service_log_debug_parse(struct event_filter *filter, const char *str,
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen const char **error_r)
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen{
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen const char *categories[2] = { NULL, NULL };
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen struct event_filter_query query = {
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen .categories = categories
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen };
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen /* FIXME: we should support more complicated filters */
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen const char *const *args = t_strsplit_spaces(str, " ");
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen for (unsigned int i = 0; args[i] != NULL; i++) {
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen categories[0] = args[i];
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen event_filter_add(filter, &query);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen }
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen *error_r = NULL;
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen return 0;
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen}
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenstatic bool
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenmaster_service_settings_check(void *_set, pool_t pool ATTR_UNUSED,
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen const char **error_r)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen{
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen struct master_service_settings *set = _set;
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen int facility;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*set->log_path == '\0') {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* default to syslog logging */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen set->log_path = "syslog";
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen if (!syslog_facility_find(set->syslog_facility, &facility)) {
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen *error_r = t_strdup_printf("Unknown syslog_facility: %s",
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen set->syslog_facility);
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen return FALSE;
2eed51b45a58562cc89d49c5f572f47d83390f23Timo Sirainen }
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen struct event_filter *filter = event_filter_create();
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen const char *error;
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen if (master_service_log_debug_parse(filter, set->log_debug, &error) < 0) {
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen *error_r = t_strdup_printf("Invalid log_debug: %s", error);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen event_filter_unref(&filter);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen return FALSE;
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen }
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen#ifndef CONFIG_BINARY
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen event_set_global_debug_log_filter(filter);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen#endif
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen event_filter_unref(&filter);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen return TRUE;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen}
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen/* </settings checks> */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void ATTR_NORETURN
e75ff6a1854ee9befb751d14023bd5fa756fbf3bTimo Sirainenmaster_service_exec_config(struct master_service *service,
e75ff6a1854ee9befb751d14023bd5fa756fbf3bTimo Sirainen const struct master_service_settings_input *input)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
e1237f7e7f978e23c86cf51b69742291c316f75cTimo Sirainen const char **conf_argv, *binary_path = service->argv[0];
ed6b37eeec4c20354a871ad5f4dc0a97f769d37eTimo Sirainen const char *error = NULL;
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen unsigned int i, argv_max_count;
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen
d764f67e463b5d8ea3dc9f5c932bf83d76cad1f0Martti Rannanjärvi if (!t_binary_abspath(&binary_path, &error)) {
d764f67e463b5d8ea3dc9f5c932bf83d76cad1f0Martti Rannanjärvi i_fatal("t_binary_abspath(%s) failed: %s", binary_path, error);
d764f67e463b5d8ea3dc9f5c932bf83d76cad1f0Martti Rannanjärvi }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if (!service->keep_environment && !input->preserve_environment) {
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if (input->preserve_home)
ed6b37eeec4c20354a871ad5f4dc0a97f769d37eTimo Sirainen master_service_import_environment("HOME");
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if (input->preserve_user)
ed6b37eeec4c20354a871ad5f4dc0a97f769d37eTimo Sirainen master_service_import_environment("USER");
9f41af1f09df00977a598008a15672dbdc2c3b72Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0)
ed6b37eeec4c20354a871ad5f4dc0a97f769d37eTimo Sirainen master_service_import_environment("LOG_STDERR_TIMESTAMP");
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen /* doveconf empties the environment before exec()ing us back
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen if DOVECOT_PRESERVE_ENVS is set, so make sure it is. */
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen if (getenv(DOVECOT_PRESERVE_ENVS_ENV) == NULL)
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen env_put(DOVECOT_PRESERVE_ENVS_ENV"=");
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen } else {
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen /* make sure doveconf doesn't remove any environment */
de266e09d27b44f0c51d67aea6a26fb1640f3290Timo Sirainen env_remove(DOVECOT_PRESERVE_ENVS_ENV);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen }
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen if (input->use_sysexits)
50349cd047ca9e7c100cbeb70acfe26672649959Timo Sirainen env_put("USE_SYSEXITS=1");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* @UNSAFE */
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen i = 0;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen argv_max_count = 11 + (service->argc + 1) + 1;
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv = t_new(const char *, argv_max_count);
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = DOVECOT_CONFIG_BIN_PATH;
cf89092dff3defce94f1860a04b3ce8bfaf4a712Timo Sirainen if (input->service != NULL) {
cf89092dff3defce94f1860a04b3ce8bfaf4a712Timo Sirainen conf_argv[i++] = "-f";
cf89092dff3defce94f1860a04b3ce8bfaf4a712Timo Sirainen conf_argv[i++] = t_strconcat("service=", input->service, NULL);
cf89092dff3defce94f1860a04b3ce8bfaf4a712Timo Sirainen }
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = "-c";
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = service->config_path;
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen if (input->module != NULL) {
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = "-m";
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = input->module;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen if (service->want_ssl_settings) {
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen conf_argv[i++] = "-m";
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen conf_argv[i++] = "ssl";
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen }
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen }
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen if (input->parse_full_config)
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = "-p";
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = "-e";
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen conf_argv[i++] = binary_path;
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen memcpy(conf_argv+i, service->argv + 1,
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen (service->argc) * sizeof(conf_argv[0]));
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen i += service->argc;
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen
8d173ad4d740a8a1c584328718325feea62201c8Timo Sirainen i_assert(i < argv_max_count);
bb308de9d25db75528605eb733a418c996d416adTimo Sirainen execv_const(conf_argv[0], conf_argv);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainenstatic void
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainenconfig_exec_fallback(struct master_service *service,
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen const struct master_service_settings_input *input)
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen{
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen const char *path;
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen struct stat st;
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen int saved_errno = errno;
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen
47fa3865933c9c57da7c6076fa4d7807614ff56dTimo Sirainen if (input->never_exec)
47fa3865933c9c57da7c6076fa4d7807614ff56dTimo Sirainen return;
47fa3865933c9c57da7c6076fa4d7807614ff56dTimo Sirainen
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen path = input->config_path != NULL ? input->config_path :
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen master_service_get_config_path(service);
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen if (stat(path, &st) == 0 &&
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode)) {
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen /* it's a file, not a socket/pipe */
e75ff6a1854ee9befb751d14023bd5fa756fbf3bTimo Sirainen master_service_exec_config(service, input);
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen }
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen errno = saved_errno;
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen}
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainenmaster_service_open_config(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen const char **path_r, const char **error_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen struct stat st;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen const char *path;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen int fd;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen *path_r = path = input->config_path != NULL ? input->config_path :
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen master_service_get_config_path(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen if (service->config_fd != -1 && input->config_path == NULL &&
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen !service->config_path_changed_with_param) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* use the already opened config socket */
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen fd = service->config_fd;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen service->config_fd = -1;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen return fd;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen if (!service->config_path_from_master &&
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen !service->config_path_changed_with_param &&
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen input->config_path == NULL) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* first try to connect to the default config socket.
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen configuration may contain secrets, so in default config
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen this fails because the socket is 0600. it's useful for
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen developers though. :) */
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen fd = net_connect_unix(DOVECOT_CONFIG_SOCKET_PATH);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (fd >= 0) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen *path_r = DOVECOT_CONFIG_SOCKET_PATH;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen net_set_nonblock(fd, FALSE);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen return fd;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen /* fallback to executing doveconf */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen if (stat(path, &st) < 0) {
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen *error_r = errno == EACCES ? eacces_error_get("stat", path) :
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen t_strdup_printf("stat(%s) failed: %m", path);
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen return -1;
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen }
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen
73fed8af5e20022bdef8620bb074507755ec2c5eTimo Sirainen if (!S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode)) {
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen /* it's not an UNIX socket, don't even try to connect */
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen fd = -1;
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen errno = ENOTSOCK;
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen } else {
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen fd = net_connect_unix_with_retries(path, 1000);
5ea5c79ca3f6012095bd5e9b2251e6dd5f614a8dTimo Sirainen }
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (fd < 0) {
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen *error_r = t_strdup_printf("net_connect_unix(%s) failed: %m",
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen path);
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen config_exec_fallback(service, input);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen return -1;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen }
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen net_set_nonblock(fd, FALSE);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen return fd;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen}
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainenstatic void
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainenconfig_build_request(struct master_service *service, string_t *str,
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen const struct master_service_settings_input *input)
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen{
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_append(str, "REQ");
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen if (input->module != NULL) {
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tmodule=%s", input->module);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen if (service->want_ssl_settings)
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen str_append(str, "\tmodule=ssl");
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen }
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen if (input->service != NULL)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tservice=%s", input->service);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen if (input->username != NULL)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tuser=%s", input->username);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen if (input->local_ip.family != 0)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\tlip=%s", net_ip2addr(&input->local_ip));
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen if (input->remote_ip.family != 0)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_printfa(str, "\trip=%s", net_ip2addr(&input->remote_ip));
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen if (input->local_name != NULL)
41942258112e4131de96b6a4399c1a8ac83a23cbTimo Sirainen str_printfa(str, "\tlname=%s", input->local_name);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_append_c(str, '\n');
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen}
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainenstatic int
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainenconfig_send_request(struct master_service *service,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen const struct master_service_settings_input *input,
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen int fd, const char *path, const char **error_r)
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen{
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen int ret;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen T_BEGIN {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen string_t *str;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str = t_str_new(128);
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen str_append(str, CONFIG_HANDSHAKE);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen config_build_request(service, str, input);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen ret = write_full(fd, str_data(str), str_len(str));
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen } T_END;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (ret < 0) {
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen *error_r = t_strdup_printf("write_full(%s) failed: %m", path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenstatic int
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenmaster_service_apply_config_overrides(struct master_service *service,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen struct setting_parser_context *parser,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const char **error_r)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen{
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const char *const *overrides;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen unsigned int i, count;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen overrides = array_get(&service->config_overrides, &count);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen for (i = 0; i < count; i++) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (settings_parse_line(parser, overrides[i]) < 0) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen *error_r = t_strdup_printf(
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen "Invalid -o parameter %s: %s", overrides[i],
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen settings_parser_get_error(parser));
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return -1;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
29357a858c79d8502ac83ab3b5425b5ffb64aa2eJosh Soref settings_parse_set_key_expanded(parser, service->set_pool,
29357a858c79d8502ac83ab3b5425b5ffb64aa2eJosh Soref t_strcut(overrides[i], '='));
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return 0;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen}
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic int
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainenconfig_read_reply_header(struct istream *istream, const char *path, pool_t pool,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const struct master_service_settings_input *input,
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen struct master_service_settings_output *output_r,
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen const char **error_r)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *line;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ssize_t ret;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen while ((ret = i_stream_read(istream)) > 0) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen line = i_stream_next_line(istream);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (line != NULL)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen break;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen if (ret <= 0) {
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen if (ret == 0)
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen return 1;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen *error_r = istream->stream_errno != 0 ?
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen t_strdup_printf("read(%s) failed: %s", path,
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen i_stream_get_error(istream)) :
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen t_strdup_printf("read(%s) failed: EOF", path);
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen return -1;
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen T_BEGIN {
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen const char *const *arg = t_strsplit_tabescaped(line);
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen ARRAY_TYPE(const_string) services;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen p_array_init(&services, pool, 8);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen for (; *arg != NULL; arg++) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (strcmp(*arg, "service-uses-local") == 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen output_r->service_uses_local = TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen else if (strcmp(*arg, "service-uses-remote") == 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen output_r->service_uses_remote = TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (strcmp(*arg, "used-local") == 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen output_r->used_local = TRUE;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen else if (strcmp(*arg, "used-remote") == 0)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen output_r->used_remote = TRUE;
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen else if (strncmp(*arg, "service=", 8) == 0) {
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen const char *name = p_strdup(pool, *arg + 8);
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen array_append(&services, &name, 1);
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen }
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen if (input->service == NULL) {
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen array_append_zero(&services);
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen output_r->specific_services = array_idx(&services, 0);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } T_END;
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen return 0;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainenvoid master_service_config_socket_try_open(struct master_service *service)
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen{
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen struct master_service_settings_input input;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen const char *path, *error;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen int fd;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen /* we'll get here before command line parameters have been parsed,
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen so -O, -c and -i parameters haven't been handled yet at this point.
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen this means we could end up opening config socket connection
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen unnecessarily, but this isn't a problem. we'll just have to
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen ignore it later on. (unfortunately there isn't a master_service_*()
553f96fdbff9f70e7b5d2261ae61b9ddf5156414Timo Sirainen call where this function would be better called.) */
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen if (getenv("DOVECONF_ENV") != NULL ||
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) != 0)
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen return;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&input);
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen input.never_exec = TRUE;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen fd = master_service_open_config(service, &input, &path, &error);
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen if (fd != -1)
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen service->config_fd = fd;
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen}
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint master_service_settings_read(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output *output_r,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(const struct setting_parser_info *) all_roots;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct setting_parser_info *tmp_root;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct setting_parser_context *parser;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen struct istream *istream;
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen const char *path = NULL, *error;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen void **sets;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret, fd = -1;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen time_t now, timeout;
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen bool use_environment, retry;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(output_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if (getenv("DOVECONF_ENV") == NULL &&
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) {
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen retry = service->config_fd != -1;
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen for (;;) {
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen fd = master_service_open_config(service, input,
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen &path, error_r);
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen if (fd == -1) {
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen if (errno == EACCES)
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen output_r->permission_denied = TRUE;
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen return -1;
cfa178a42cac8c4ddb34ca995253346873129d0dTimo Sirainen }
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen if (config_send_request(service, input, fd,
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen path, error_r) == 0)
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen break;
af8b1248fed8529d26985460acdc4b1e4b7de675Timo Sirainen i_close_fd(&fd);
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen if (!retry) {
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen config_exec_fallback(service, input);
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen return -1;
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen }
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen /* config process died, retry connecting */
1f73636296eb5ac856f36a08543fdc61983f1555Timo Sirainen retry = FALSE;
a03b4fe1a887d187d0dbcd961e9d5127f7c5bf2aTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen if (service->set_pool != NULL) {
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen if (service->set_parser != NULL)
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen settings_parser_deinit(&service->set_parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p_clear(service->set_pool);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->set_pool =
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainen pool_alloconly_create("master service settings", 16384);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p_array_init(&all_roots, service->set_pool, 8);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tmp_root = &master_service_setting_parser_info;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_append(&all_roots, &tmp_root, 1);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen if (service->want_ssl_settings) {
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen tmp_root = &master_service_ssl_setting_parser_info;
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen array_append(&all_roots, &tmp_root, 1);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen }
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (input->roots != NULL) {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen for (i = 0; input->roots[i] != NULL; i++)
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen array_append(&all_roots, &input->roots[i], 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser = settings_parser_init_list(service->set_pool,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_idx(&all_roots, 0), array_count(&all_roots),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (fd != -1) {
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi istream = i_stream_create_fd(fd, (size_t)-1);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen now = time(NULL);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen timeout = now + CONFIG_READ_TIMEOUT_SECS;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen do {
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen alarm(timeout - now);
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen ret = config_read_reply_header(istream, path,
194755bdfb97c07ca8b9df071099f68947b971e3Timo Sirainen service->set_pool, input,
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen output_r, error_r);
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen if (ret == 0) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ret = settings_parse_stream_read(parser,
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen istream);
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen if (ret < 0)
a814eff9aada6c78d39fa09682a78d950993f381Martti Rannanjärvi *error_r = t_strdup(
dd3ab584e19152b0ce75cf6fe20c165fdbaf7d36Martti Rannanjärvi settings_parser_get_error(parser));
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen }
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen alarm(0);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen if (ret <= 0)
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen break;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen /* most likely timed out, but just in case some other
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen signal was delivered early check if we need to
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen continue */
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen now = time(NULL);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen } while (now < timeout);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen i_stream_unref(&istream);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen if (ret != 0) {
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen if (ret > 0) {
a814eff9aada6c78d39fa09682a78d950993f381Martti Rannanjärvi *error_r = t_strdup_printf(
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen "Timeout reading config from %s", path);
a7a316bc6cbd7c89bf01ac091a2e9fc2d514f1a0Timo Sirainen }
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
4a7863c531a27498830004ca2ead2eb53812ed79Timo Sirainen config_exec_fallback(service, input);
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen settings_parser_deinit(&parser);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0 &&
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen service->config_fd == -1 && input->config_path == NULL)
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen service->config_fd = fd;
1f9d1bedae25d86f26c239055c5487499dfeeb58Timo Sirainen else
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&fd);
497e3c244905f2019499eb42bfef11e203bf3f52Timo Sirainen use_environment = FALSE;
497e3c244905f2019499eb42bfef11e203bf3f52Timo Sirainen } else {
497e3c244905f2019499eb42bfef11e203bf3f52Timo Sirainen use_environment = TRUE;
a88696bd63b2ce0f7b02ee3352e4bf739497352aTimo Sirainen }
a88696bd63b2ce0f7b02ee3352e4bf739497352aTimo Sirainen
497e3c244905f2019499eb42bfef11e203bf3f52Timo Sirainen if (use_environment || service->keep_environment) {
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if (settings_parse_environ(parser) < 0) {
a814eff9aada6c78d39fa09682a78d950993f381Martti Rannanjärvi *error_r = t_strdup(settings_parser_get_error(parser));
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen settings_parser_deinit(&parser);
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen return -1;
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen }
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (array_is_created(&service->config_overrides)) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (master_service_apply_config_overrides(service, parser,
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen error_r) < 0) {
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen settings_parser_deinit(&parser);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return -1;
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
8c4b2e0734326ef8e534f25e8ee78ace1fc22d15Timo Sirainen if (!settings_parser_check(parser, service->set_pool, &error)) {
a814eff9aada6c78d39fa09682a78d950993f381Martti Rannanjärvi *error_r = t_strdup_printf("Invalid settings: %s", error);
9a69030b126fca4d8785e4517c104b2fc3512f03Timo Sirainen settings_parser_deinit(&parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen sets = settings_parser_get_list(parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->set = sets[0];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->set_parser = parser;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (service->set->version_ignore &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* running standalone. we want to ignore plugin versions. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->version_string = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_SEND_STATS) != 0) {
5343822b9b61907ce16993da795d08998cb6fa14Timo Sirainen /* When running standalone (e.g. doveadm) try to connect to the
5343822b9b61907ce16993da795d08998cb6fa14Timo Sirainen stats socket, but don't log an error if it's not running.
5343822b9b61907ce16993da795d08998cb6fa14Timo Sirainen It may be intentional. */
5343822b9b61907ce16993da795d08998cb6fa14Timo Sirainen bool silent_notfound_errors =
5343822b9b61907ce16993da795d08998cb6fa14Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0;
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen master_service_init_stats_client(service, silent_notfound_errors);
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (service->set->shutdown_clients)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen master_service_set_die_with_master(master_service, TRUE);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* if we change any settings afterwards, they're in expanded form.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen especially all settings from userdb are already expanded. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen settings_parse_set_expanded(service->set_parser, TRUE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainenint master_service_settings_read_simple(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct setting_parser_info **roots,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const char **error_r)
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen{
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen struct master_service_settings_input input;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct master_service_settings_output output;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&input);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen input.roots = roots;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen input.module = service->name;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return master_service_settings_read(service, &input, &output, error_r);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen}
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainenpool_t master_service_settings_detach(struct master_service *service)
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen{
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen pool_t pool = service->set_pool;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen settings_parser_deinit(&service->set_parser);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen service->set_pool = NULL;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen return pool;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen}
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst struct master_service_settings *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmaster_service_settings_get(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen void **sets;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen sets = settings_parser_get_list(service->set_parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return sets[0];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid **master_service_settings_get_others(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen return master_service_settings_parser_get_others(service,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen service->set_parser);
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen}
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainenvoid **master_service_settings_parser_get_others(struct master_service *service,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen const struct setting_parser_context *set_parser)
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen{
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen return settings_parser_get_list(set_parser) + 1 +
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen (service->want_ssl_settings ? 1 : 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainenstruct setting_parser_context *
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainenmaster_service_get_settings_parser(struct master_service *service)
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainen{
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainen return service->set_parser;
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainen}
35d87d75ac84ac6aee86c3a1b0dccf627b21457fTimo Sirainen
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainenint master_service_set(struct master_service *service, const char *line)
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen{
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen return settings_parse_line(service->set_parser, line);
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen}
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainenbool master_service_set_has_config_override(struct master_service *service,
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen const char *key)
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen{
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen const char *const *override, *key_root;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen bool ret;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen if (!array_is_created(&service->config_overrides))
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen return FALSE;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen key_root = settings_parse_unalias(service->set_parser, key);
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen if (key_root == NULL)
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen key_root = key;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen array_foreach(&service->config_overrides, override) {
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen T_BEGIN {
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen const char *okey, *okey_root;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen okey = t_strcut(*override, '=');
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen okey_root = settings_parse_unalias(service->set_parser,
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen okey);
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen if (okey_root == NULL)
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen okey_root = okey;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen ret = strcmp(okey_root, key_root) == 0;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen } T_END;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen if (ret)
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen return TRUE;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen }
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen return FALSE;
61f45f55439e542d8645d1851cb56ffc36cd10f6Timo Sirainen}