master-service.c revision 2ac0a22865272cb4311a1bd09eb69b475625b3eb
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (C) 2005-2009 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib-signals.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ioloop.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "env-util.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "home-expand.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "restrict-access.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "fd-close-on-exec.h"
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen#include "settings-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "syslog-util.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdlib.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <unistd.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <sys/stat.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <syslog.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MASTER_CONFIG_FILE_ENV "CONFIG_FILE"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainenstruct master_service *master_service;
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void io_listeners_add(struct master_service *service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void io_listeners_remove(struct master_service *service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void master_status_update(struct master_service *service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *master_service_getopt_string(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen return "c:ko:Os:L";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service *service = context;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen which is too common at least while testing :) */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (si->si_signo != SIGINT) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen si->si_signo, dec2str(si->si_pid),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen dec2str(si->si_uid),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_stop(service->ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void master_service_verify_version(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (service->version_string != NULL &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen strcmp(service->version_string, PACKAGE_VERSION) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("Dovecot version mismatch: "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "Master is v%s, %s is v"PACKAGE_VERSION" "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "(if you don't care, set version_ignore=yes)",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->name, service->version_string);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct master_service *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int argc, char *argv[])
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service *service;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen const char *str;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(name != NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#ifdef DEBUG
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen if (getenv("GDB") == NULL &&
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen int count;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen str = getenv("SOCKET_COUNT");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen count = str == NULL ? 0 : atoi(str);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#endif
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* NOTE: we start rooted, so keep the code minimal until
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen restrict_access_by_env() is called */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_init();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* Set a logging prefix temporarily. This will be ignored once the log
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen is properly initialized */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (getenv(MASTER_UID_ENV) == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen flags |= MASTER_SERVICE_FLAG_STANDALONE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service = i_new(struct master_service, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->argc = argc;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->argv = argv;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->name = i_strdup(name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->flags = flags;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->ioloop = io_loop_create();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->service_count_left = (unsigned int)-1;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen service->config_fd = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->config_path = getenv(MASTER_CONFIG_FILE_ENV);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (service->config_path == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->config_path = DEFAULT_CONFIG_FILE_PATH;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->version_string = getenv(MASTER_DOVECOT_VERSION_ENV);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->socket_count = 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->version_string = PACKAGE_VERSION;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen str = getenv("SOCKET_COUNT");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (str != NULL)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen service->socket_count = atoi(str);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen str = getenv("SSL_SOCKET_COUNT");
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (str != NULL)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen service->ssl_socket_count = atoi(str);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* set up some kind of logging until we know exactly how and where
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen we want to log */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (getenv("LOG_SERVICE") != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_internal();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (getenv("USER") != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_prefix(t_strdup_printf("%s(%s): ",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen name, getenv("USER")));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_prefix(t_strdup_printf("%s: ", name));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen master_service_verify_version(service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return service;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_init_log(struct master_service *service, const char *prefix,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int max_lines_per_sec)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *path;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0 &&
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR) == 0) {
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen i_set_failure_file("/dev/stderr", "");
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen return;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen }
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (getenv("LOG_SERVICE") != NULL && !service->log_directly) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* logging via log service */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_internal();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_prefix(prefix);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->set == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_set_failure_file("/dev/stderr", prefix);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (*service->set->log_path == '\0') {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* log to syslog */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int facility;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!syslog_facility_find(service->set->syslog_facility,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &facility))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen facility = LOG_MAIL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_prefix(prefix);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* log to file or stderr */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen path = home_expand(service->set->log_path);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_file(path, prefix);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen path = home_expand(service->set->info_log_path);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (*path != '\0')
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_info_file(path);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_timestamp_format(service->set->log_timestamp);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool master_service_parse_option(struct master_service *service,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int opt, const char *arg)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (opt) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'c':
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->config_path = arg;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'k':
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->keep_environment = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen case 'o':
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (!array_is_created(&service->config_overrides))
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen i_array_init(&service->config_overrides, 16);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen array_append(&service->config_overrides, &arg, 1);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen break;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen case 'O':
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen service->default_settings = TRUE;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case 's':
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((i = atoi(arg)) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("Invalid socket count: %s", arg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->socket_count = i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'L':
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->log_directly = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen default:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void master_status_error(void *context)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct master_service *service = context;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* status fd is a write-only pipe, so if we're here it means the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master wants us to die (or died itself). don't die until all
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service connections are finished. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&service->io_status_error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* the log fd may also be closed already, don't die when trying to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen log later */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_set_failure_ignore_errors(TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->master_status.available_count ==
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_stop(service);
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen else
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen io_listeners_remove(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_init_finish(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct stat st;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *value;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->total_available_count == 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->service_count_left == (unsigned int)-1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* set default signal handlers */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_init();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_ignore(SIGPIPE, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_ignore(SIGALRM, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_set_handler(SIGINT, TRUE, sig_die, service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_set_handler(SIGTERM, TRUE, sig_die, service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (fstat(MASTER_STATUS_FD, &st) < 0 || !S_ISFIFO(st.st_mode))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("Must be started by dovecot master process");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* initialize master_status structure */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen value = getenv(MASTER_UID_ENV);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (value == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal(MASTER_UID_ENV" not set");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.pid = getpid();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.uid =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (unsigned int)strtoul(value, NULL, 10);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* set the default limit */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen value = getenv(MASTER_CLIENT_LIMIT_ENV);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen count = value == NULL ? 0 :
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (unsigned int)strtoul(value, NULL, 10);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (count == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal(MASTER_CLIENT_LIMIT_ENV" not set");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_set_client_limit(service, count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* start listening errors for status fd, it means master died */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->io_status_error = io_add(MASTER_STATUS_FD, IO_ERROR,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_error, service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_set_client_limit(service, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_set_service_count(service, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_listeners_add(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STD_CLIENT) != 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we already have a connection to be served */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_update(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid master_service_env_clean(bool preserve_home)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *user, *tz, *home;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen#ifdef DEBUG
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen bool gdb = getenv("GDB") != NULL;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen#endif
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user = getenv("USER");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (user != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user = t_strconcat("USER=", user, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tz = getenv("TZ");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (tz != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tz = t_strconcat("TZ=", tz, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen home = preserve_home ? getenv("HOME") : NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (home != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen home = t_strconcat("HOME=", home, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* Note that if the original environment was set with env_put(), the
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen environment strings will be invalid after env_clean(). That's why
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen we t_strconcat() them above. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen env_clean();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (user != NULL) env_put(user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (tz != NULL) env_put(tz);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (home != NULL) env_put(home);
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen#ifdef DEBUG
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (gdb) env_put("GDB=1");
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen#endif
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_set_client_limit(struct master_service *service,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int client_limit)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->master_status.available_count ==
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count = client_limit;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count = client_limit;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenunsigned int master_service_get_client_limit(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return service->total_available_count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_set_service_count(struct master_service *service,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int count)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int used;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen used = service->total_available_count -
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(count >= used);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->total_available_count > count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count = count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count = count - used;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->service_count_left = count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenunsigned int master_service_get_service_count(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return service->service_count_left;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenunsigned int master_service_get_socket_count(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return service->socket_count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *master_service_get_config_path(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return service->config_path;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *master_service_get_version_string(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return service->version_string;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainenconst char *master_service_get_name(struct master_service *service)
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen{
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen return service->name;
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen}
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_run(struct master_service *service,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_connection_callback_t *callback)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->callback = callback;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_run(service->ioloop);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->callback = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid master_service_stop(struct master_service *service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_stop(service->ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid master_service_anvil_send(struct master_service *service, const char *cmd)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen ssize_t ret;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen ret = write(MASTER_ANVIL_FD, cmd, strlen(cmd));
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (ret < 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("write(anvil) failed: %m");
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen else if (ret == 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("write(anvil) failed: EOF");
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen else {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_assert((size_t)ret == strlen(cmd));
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_client_connection_destroyed(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* we can listen again */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen io_listeners_add(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->total_available_count > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->service_count_left != service->total_available_count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->service_count_left == (unsigned int)-1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we have only limited amount of service requests left */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->service_count_left > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->service_count_left--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->service_count_left == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->master_status.available_count ==
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_stop(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_update(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->io_status_error == NULL &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count ==
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* master has closed the connection and we have nothing else
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen to do anymore. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_stop(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid master_service_deinit(struct master_service **_service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service *service = *_service;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *_service = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_listeners_remove(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->io_status_error != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&service->io_status_error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->io_status_write != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&service->io_status_write);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (array_is_created(&service->config_overrides))
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen array_free(&service->config_overrides);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen if (service->set_parser != NULL) {
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen settings_parser_deinit(&service->set_parser);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen pool_unref(&service->set_pool);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_signals_deinit();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_destroy(&service->ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(service->name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_deinit();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void master_service_listen(struct master_service_listener *l)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct master_service_connection conn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (l->service->master_status.available_count == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we are full. stop listening for now. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_listeners_remove(l->service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memset(&conn, 0, sizeof(conn));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn.listen_fd = l->fd;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn.fd = net_accept(l->fd, &conn.remote_ip, &conn.remote_port);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn.fd < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn.fd == -1)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (errno != ENOTSOCK) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("net_accept() failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_listeners_remove(l->service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* it's not a socket. probably a fifo. use the "listener"
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen as the connection fd and stop the listener. */
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen io_remove(&l->io);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen conn.fd = dup(l->fd);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (conn.fd == -1) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen i_error("dup() failed: %m");
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen return;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&l->io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen conn.ssl = l->ssl;
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainen net_set_nonblock(conn.fd, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l->service->master_status.available_count--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_update(l->service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l->service->callback(&conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainenstatic void io_listeners_init(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->socket_count == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->listeners =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_new(struct master_service_listener, service->socket_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0; i < service->socket_count; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct master_service_listener *l = &service->listeners[i];
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l->service = service;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l->fd = MASTER_LISTEN_FD_FIRST + i;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (i >= service->socket_count - service->ssl_socket_count)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen l->ssl = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainenstatic void io_listeners_add(struct master_service *service)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen unsigned int i;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (service->listeners == NULL)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen io_listeners_init(service);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen for (i = 0; i < service->socket_count; i++) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen struct master_service_listener *l = &service->listeners[i];
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (l->io == NULL) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen l->io = io_add(MASTER_LISTEN_FD_FIRST + i, IO_READ,
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen master_service_listen, l);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen}
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void io_listeners_remove(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->listeners != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0; i < service->socket_count; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->listeners[i].io != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&service->listeners[i].io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic bool master_status_update_is_important(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->master_status.available_count == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!service->initial_status_sent)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void master_status_update(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ssize_t ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->master_status.pid == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return; /* closed */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = write(MASTER_STATUS_FD, &service->master_status,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sizeof(service->master_status));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* success */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->io_status_write != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* delayed important update sent successfully */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&service->io_status_write);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->initial_status_sent = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else if (ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* shouldn't happen? */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("write(master_status_fd) returned 0");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.pid = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else if (errno != EAGAIN) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* failure */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (errno != EPIPE)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("write(master_status_fd) failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.pid = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else if (master_status_update_is_important(service)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* reader is busy, but it's important to get this notification
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen through. send it when possible. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->io_status_write == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->io_status_write =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_add(MASTER_STATUS_FD, IO_WRITE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_update, service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}