master-service-settings.c revision 194755bdfb97c07ca8b9df071099f68947b971e3
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#define DOVECOT_CONFIG_SOCKET_PATH PKG_RUNDIR"/config"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#define CONFIG_HANDSHAKE "VERSION\tconfig\t2\t0\n"
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen { type, #name, offsetof(struct master_service_settings, name), NULL }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic const struct setting_define master_service_setting_defines[] = {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic const struct master_service_settings master_service_default_settings = {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen .log_timestamp = DEFAULT_FAILURE_STAMP_FORMAT,
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainenconst struct setting_parser_info master_service_setting_parser_info = {
1cc7a6c6a986b972fdb7eac146f4ca8036aca4e6Timo Sirainen .struct_size = sizeof(struct master_service_settings),
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenmaster_service_exec_config(struct master_service *service, bool preserve_home)
d4c3d55021bcbf2b062f4782b1cde9115d35aefcTimo Sirainen const char **conf_argv, *path, *const *paths, *binary_path;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* already have the path */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen } else if (strchr(service->argv[0], '/') != NULL) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* relative to current directory */
e597ab14b6fc01a602b35d26177d09643af8fed5Timo Sirainen /* we have to find our executable from path */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen path = t_strconcat(*paths, "/", binary_path, NULL);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen /* @UNSAFE */
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen conf_argv = t_new(const char *, 6 + (service->argc + 1) + 1);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen conf_argv[2] = t_strconcat("service=", service->name, NULL);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_fatal("execv(%s) failed: %m", conf_argv[0]);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenconfig_exec_fallback(struct master_service *service,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen const struct master_service_settings_input *input)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen path = input->config_path != NULL ? input->config_path :
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen !S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode)) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen /* it's a file, not a socket/pipe */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen master_service_exec_config(service, input->preserve_home);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenmaster_service_open_config(struct master_service *service,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen const struct master_service_settings_input *input,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *path_r = path = input->config_path != NULL ? input->config_path :
0b32a8d139f6a4f2b18a6444fc66d31b4a1b0da6Timo Sirainen if (service->config_fd != -1 && input->config_path == NULL) {
0b32a8d139f6a4f2b18a6444fc66d31b4a1b0da6Timo Sirainen /* use the already opened config socket */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (service->config_path_is_default && input->config_path == NULL) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen /* first try to connect to the default config socket.
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen configuration may contain secrets, so in default config
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen this fails because the socket is 0600. it's useful for
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen developers though. :) */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fd = net_connect_unix(DOVECOT_CONFIG_SOCKET_PATH);
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen /* fallback to executing doveconf */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen fd = net_connect_unix_with_retries(path, 1000);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *error_r = t_strdup_printf("net_connect_unix(%s) failed: %m",
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const struct master_service_settings_input *input)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(str, "\tmodule=%s", input->module);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(str, "\tservice=%s", input->service);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen str_printfa(str, "\tuser=%s", input->username);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(str, "\tlip=%s", net_ip2addr(&input->local_ip));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(str, "\trip=%s", net_ip2addr(&input->remote_ip));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen str_printfa(str, "\tlhost=%s", input->local_host);
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen str_printfa(str, "\tlhost=%s", input->remote_host);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenconfig_send_request(const struct master_service_settings_input *input,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen int fd, const char *path, const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ret = write_full(fd, str_data(str), str_len(str));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen *error_r = t_strdup_printf("write_full(%s) failed: %m", path);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenmaster_service_apply_config_overrides(struct master_service *service,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char *const *overrides;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen unsigned int i, count;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen overrides = array_get(&service->config_overrides, &count);
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen for (i = 0; i < count; i++) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (settings_parse_line(parser, overrides[i]) < 0) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen settings_parse_set_key_expandeded(parser, service->set_pool,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenconfig_read_reply_header(struct istream *istream, const char *path, pool_t pool,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const struct master_service_settings_input *input,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen struct master_service_settings_output *output_r,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen t_strdup_printf("read(%s) failed: %m", path) :
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen t_strdup_printf("read(%s) failed: EOF", path);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char *const *arg = t_strsplit(line, "\t");
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen else if (strcmp(*arg, "service-uses-remote") == 0)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen output_r->specific_services = array_idx(&services, 0);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenint master_service_settings_read(struct master_service *service,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const struct master_service_settings_input *input,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct master_service_settings_output *output_r,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const char **error_r)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ARRAY_DEFINE(all_roots, const struct setting_parser_info *);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen unsigned int i;
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS) == 0) {
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen fd = master_service_open_config(service, input, &path, error_r);
53895e43662b29a954d8f70bd2a27bafbdb4bbe8Timo Sirainen if (config_send_request(input, fd, path, error_r) < 0) {
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen pool_alloconly_create("master service settings", 8192);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen settings_parser_info_update(service->set_pool,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen p_array_init(&all_roots, service->set_pool, 8);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen tmp_root = &master_service_setting_parser_info;
0b32a8d139f6a4f2b18a6444fc66d31b4a1b0da6Timo Sirainen array_append(&all_roots, &input->roots[i], 1);
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen parser = settings_parser_init_list(service->set_pool,
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen array_idx(&all_roots, 0), array_count(&all_roots),
8b3f557cda9023b87b183e364cb7f7c7b0906950Timo Sirainen istream = i_stream_create_fd(fd, (size_t)-1, FALSE);
if (ret != 0) {
if (ret > 0) {
error_r) < 0)
const char **error_r)
return pool;
const struct master_service_settings *
void **sets;
return sets[0];