master-service-settings.c revision 21c1655dbc5fe861a152dc9a8a388d0d64f5ae20
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "istream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "write-full.h"
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen#include "str.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "settings-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stddef.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdlib.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"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen#define CONFIG_READ_TIMEOUT_SECS 10
c6260b961ca7b469a75ab842eeb53d3f904090e3Timo Sirainen#define CONFIG_HANDSHAKE "VERSION\tconfig\t1\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
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct setting_define master_service_setting_defines[] = {
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),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_STR, syslog_facility),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DEF(SET_BOOL, version_ignore),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen SETTING_DEFINE_LIST_END
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct master_service_settings master_service_default_settings = {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(log_path) "",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(info_log_path) "",
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen MEMBER(debug_log_path) "",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(syslog_facility) "mail",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(version_ignore) FALSE
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct setting_parser_info master_service_setting_parser_info = {
1cfdcb36985904eff281fc6d7ea2d13b3c375980Timo Sirainen MEMBER(module_name) "master",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(defines) master_service_setting_defines,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(defaults) &master_service_default_settings,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MEMBER(type_offset) (size_t)-1,
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen MEMBER(struct_size) sizeof(struct master_service_settings),
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen MEMBER(parent_offset) (size_t)-1
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void ATTR_NORETURN
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmaster_service_exec_config(struct master_service *service, bool preserve_home)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen const char **conf_argv, *path, *const *paths, *binary_path;
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen char full_path[PATH_MAX];
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen binary_path = service->argv[0];
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen if (*service->argv[0] == '/') {
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen /* already have the path */
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen } else if (strchr(service->argv[0], '/') != NULL) {
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen /* relative to current directory */
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen if (realpath(service->argv[0], full_path) == NULL)
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen i_fatal("realpath(%s) failed: %m", service->argv[0]);
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen binary_path = full_path;
8bf9eec2783abd32643578460cc6ba4ab0a647f9Timo Sirainen } else if ((path = getenv("PATH")) != NULL) {
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen /* we have to find our executable from path */
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen paths = t_strsplit(path, ":");
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen for (; *paths != NULL; paths++) {
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen path = t_strconcat(*paths, "/", binary_path, NULL);
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen if (access(path, X_OK) == 0) {
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen binary_path = path;
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen break;
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen }
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen }
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!service->keep_environment)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen master_service_env_clean(preserve_home);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* @UNSAFE */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen conf_argv = t_new(const char *, 6 + (service->argc + 1) + 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen conf_argv[0] = DOVECOT_CONFIG_BIN_PATH;
4970e8dfcb18c1353e44b82e4ec836d165b7de82Timo Sirainen conf_argv[1] = "-f";
4970e8dfcb18c1353e44b82e4ec836d165b7de82Timo Sirainen conf_argv[2] = t_strconcat("service=", service->name, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen conf_argv[3] = "-c";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen conf_argv[4] = service->config_path;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conf_argv[5] = "-e";
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen conf_argv[6] = binary_path;
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen memcpy(conf_argv+7, service->argv + 1,
d41ebbd7ae8cfe36a570c644dd7c9c55073fbb20Timo Sirainen (service->argc) * sizeof(conf_argv[0]));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen execv(conf_argv[0], (char **)conf_argv);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("execv(%s) failed: %m", conf_argv[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainenmaster_service_read_config(struct master_service *service, const char *path,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char **error_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen struct stat st;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen int fd, ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (service->config_fd != -1) {
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen fd = service->config_fd;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen service->config_fd = -1;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen } else {
21c1655dbc5fe861a152dc9a8a388d0d64f5ae20Timo Sirainen fd = net_connect_unix_with_retries(path, 1000);
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (fd < 0) {
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen *error_r = t_strdup_printf(
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen "net_connect_unix(%s) failed: %m", path);
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (stat(path, &st) == 0 && !S_ISFIFO(st.st_mode)) {
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen /* it's a file, not a socket */
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen master_service_exec_config(service,
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen input->preserve_home);
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen net_set_nonblock(fd, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen T_BEGIN {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen string_t *str;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str = t_str_new(128);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen str_append(str, CONFIG_HANDSHAKE"REQ");
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen if (input->module != NULL)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen str_printfa(str, "\tmodule=%s", input->module);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen if (input->service != NULL)
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen str_printfa(str, "\tservice=%s", input->service);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (input->username != NULL)
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str_printfa(str, "\tuser=%s", input->username);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (input->local_ip.family != 0) {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str_printfa(str, "\tlip=%s",
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen net_ip2addr(&input->local_ip));
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen }
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (input->remote_ip.family != 0) {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str_printfa(str, "\trip=%s",
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen net_ip2addr(&input->remote_ip));
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen }
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen str_append_c(str, '\n');
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen ret = write_full(fd, str_data(str), str_len(str));
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen } T_END;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (ret < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *error_r = t_strdup_printf("write_full(%s) failed: %m", path);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return fd;
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 }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen settings_parse_set_key_expandeded(parser, service->set_pool,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen t_strcut(overrides[i], '='));
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return 0;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen}
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint master_service_settings_read(struct master_service *service,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const struct master_service_settings_input *input,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen const char **error_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ARRAY_DEFINE(all_roots, const struct setting_parser_info *);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct setting_parser_info *tmp_root;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct setting_parser_context *parser;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen struct istream *istream;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen const char *path = NULL, *error, *env, *const *keys;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen void **sets;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret, fd = -1;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen time_t now, timeout;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if (getenv("DOVECONF_ENV") == NULL &&
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) {
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen path = input->config_path != NULL ? input->config_path :
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen master_service_get_config_path(service);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen fd = master_service_read_config(service, path, input, error_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (fd == -1)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
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 =
e774b2f08b0909382ddc3d2869ae7e3b97205184Timo Sirainen pool_alloconly_create("master service settings", 8192);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen if (input->dyn_parsers != NULL) {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen settings_parser_info_update(service->set_pool,
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen input->dyn_parsers);
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo 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);
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) {
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen istream = i_stream_create_fd(fd, (size_t)-1, FALSE);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen now = time(NULL);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen timeout = now + CONFIG_READ_TIMEOUT_SECS;
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen do {
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen alarm(timeout - now);
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen ret = settings_parse_stream_read(parser, istream);
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) {
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen *error_r = ret > 0 ? t_strdup_printf(
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen "Timeout reading config from %s", path) :
27ca0e561c70933da8834e57f967dee9b41896baTimo Sirainen settings_parser_get_error(parser);
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen (void)close(fd);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen }
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
13fc05b4fae8583f090901702031c4f0e8bf135dTimo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0)
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen service->config_fd = fd;
13fc05b4fae8583f090901702031c4f0e8bf135dTimo Sirainen else if (fd != -1)
13fc05b4fae8583f090901702031c4f0e8bf135dTimo Sirainen (void)close(fd);
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_NO_ENV_SETTINGS) == 0) {
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen /* let environment override settings. especially useful for the
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen settings from userdb. */
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if (settings_parse_environ(parser) < 0) {
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen *error_r = settings_parser_get_error(parser);
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen return -1;
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen }
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen env = getenv("VARS_EXPANDED");
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen if (env != NULL) T_BEGIN {
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen keys = t_strsplit(env, " ");
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen settings_parse_set_keys_expandeded(parser,
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen service->set_pool,
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen keys);
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen } T_END;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (array_is_created(&service->config_overrides)) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (master_service_apply_config_overrides(service, parser,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen error_r) < 0)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return -1;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
8c4b2e0734326ef8e534f25e8ee78ace1fc22d15Timo Sirainen if (!settings_parser_check(parser, service->set_pool, &error)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *error_r = t_strdup_printf("Invalid settings: %s", error);
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 }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo 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;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen memset(&input, 0, sizeof(input));
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen input.roots = roots;
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen input.module = service->name;
44aac2d461b4cb8e05e8c07f2f209372997a8719Timo Sirainen return master_service_settings_read(service, &input, 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{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return settings_parser_get_list(service->set_parser) + 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo 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}