bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib-signals.h"
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen#include "event-filter.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ioloop.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "path-util.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "array.h"
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen#include "strescape.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "env-util.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "home-expand.h"
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen#include "process-title.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "restrict-access.h"
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen#include "settings-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "syslog-util.h"
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen#include "stats-client.h"
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen#include "master-instance.h"
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen#include "master-login.h"
5a6343181a5183b1ae1c39d40fc5a1deb3b840d9Timo Sirainen#include "master-service-ssl.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-private.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service-settings.h"
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi#include "iostream-ssl.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
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
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen/* when we're full of connections, how often to check if login state has
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen changed. we normally notice it immediately because of a signal, so this is
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen just a fallback against race conditions. */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen#define MASTER_SERVICE_STATE_CHECK_MSECS 1000
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen/* If die callback hasn't managed to stop the service for this many seconds,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen force it. */
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen#define MASTER_SERVICE_DIE_TIMEOUT_MSECS (30*1000)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainenstruct master_service *master_service;
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainenstatic void master_service_io_listeners_close(struct master_service *service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void master_service_refresh_login_state(struct master_service *service);
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainenstatic void
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainenmaster_status_send(struct master_service *service, bool important_update);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *master_service_getopt_string(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
104318260228780a5c6b3181b3401e8e504e2776Timo Sirainen return "c:i:ko:OL";
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
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* SIGINT comes either from master process or from keyboard. we don't
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen want to log it in either case.*/
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));
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_NO_IDLE_DIE) != 0) {
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen /* never die when idling */
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen return;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen } else if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* SIGINT came from master. die only if we're not handling
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen any clients currently. */
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (service->master_status.available_count !=
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen service->total_available_count)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen return;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen if (service->idle_die_callback != NULL &&
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainen !service->idle_die_callback()) {
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainen /* we don't want to die - send a notification to master
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainen so it doesn't think we're ignoring it completely. */
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainen master_status_send(service, FALSE);
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen return;
2f94ca6b0f70641fe31c8e1f93404ca0df8bb289Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen service->killed = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_stop(service->ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainenstatic void sig_close_listeners(const siginfo_t *si ATTR_UNUSED, void *context)
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen{
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen struct master_service *service = context;
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen /* We're in a signal handler: Close listeners immediately so master
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen can successfully restart. We can safely close only those listeners
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen that don't have an io, but this shouldn't be a big problem. If there
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen is an active io, the service is unlikely to be unresposive for
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen longer periods of time, so the listener gets closed soon enough via
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen master_status_error().
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen For extra safety we don't actually close() the fd, but instead
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen replace it with /dev/null. This way it won't be replaced with some
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen other new fd and attempted to be used in unexpected ways. */
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen for (unsigned int i = 0; i < service->socket_count; i++) {
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen if (service->listeners[i].fd != -1 &&
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen service->listeners[i].io == NULL) {
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen if (dup2(dev_null_fd, service->listeners[i].fd) < 0)
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen lib_signals_syscall_error("signal: dup2(/dev/null, listener) failed: ");
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen service->listeners[i].closed = TRUE;
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen }
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen }
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen}
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainensig_state_changed(const siginfo_t *si ATTR_UNUSED, void *context)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct master_service *service = context;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_refresh_login_state(service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainenstatic void master_service_verify_version_string(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)",
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen service->version_string, service->name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainenstatic void master_service_init_socket_listeners(struct master_service *service)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen{
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen unsigned int i;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char *value;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen bool have_ssl_sockets = FALSE;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (service->socket_count == 0)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen return;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->listeners =
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen i_new(struct master_service_listener, service->socket_count);
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen for (i = 0; i < service->socket_count; i++) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen struct master_service_listener *l = &service->listeners[i];
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen l->service = service;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen l->fd = MASTER_LISTEN_FD_FIRST + i;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen value = getenv(t_strdup_printf("SOCKET%u_SETTINGS", i));
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (value != NULL) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char *const *settings =
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen t_strsplit_tabescaped(value);
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (*settings != NULL) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen l->name = i_strdup_empty(*settings);
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen settings++;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen while (*settings != NULL) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (strcmp(*settings, "ssl") == 0) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen l->ssl = TRUE;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen have_ssl_sockets = TRUE;
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen } else if (strcmp(*settings, "haproxy") == 0) {
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen l->haproxy = TRUE;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen settings++;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->want_ssl_settings = have_ssl_sockets ||
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_USE_SSL_SETTINGS) != 0;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen}
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct master_service *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenmaster_service_init(const char *name, enum master_service_flags flags,
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen int *argc, char **argv[], const char *getopt_str)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service *service;
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen data_stack_frame_t datastack_frame_id = 0;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen unsigned int count;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen const char *value;
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi const char *error;
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) {
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv("SOCKET_COUNT");
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch if (value == NULL || str_to_uint(value, &count) < 0)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch count = 0;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen fd_debug_verify_leaks(MASTER_LISTEN_FD_FIRST + count, 1024);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#endif
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen /* make sure we can dump core, at least until
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen privileges are dropped. (i'm not really sure why this
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen is needed, because doing the same just before exec
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen doesn't help, and exec shouldn't affect this with
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen non-setuid/gid binaries..) */
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen restrict_access_allow_coredumps(TRUE);
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen }
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 */
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s(init): ", name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen /* make sure all the data stack allocations during init will be freed
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen before we get to ioloop. the corresponding t_pop() is in
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen master_service_init_finish(). */
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen if ((flags & MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME) == 0)
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen datastack_frame_id = t_push(NULL);
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen /* ignore these signals as early as possible */
d6b3cfd855c0eebed68be50d3111de1b5a6afeb0Timo Sirainen lib_signals_init();
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen lib_signals_ignore(SIGPIPE, TRUE);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen lib_signals_ignore(SIGALRM, FALSE);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (getenv(MASTER_UID_ENV) == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen flags |= MASTER_SERVICE_FLAG_STANDALONE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1904e2fc786dbc037039d284b371730777277fc5Aki Tuomi process_title_init(*argc, argv);
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service = i_new(struct master_service, 1);
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen service->argc = *argc;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen service->argv = *argv;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->name = i_strdup(name);
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen /* keep getopt_str first in case it contains "+" */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen service->getopt_str = *getopt_str == '\0' ?
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen i_strdup(master_service_getopt_string()) :
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen i_strconcat(getopt_str, master_service_getopt_string(), NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->flags = flags;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service->ioloop = io_loop_create();
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen service->service_count_left = UINT_MAX;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen service->config_fd = -1;
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen service->datastack_frame_id = datastack_frame_id;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen service->config_path = i_strdup(getenv(MASTER_CONFIG_FILE_ENV));
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen if (service->config_path == NULL)
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen service->config_path = i_strdup(DEFAULT_CONFIG_FILE_PATH);
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen else
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen service->config_path_from_master = TRUE;
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 }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen /* listener configuration */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv("SOCKET_COUNT");
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch if (value != NULL && str_to_uint(value, &service->socket_count) < 0)
c93aca832ee532010ead91b85fa9f614132e1be2Stephan Bosch i_fatal("Invalid SOCKET_COUNT environment");
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen T_BEGIN {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen master_service_init_socket_listeners(service);
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen } T_END;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi /* load SSL module if necessary */
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi if (service->want_ssl_settings && ssl_module_load(&error) < 0)
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi i_fatal("Cannot load SSL module: %s", error);
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi
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();
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen if (getenv("USER") != NULL)
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s(%s): ", name, getenv("USER"));
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen else
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s: ", name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen /* Initialize debug logging */
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen value = getenv(DOVECOT_LOG_DEBUG_ENV);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen if (value != NULL) {
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen struct event_filter *filter = event_filter_create();
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen const char *error;
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen if (master_service_log_debug_parse(filter, value, &error) < 0) {
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen i_error("Invalid "DOVECOT_LOG_DEBUG_ENV" - ignoring: %s",
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen error);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen }
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen event_set_global_debug_log_filter(filter);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen event_filter_unref(&filter);
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen }
1fd856f1177990003ec3829267b9e490c095d836Timo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) {
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* initialize master_status structure */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv(MASTER_UID_ENV);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (value == NULL ||
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen str_to_uint(value, &service->master_status.uid) < 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen i_fatal(MASTER_UID_ENV" missing");
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen service->master_status.pid = getpid();
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* set the default limit */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv(MASTER_CLIENT_LIMIT_ENV);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (value == NULL || str_to_uint(value, &count) < 0 ||
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen count == 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen i_fatal(MASTER_CLIENT_LIMIT_ENV" missing");
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen master_service_set_client_limit(service, count);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* seve the process limit */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv(MASTER_PROCESS_LIMIT_ENV);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (value != NULL && str_to_uint(value, &count) == 0 &&
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen count > 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen service->process_limit = count;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen value = getenv(MASTER_PROCESS_MIN_AVAIL_ENV);
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen if (value != NULL && str_to_uint(value, &count) == 0 &&
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen count > 0)
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen service->process_min_avail = count;
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* set the default service count */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen value = getenv(MASTER_SERVICE_COUNT_ENV);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (value != NULL && str_to_uint(value, &count) == 0 &&
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen count > 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen master_service_set_service_count(service, count);
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen /* set the idle kill timeout */
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen value = getenv(MASTER_SERVICE_IDLE_KILL_ENV);
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen if (value != NULL && str_to_uint(value, &count) == 0)
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen service->idle_kill_secs = count;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen } else {
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen master_service_set_client_limit(service, 1);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen master_service_set_service_count(service, 1);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen if ((flags & MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN) != 0) {
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen /* since we're going to keep the config socket open anyway,
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen open it now so we can read settings even after privileges
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen are dropped. */
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen master_service_config_socket_try_open(service);
b7b9d4be2a1ff399026a5d6feeffd3a048f22be0Timo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen master_service_verify_version_string(service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return service;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainenint master_getopt(struct master_service *service)
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen{
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen int c;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen i_assert(master_getopt_str_is_valid(service->getopt_str));
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen while ((c = getopt(service->argc, service->argv,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen service->getopt_str)) > 0) {
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (!master_service_parse_option(service, c, optarg))
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen break;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen }
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen return c;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen}
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainenbool master_getopt_str_is_valid(const char *str)
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen{
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen unsigned int i, j;
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen /* make sure there are no duplicates. there are few enough characters
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen that this should be fast enough. */
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen for (i = 0; str[i] != '\0'; i++) {
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen if (str[i] == ':' || str[i] == '+' || str[i] == '-')
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen continue;
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen for (j = i+1; str[j] != '\0'; j++) {
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen if (str[i] == str[j])
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen return FALSE;
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen }
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen }
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen return TRUE;
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen}
9b0f6b90ff8d1d6efd718b0d7cbe01b2454e9fd6Timo Sirainen
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainenstatic bool
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainenmaster_service_try_init_log(struct master_service *service,
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen const char *prefix)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen const char *path, *timestamp;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0 &&
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR) == 0) {
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen timestamp = getenv("LOG_STDERR_TIMESTAMP");
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen if (timestamp != NULL)
e52f55c08f6f1b4fbc5765bf6aa9c7daee0785c3Timo Sirainen i_set_failure_timestamp_format(timestamp);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen i_set_failure_file("/dev/stderr", "");
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen return TRUE;
719abeb2088987f213a33a7dd1fe78958beaef03Timo Sirainen }
719abeb2088987f213a33a7dd1fe78958beaef03Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (getenv("LOG_SERVICE") != NULL && !service->log_directly) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* logging via log service */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_internal();
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s", prefix);
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (service->set == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_set_failure_file("/dev/stderr", prefix);
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen /* may be called again after we have settings */
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (strcmp(service->set->log_path, "syslog") != 0) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* error logging goes to file or stderr */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen path = home_expand(service->set->log_path);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen i_set_failure_file(path, prefix);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (strcmp(service->set->log_path, "syslog") == 0 ||
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen strcmp(service->set->info_log_path, "syslog") == 0 ||
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen strcmp(service->set->debug_log_path, "syslog") == 0) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* something gets logged 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);
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("%s", prefix);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (strcmp(service->set->log_path, "syslog") != 0) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* set error handlers back to file */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen i_set_fatal_handler(default_fatal_handler);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen i_set_error_handler(default_error_handler);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*service->set->info_log_path != '\0' &&
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen strcmp(service->set->info_log_path, "syslog") != 0) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen path = home_expand(service->set->info_log_path);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*path != '\0')
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen i_set_info_file(path);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*service->set->debug_log_path != '\0' &&
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen strcmp(service->set->debug_log_path, "syslog") != 0) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen path = home_expand(service->set->debug_log_path);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*path != '\0')
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen i_set_debug_file(path);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_set_failure_timestamp_format(service->set->log_timestamp);
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen return TRUE;
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen}
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainenvoid master_service_init_log(struct master_service *service,
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen const char *prefix)
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen{
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen if (service->log_initialized) {
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen /* change only the prefix */
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen i_set_failure_prefix("%s", prefix);
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen return;
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen }
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen if (master_service_try_init_log(service, prefix))
61eec37dd74af9434ff876bc739a4cbe4a0ba8b4Timo Sirainen service->log_initialized = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainenvoid master_service_init_stats_client(struct master_service *service,
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen bool silent_notfound_errors)
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen{
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen if (service->stats_client == NULL &&
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen service->set->stats_writer_socket_path[0] != '\0') T_BEGIN {
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen const char *path = t_strdup_printf("%s/%s",
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen service->set->base_dir,
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen service->set->stats_writer_socket_path);
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen service->stats_client =
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen stats_client_init(path, silent_notfound_errors);
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen } T_END;
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen}
f6f23086d0259d50cde3bd5d4180d67d820d293dTimo Sirainen
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainenvoid master_service_set_die_with_master(struct master_service *service,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen bool set)
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen{
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen service->die_with_master = set;
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen}
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainenvoid master_service_set_die_callback(struct master_service *service,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen void (*callback)(void))
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen{
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen service->die_callback = callback;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen}
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainenvoid master_service_set_idle_die_callback(struct master_service *service,
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen bool (*callback)(void))
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen{
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen service->idle_die_callback = callback;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen}
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainenstatic bool get_instance_config(const char *name, const char **config_path_r)
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen{
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen struct master_instance_list *list;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen const struct master_instance *inst;
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen const char *instance_path, *path;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen /* note that we don't have any settings yet. we're just finding out
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen which dovecot.conf we even want to read! so we must use the
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen hardcoded state_dir path. */
d9515a2eaa94c8287188c38fc28028727671e729Timo Sirainen instance_path = t_strconcat(PKG_STATEDIR"/"MASTER_INSTANCE_FNAME, NULL);
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen list = master_instance_list_init(instance_path);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen inst = master_instance_list_find_by_name(list, name);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen if (inst != NULL) {
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen path = t_strdup_printf("%s/dovecot.conf", inst->base_dir);
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi const char *error;
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi if (t_readlink(path, config_path_r, &error) < 0)
dd645357a6b851a3a9527d16e2bced731e46dcaaMartti Rannanjärvi i_fatal("t_readlink(%s) failed: %s", path, error);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen }
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen master_instance_list_deinit(&list);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen return inst != NULL;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen}
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool master_service_parse_option(struct master_service *service,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int opt, const char *arg)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen const char *path;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (opt) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'c':
85b4143f07c504294dd4e5b168e9bfb293515c31Josef 'Jeff' Sipek i_free(service->config_path);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen service->config_path = i_strdup(arg);
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen service->config_path_changed_with_param = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen case 'i':
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen if (!get_instance_config(arg, &path))
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen i_fatal("Unknown instance name: %s", arg);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen service->config_path = i_strdup(path);
6efdbeab167483597bef087f70ea852d1256a082Timo Sirainen service->config_path_changed_with_param = TRUE;
96d19229e5f322411eb84446e5477d8170cfa5afTimo 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':
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen service->flags |= MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo 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
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainenstatic void master_service_error(struct master_service *service)
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen{
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen master_service_stop_new_connections(service);
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen if (service->master_status.available_count ==
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen service->total_available_count || service->die_with_master) {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (service->die_callback == NULL)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen master_service_stop(service);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen else {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen service->to_die =
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen timeout_add(MASTER_SERVICE_DIE_TIMEOUT_MSECS,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen master_service_stop,
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen service);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen service->die_callback();
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen }
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen }
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen}
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainenstatic void master_status_error(struct master_service *service)
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
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen master_service_error(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_init_finish(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen enum libsig_flags sigint_flags = LIBSIG_FLAG_DELAYED;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct stat st;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* set default signal handlers */
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0)
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen sigint_flags |= LIBSIG_FLAG_RESTART;
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen lib_signals_set_handler(SIGINT, sigint_flags, sig_die, service);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen lib_signals_set_handler(SIGTERM, LIBSIG_FLAG_DELAYED, sig_die, service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_TRACK_LOGIN_STATE) != 0) {
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen lib_signals_set_handler(SIGUSR1, LIBSIG_FLAGS_SAFE,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen sig_state_changed, service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
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 /* start listening errors for status fd, it means master died */
cbcba924a745c938260fd39cb284175b75f8eaf2Timo Sirainen service->io_status_error = io_add(MASTER_DEAD_FD, IO_ERROR,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_status_error, service);
4cbe2b4ee234317331eadd1768d9ce433adb60e1Timo Sirainen lib_signals_set_handler(SIGQUIT, 0, sig_close_listeners, service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen master_service_io_listeners_add(service);
8b5c520883aa37bb55646286d375fdbae294d710Timo Sirainen if (service->want_ssl_settings &&
8b5c520883aa37bb55646286d375fdbae294d710Timo Sirainen (service->flags & MASTER_SERVICE_FLAG_NO_SSL_INIT) == 0)
5a6343181a5183b1ae1c39d40fc5a1deb3b840d9Timo Sirainen master_service_ssl_ctx_init(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);
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen
0679f8a70a8dda43b204ae35fc6a903818cc6584Timo Sirainen /* close data stack frame opened by master_service_init() */
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME) == 0) {
3c5ee51327f075dc13cdacf46135f7f0abbdaafeTimo Sirainen if (!t_pop(&service->datastack_frame_id))
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen i_panic("Leaked t_pop() call");
28bf8f762fcd21c57bf71822cf818447babce9a0Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainenstatic void master_service_import_environment_real(const char *import_environment)
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen{
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen const char *const *envs, *key, *value;
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen ARRAY_TYPE(const_string) keys;
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen if (*import_environment == '\0')
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen return;
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen t_array_init(&keys, 8);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen /* preserve existing DOVECOT_PRESERVE_ENVS */
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen value = getenv(DOVECOT_PRESERVE_ENVS_ENV);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen if (value != NULL)
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen array_append(&keys, &value, 1);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen /* add new environments */
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen envs = t_strsplit_spaces(import_environment, " ");
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen for (; *envs != NULL; envs++) {
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen value = strchr(*envs, '=');
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen if (value == NULL)
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen key = *envs;
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen else {
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen key = t_strdup_until(*envs, value);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen env_put(*envs);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen }
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen array_append(&keys, &key, 1);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen }
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen array_append_zero(&keys);
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen value = t_strarray_join(array_idx(&keys, 0), " ");
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen env_put(t_strconcat(DOVECOT_PRESERVE_ENVS_ENV"=", value, NULL));
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen}
8a0a8c982a6ffc75a4b1c8717b6180a811655794Timo Sirainen
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainenvoid master_service_import_environment(const char *import_environment)
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen{
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen T_BEGIN {
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen master_service_import_environment_real(import_environment);
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen } T_END;
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen}
c6dfc77cb24ba1bb72437896080d3177b653e2afTimo Sirainen
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainenvoid master_service_env_clean(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen const char *value = getenv(DOVECOT_PRESERVE_ENVS_ENV);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen if (value == NULL || *value == '\0')
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen env_clean();
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen else T_BEGIN {
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen value = t_strconcat(value, " "DOVECOT_PRESERVE_ENVS_ENV, NULL);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen env_clean_except(t_strsplit_spaces(value, " "));
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen } T_END;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_set_client_limit(struct master_service *service,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int client_limit)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen unsigned int used;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->master_status.available_count ==
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen used = service->total_available_count -
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen service->master_status.available_count;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen i_assert(client_limit >= used);
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->total_available_count = client_limit;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen service->master_status.available_count = client_limit - used;
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
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainenunsigned int master_service_get_process_limit(struct master_service *service)
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen{
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen return service->process_limit;
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen}
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainenunsigned int master_service_get_process_min_avail(struct master_service *service)
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen{
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen return service->process_min_avail;
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen}
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainenunsigned int master_service_get_idle_kill_secs(struct master_service *service)
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen{
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen return service->idle_kill_secs;
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen}
0161376aac025266d8654577c4b9ce371ffc87eaTimo 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
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainenconst char *master_service_get_socket_name(struct master_service *service,
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen int listen_fd)
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen{
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen unsigned int i;
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen i_assert(listen_fd >= MASTER_LISTEN_FD_FIRST);
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen i = listen_fd - MASTER_LISTEN_FD_FIRST;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen i_assert(i < service->socket_count);
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen return service->listeners[i].name != NULL ?
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->listeners[i].name : "";
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen}
7f1b897201d80c83c96b0d663f2a14c517d48f14Timo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenvoid master_service_set_avail_overflow_callback(struct master_service *service,
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen void (*callback)(void))
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen{
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen service->avail_overflow_callback = callback;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen}
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo 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
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainenvoid master_service_stop_new_connections(struct master_service *service)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen{
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen unsigned int current_count;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen if (service->stopping)
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen return;
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen service->stopping = TRUE;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen master_service_io_listeners_remove(service);
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen master_service_io_listeners_close(service);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen /* make sure we stop after servicing current connections */
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen current_count = service->total_available_count -
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen service->master_status.available_count;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen service->service_count_left = current_count;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen service->total_available_count = current_count;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen if (current_count == 0)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen master_service_stop(service);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen else {
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen /* notify master that we're not accepting any more
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen connections */
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen service->master_status.available_count = 0;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen master_status_update(service);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen }
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen if (service->login != NULL)
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen master_login_stop(service->login);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen}
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenbool master_service_is_killed(struct master_service *service)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen{
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen return service->killed;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen}
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen
57397188558fcd1a9e24dbbbd2952eac9c45c20dTimo Sirainenbool master_service_is_master_stopped(struct master_service *service)
57397188558fcd1a9e24dbbbd2952eac9c45c20dTimo Sirainen{
03baa1c4c51f7b08fb285e82b528fcb00ac09ebfTimo Sirainen return service->io_status_error == NULL &&
03baa1c4c51f7b08fb285e82b528fcb00ac09ebfTimo Sirainen (service->flags & MASTER_SERVICE_FLAG_STANDALONE) == 0;
57397188558fcd1a9e24dbbbd2952eac9c45c20dTimo Sirainen}
57397188558fcd1a9e24dbbbd2952eac9c45c20dTimo 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));
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen if (ret < 0) {
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen if (errno == EPIPE) {
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen /* anvil process was probably recreated, don't bother
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen logging an error about losing connection to it */
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen return;
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("write(anvil) failed: %m");
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo 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
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainenvoid master_service_client_connection_created(struct master_service *service)
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen{
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen i_assert(service->master_status.available_count > 0);
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen service->master_status.available_count--;
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen master_status_update(service);
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen}
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainenstatic bool master_service_want_listener(struct master_service *service)
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen{
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (service->master_status.available_count > 0) {
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* more concurrent clients can still be added */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen return TRUE;
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen }
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (service->service_count_left == 1) {
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* after handling this client, the whole process will stop. */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen return FALSE;
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen }
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (service->avail_overflow_callback != NULL) {
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* overflow callback is set. it's possible that the current
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen existing client may be replaced by a new client, which needs
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen the listener to try to accept new connections. */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen return TRUE;
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen }
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* the listener isn't needed until the current client is disconnected */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen return FALSE;
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen}
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainenvoid master_service_client_connection_handled(struct master_service *service,
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen struct master_service_connection *conn)
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen{
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen if (!conn->accepted) {
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen if (close(conn->fd) < 0)
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen i_error("close(service connection) failed: %m");
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen master_service_client_connection_destroyed(service);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen } else if (conn->fifo) {
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen /* reading FIFOs stays open forever, don't count them
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen as real clients */
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen master_service_client_connection_destroyed(service);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen }
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (!master_service_want_listener(service)) {
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen i_assert(service->listeners != NULL);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen master_service_io_listeners_remove(service);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen if (service->service_count_left == 1) {
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen /* we're not going to accept any more connections after
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen this. go ahead and close the connection early. don't
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen do this before calling callback, because it may want
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen to access the listen_fd (e.g. to check socket
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen permissions). */
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen master_service_io_listeners_close(service);
d2c41d6587f973d3b215e035288a07619bc22c2aTimo Sirainen }
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen }
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen}
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainenvoid master_service_client_connection_callback(struct master_service *service,
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen struct master_service_connection *conn)
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen{
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen service->callback(conn);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen master_service_client_connection_handled(service, conn);
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen}
8ab32a83ca0ead65c5670f337ca3a4d7a0fd0ed1Timo Sirainen
db693bf6fcae96d834567f1782257517b7207655Timo Sirainenvoid master_service_client_connection_accept(struct master_service_connection *conn)
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen{
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen conn->accepted = TRUE;
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen}
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid master_service_client_connection_destroyed(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen /* we can listen again */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen master_service_io_listeners_add(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->total_available_count > 0);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen i_assert(service->service_count_left > 0);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen if (service->service_count_left == service->total_available_count) {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->total_available_count--;
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->service_count_left--;
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen } else {
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen if (service->service_count_left != UINT_MAX)
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->service_count_left--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen i_assert(service->master_status.available_count <
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen service->total_available_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->master_status.available_count++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen if (service->service_count_left == 0) {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen i_assert(service->master_status.available_count ==
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->total_available_count);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen master_service_stop(service);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen } else if ((service->io_status_error == NULL ||
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->listeners == NULL) &&
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->master_status.available_count ==
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen service->total_available_count) {
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen /* we've finished handling all clients, and
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen a) master has closed the connection
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen b) there are no listeners (std-client?) */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen master_service_stop(service);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen } else {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen master_status_update(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void master_service_set_login_state(struct master_service *service,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen enum master_login_state state)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&service->to_overflow_state);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen switch (state) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen case MASTER_LOGIN_STATE_NONFULL:
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service->call_avail_overflow = FALSE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (service->master_status.available_count > 0)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* some processes should now be able to handle new connections,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen although we can't. but there may be race conditions, so
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen make sure that we'll check again soon if the state has
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen changed to "full" without our knowledge. */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service->to_overflow_state =
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen timeout_add(MASTER_SERVICE_STATE_CHECK_MSECS,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_refresh_login_state,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen case MASTER_LOGIN_STATE_FULL:
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* make sure we're listening for more connections */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service->call_avail_overflow = TRUE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_io_listeners_add(service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_error("Invalid master login state: %d", state);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void master_service_refresh_login_state(struct master_service *service)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen int ret;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen ret = lseek(MASTER_LOGIN_NOTIFY_FD, 0, SEEK_CUR);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (ret < 0)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_error("lseek(login notify fd) failed: %m");
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen else
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_set_login_state(service, ret);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
3ba9a079592f46e94ce846e5aa80e4d479cd5e41Timo Sirainenvoid master_service_close_config_fd(struct master_service *service)
6a6e3c2538a08cc4880a8db7e0a9a3392122ea04Timo Sirainen{
a943ed0f901e312445fd393249b91932797bba79Josef 'Jeff' Sipek i_close_fd(&service->config_fd);
6a6e3c2538a08cc4880a8db7e0a9a3392122ea04Timo Sirainen}
6a6e3c2538a08cc4880a8db7e0a9a3392122ea04Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid master_service_deinit(struct master_service **_service)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct master_service *service = *_service;
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen unsigned int i;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *_service = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen master_service_haproxy_abort(service);
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen
442232f2d1cfdf28f3a18aa00a5c19246d321036Timo Sirainen master_service_io_listeners_remove(service);
5a6343181a5183b1ae1c39d40fc5a1deb3b840d9Timo Sirainen master_service_ssl_ctx_deinit(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen if (service->stats_client != NULL)
b63e20ea9bc84f1aa90a551f217d01385e070b73Timo Sirainen stats_client_deinit(&service->stats_client);
6a6e3c2538a08cc4880a8db7e0a9a3392122ea04Timo Sirainen master_service_close_config_fd(service);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&service->to_die);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&service->to_overflow_state);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&service->to_status);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&service->io_status_error);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek 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();
41789540204ce091b2c06629d9a31788082e5da8Timo Sirainen /* run atexit callbacks before destroying ioloop */
41789540204ce091b2c06629d9a31788082e5da8Timo Sirainen lib_atexit_run();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_destroy(&service->ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen for (i = 0; i < service->socket_count; i++)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen i_free(service->listeners[i].name);
6ed1e82824590b514201d9db84ba96bdfc832dd5Timo Sirainen i_free(service->listeners);
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen i_free(service->getopt_str);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(service->name);
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen i_free(service->config_path);
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{
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen struct master_service *service = l->service;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct master_service_connection conn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (service->master_status.available_count == 0) {
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen /* we are full. stop listening for now, unless overflow
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen callback destroys one of the existing connections */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (service->call_avail_overflow &&
a7bf18c0a462e4069675dec5038c474f8eb0a60dTimo Sirainen service->avail_overflow_callback != NULL)
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen service->avail_overflow_callback();
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (service->master_status.available_count == 0) {
442232f2d1cfdf28f3a18aa00a5c19246d321036Timo Sirainen master_service_io_listeners_remove(service);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen return;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&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) {
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen struct stat st;
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen int orig_errno = errno;
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn.fd == -1)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen if (errno == ENOTSOCK) {
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen /* it's not a socket. should be a fifo. */
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen } else if (errno == EINVAL &&
56ba5a9b62e3ce527e898a8fe3b1a015ab30ed54Timo Sirainen (fstat(l->fd, &st) == 0 && S_ISFIFO(st.st_mode))) {
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen /* BSDI fails accept(fifo) with EINVAL. */
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen } else {
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen errno = orig_errno;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("net_accept() failed: %m");
5ff22d69989a3ccc2d947164e47996f720d493d8Timo Sirainen /* try again later after one of the existing
5ff22d69989a3ccc2d947164e47996f720d493d8Timo Sirainen connections has died */
5ff22d69989a3ccc2d947164e47996f720d493d8Timo Sirainen master_service_io_listeners_remove(service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen /* use the "listener" as the connection fd and stop the
835ba470fb6a73b74e258e12678236106d0df09eTimo Sirainen listener. */
89237470342ea6d4bbdf4cff9764037cfb3f6f45Timo Sirainen conn.fd = l->fd;
e3540e734a79fd4f971652925079c2e26a4b5524Timo Sirainen conn.listen_fd = l->fd;
89237470342ea6d4bbdf4cff9764037cfb3f6f45Timo Sirainen conn.fifo = TRUE;
89237470342ea6d4bbdf4cff9764037cfb3f6f45Timo Sirainen
89237470342ea6d4bbdf4cff9764037cfb3f6f45Timo Sirainen io_remove(&l->io);
89237470342ea6d4bbdf4cff9764037cfb3f6f45Timo Sirainen l->fd = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen conn.ssl = l->ssl;
13f4d4d4a69d7dff2f71363d189d048abb04b6c6Timo Sirainen conn.name = master_service_get_socket_name(service, conn.listen_fd);
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch (void)net_getsockname(conn.fd, &conn.local_ip, &conn.local_port);
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch conn.real_remote_ip = conn.remote_ip;
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch conn.real_remote_port = conn.remote_port;
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch conn.real_local_ip = conn.local_ip;
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch conn.real_local_port = conn.local_port;
72f21884c0bb9bb26edad63623427ac2120901eaStephan Bosch
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainen net_set_nonblock(conn.fd, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
21e6b4fd844fd074583b17f09e1f27b9835ee238Timo Sirainen master_service_client_connection_created(service);
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen if (l->haproxy)
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen master_service_haproxy_new(service, &conn);
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen else
8761992b5aa05862e7ec3a460cdc17af41a4a0f5Timo Sirainen master_service_client_connection_callback(service, &conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenvoid master_service_io_listeners_add(struct master_service *service)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen unsigned int i;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
baca06331782e2752734199486e51a26d7c93d75Timo Sirainen if (service->stopping)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen return;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen for (i = 0; i < service->socket_count; i++) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen struct master_service_listener *l = &service->listeners[i];
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
04a6e51325d52a8f6046389406b2f606159a61e3Timo Sirainen if (l->io == NULL && l->fd != -1 && !l->closed) {
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
442232f2d1cfdf28f3a18aa00a5c19246d321036Timo Sirainenvoid master_service_io_listeners_remove(struct master_service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen for (i = 0; i < service->socket_count; i++) {
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&service->listeners[i].io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainenvoid master_service_ssl_io_listeners_remove(struct master_service *service)
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen{
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen unsigned int i;
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen for (i = 0; i < service->socket_count; i++) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (service->listeners[i].io != NULL &&
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->listeners[i].ssl)
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen io_remove(&service->listeners[i].io);
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen }
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen}
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainenstatic void master_service_io_listeners_close(struct master_service *service)
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen{
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen unsigned int i;
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen /* close via listeners. some fds might be pipes that are
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen currently handled as clients. we don't want to close them. */
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen for (i = 0; i < service->socket_count; i++) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (service->listeners[i].fd != -1) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen if (close(service->listeners[i].fd) < 0) {
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen i_error("close(listener %d) failed: %m",
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->listeners[i].fd);
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen }
71056e0f5e1f68cb9ac002a7827eb98435c40d62Timo Sirainen service->listeners[i].fd = -1;
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen }
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen }
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen}
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo 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
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainenstatic void
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainenmaster_status_send(struct master_service *service, bool important_update)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ssize_t ret;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&service->to_status);
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen ret = write(MASTER_STATUS_FD, &service->master_status,
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen sizeof(service->master_status));
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen if (ret == sizeof(service->master_status)) {
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen /* success */
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&service->io_status_write);
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->last_sent_status_time = ioloop_time;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->last_sent_status_avail_count =
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->master_status.available_count;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->initial_status_sent = TRUE;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen } else if (ret >= 0) {
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen /* shouldn't happen? */
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen i_error("write(master_status_fd) returned %d", (int)ret);
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->master_status.pid = 0;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen } else if (errno != EAGAIN) {
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen /* failure */
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen if (errno != EPIPE)
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen i_error("write(master_status_fd) failed: %m");
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->master_status.pid = 0;
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen } else if (important_update) {
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen /* reader is busy, but it's important to get this notification
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen through. send it when possible. */
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen if (service->io_status_write == NULL) {
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen service->io_status_write =
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen io_add(MASTER_STATUS_FD, IO_WRITE,
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen master_status_update, service);
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen }
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen }
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen}
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainenvoid master_status_update(struct master_service *service)
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen{
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen bool important_update;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen if ((service->flags & MASTER_SERVICE_FLAG_UPDATE_PROCTITLE) != 0 &&
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen service->set != NULL && service->set->verbose_proctitle) T_BEGIN {
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen unsigned int used_count = service->total_available_count -
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen service->master_status.available_count;
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen process_title_set(t_strdup_printf("[%u connections]",
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen used_count));
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen } T_END;
e2bdca8201e4aa1cd31332ffbdd4c6eef9151d5eTimo Sirainen
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen important_update = master_status_update_is_important(service);
a7bf18c0a462e4069675dec5038c474f8eb0a60dTimo Sirainen if (service->master_status.pid == 0 ||
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen service->master_status.available_count ==
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen service->last_sent_status_avail_count) {
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen /* a) closed, b) updating to same state */
d90a924480a061683786e459a2e1c1d0b6e4f1e4Josef 'Jeff' Sipek timeout_remove(&service->to_status);
4afd5b65670e52e1d513e707c96d626ab1856e03Josef 'Jeff' Sipek io_remove(&service->io_status_write);
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen return;
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen }
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen if (ioloop_time == service->last_sent_status_time &&
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen !important_update) {
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen /* don't spam master */
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen if (service->to_status != NULL)
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen timeout_reset(service->to_status);
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen else {
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen service->to_status =
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen timeout_add(1000, master_status_update,
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen service);
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen }
a7bf18c0a462e4069675dec5038c474f8eb0a60dTimo Sirainen if (service->io_status_write != NULL)
a7bf18c0a462e4069675dec5038c474f8eb0a60dTimo Sirainen io_remove(&service->io_status_write);
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen return;
2037c54ef0239bf7814badab08fc15f945f560fbTimo Sirainen }
b17d7bbd284df42e6aeb74f8de0f73ee07cfccb6Timo Sirainen master_status_send(service, important_update);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainenbool version_string_verify(const char *line, const char *service_name,
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen unsigned major_version)
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen{
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen unsigned int minor_version;
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen return version_string_verify_full(line, service_name,
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen major_version, &minor_version);
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen}
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainenbool version_string_verify_full(const char *line, const char *service_name,
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen unsigned major_version,
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen unsigned int *minor_version_r)
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t service_name_len = strlen(service_name);
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen bool ret;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (strncmp(line, "VERSION\t", 8) != 0)
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen return FALSE;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen line += 8;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen if (strncmp(line, service_name, service_name_len) != 0 ||
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen line[service_name_len] != '\t')
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen return FALSE;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen line += service_name_len + 1;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen T_BEGIN {
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen const char *p = strchr(line, '\t');
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen if (p == NULL)
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen ret = FALSE;
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen else {
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen ret = str_uint_equals(t_strdup_until(line, p),
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen major_version);
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen if (str_to_uint(p+1, minor_version_r) < 0)
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen ret = FALSE;
6303f32ad4af9cb08794561e6324df1c6c5fb637Timo Sirainen }
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen } T_END;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen return ret;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen}
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi
754896551f0422cda5d78500b26700eec5343c5bAki Tuomibool master_service_is_ssl_module_loaded(struct master_service *service)
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi{
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi /* if this is TRUE, then ssl module is loaded by init */
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi return service->want_ssl_settings;
754896551f0422cda5d78500b26700eec5343c5bAki Tuomi}