master-service.c revision 7487ff578435377bbeefffdbfb78ca09ed1292df
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"
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"
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
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{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "c:ks: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
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (getenv("GDB") == NULL) {
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;
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
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_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;
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);
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;
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);
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
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
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_client_connection_destroyed(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->listeners == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we can listen again */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_listeners_add(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
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);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo 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"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen as the connection fd */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&l->io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn.fd = l->fd;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen conn.ssl = l->ssl;
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
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void io_listeners_add(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;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l->io = io_add(MASTER_LISTEN_FD_FIRST + i, IO_READ,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_listen, l);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (i >= service->socket_count - service->ssl_socket_count)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen l->ssl = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo 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 i_free_and_null(service->listeners);
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}