main.c revision 52bc5d390f066c7cced1e20311ffe2f7d19638dc
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "common.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "ioloop.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "lib-signals.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "fd-close-on-exec.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "array.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "write-full.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "env-util.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "hostpid.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "restrict-process-size.h"
292cbb3fbe41bb7ee09b67c3ec59ab7c7ba5220eStephen Gallagher#include "master-service.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "master-service-settings.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "askpass.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "capabilities.h"
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher#include "service.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "service-listen.h"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include "service-monitor.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include "service-log.h"
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#include <stdio.h>
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#include <stdlib.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#include <unistd.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#include <fcntl.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#include <sys/stat.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#include <pwd.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#include <grp.h>
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#define MASTER_SERVICE_NAME "master"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#define FATAL_FILENAME "master-fatal.lastlog"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#define MASTER_PID_FILE_NAME "master.pid"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstruct master_service *master_service;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagheruid_t master_uid;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallaghergid_t master_gid;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherbool auth_success_written;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherbool core_dumps_disabled;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherchar ssl_manual_key_password[100];
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint null_fd;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstruct service_list *services;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic char *pidfile_path;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic fatal_failure_callback_t *orig_fatal_callback;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic failure_callback_t *orig_error_callback;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic const char *child_process_env[3]; /* @UNSAFE */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic const struct setting_parser_info *set_roots[] = {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan &master_setting_parser_info,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan NULL
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher};
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallaghervoid process_exec(const char *cmd, const char *extra_args[])
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char *executable, *p, **argv;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher argv = t_strsplit(cmd, " ");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan executable = argv[0];
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (extra_args != NULL) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher unsigned int count1, count2;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char **new_argv;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* @UNSAFE */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan count1 = str_array_length(argv);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan count2 = str_array_length(extra_args);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan new_argv = t_new(const char *, count1 + count2 + 1);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher memcpy(new_argv, argv, sizeof(const char *) * count1);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan memcpy(new_argv + count1, extra_args,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan sizeof(const char *) * count2);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan argv = new_argv;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* hide the path, it's ugly */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan p = strrchr(argv[0], '/');
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (p != NULL) argv[0] = p+1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* prefix with dovecot/ */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher argv[0] = t_strconcat(PACKAGE"/", argv[0], NULL);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)execv(executable, (char **)argv);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal_status(errno == ENOMEM ? FATAL_OUTOFMEM : FATAL_EXEC,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "execv(%s) failed: %m", executable);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint get_uidgid(const char *user, uid_t *uid_r, gid_t *gid_r,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char **error_r)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct passwd *pw;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (*user == '\0') {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan *uid_r = (uid_t)-1;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if ((pw = getpwnam(user)) == NULL) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher *error_r = t_strdup_printf("User doesn't exist: %s", user);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher *uid_r = pw->pw_uid;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan *gid_r = pw->pw_gid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanint get_gid(const char *group, gid_t *gid_r, const char **error_r)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher struct group *gr;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (*group == '\0') {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher *gid_r = (gid_t)-1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if ((gr = getgrnam(group)) == NULL) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher *error_r = t_strdup_printf("Group doesn't exist: %s", group);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return -1;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher *gid_r = gr->gr_gid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void ATTR_NORETURN ATTR_FORMAT(3, 0)
292cbb3fbe41bb7ee09b67c3ec59ab7c7ba5220eStephen Gallaghermaster_fatal_callback(enum log_type type, int status,
3a8abe04137d028b8ebd1cb33152aefa55893efbStephen Gallagher const char *format, va_list args)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char *path, *str;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan va_list args2;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan int fd;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* if we already forked a child process, this isn't fatal for the
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan main process and there's no need to write the fatal file. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (getpid() == strtol(my_pid, NULL, 10)) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher /* write the error message to a file (we're chdired to
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher base dir) */
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher path = t_strconcat(FATAL_FILENAME, NULL);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (fd != -1) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher VA_COPY(args2, args);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher str = t_strdup_vprintf(format, args2);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher write_full(fd, str, strlen(str));
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher (void)close(fd);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan orig_fatal_callback(type, status, format, args);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan abort(); /* just to silence the noreturn attribute warnings */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void ATTR_NORETURN
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstartup_fatal_handler(enum log_type type, int status,
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan const char *fmt, va_list args)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher va_list args2;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan VA_COPY(args2, args);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fprintf(stderr, "Fatal: %s\n", t_strdup_vprintf(fmt, args2));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan orig_fatal_callback(type, status, fmt, args);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher abort();
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstartup_error_handler(enum log_type type, const char *fmt, va_list args)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher va_list args2;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher VA_COPY(args2, args);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fprintf(stderr, "Error: %s\n", t_strdup_vprintf(fmt, args2));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan orig_error_callback(type, fmt, args);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void fatal_log_check(const struct master_settings *set)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *path;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan char buf[1024];
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ssize_t ret;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher int fd;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan path = t_strconcat(set->base_dir, "/"FATAL_FILENAME, NULL);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fd = open(path, O_RDONLY);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (fd == -1)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = read(fd, buf, sizeof(buf));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ret < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_error("read(%s) failed: %m", path);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher else {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher buf[ret] = '\0';
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fprintf(stderr, "Last died with error (see error log for more "
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "information): %s\n", buf);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher close(fd);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (unlink(path) < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_error("unlink(%s) failed: %m", path);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic bool
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanservices_has_name(const struct master_settings *set, const char *name)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher struct service_settings *const *services;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher unsigned int i, count;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan services = array_get(&set->services, &count);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan for (i = 0; i < count; i++) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (strcmp(services[i]->name, name) == 0)
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher return TRUE;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return FALSE;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic bool services_have_auth_destinations(const struct master_settings *set)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct service_settings *const *services;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan unsigned int i, count;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan services = array_get(&set->services, &count);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan for (i = 0; i < count; i++) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (strcmp(services[i]->type, "auth-source") == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (services_has_name(set, services[i]->auth_dest_service))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return TRUE;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return FALSE;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher}
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void auth_warning_print(const struct master_settings *set)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct stat st;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan auth_success_written = stat(AUTH_SUCCESS_PATH, &st) == 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!auth_success_written && !set->auth_debug &&
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan services_have_auth_destinations(set)) {
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher fprintf(stderr,
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher"If you have trouble with authentication failures,\n"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan"enable auth_debug setting. See http://wiki.dovecot.org/WhyDoesItNotWork\n"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher"This message goes away after the first successful login.\n");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic bool pid_file_read(const char *path, pid_t *pid_r)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan char buf[32];
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan int fd;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan ssize_t ret;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan bool found;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fd = open(path, O_RDONLY);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (fd == -1) {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (errno == ENOENT)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return FALSE;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i_fatal("open(%s) failed: %m", path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret = read(fd, buf, sizeof(buf));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (ret <= 0) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (ret == 0)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_error("Empty PID file in %s, overriding", path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan else
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("read(%s) failed: %m", path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan found = FALSE;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher } else {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (buf[ret-1] == '\n')
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ret--;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan buf[ret] = '\0';
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan *pid_r = atoi(buf);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan found = !(*pid_r == getpid() ||
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (kill(*pid_r, 0) < 0 && errno == ESRCH));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)close(fd);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return found;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void pid_file_check_running(const char *path)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan pid_t pid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!pid_file_read(path, &pid))
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("Dovecot is already running with PID %s "
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "(read from %s)", dec2str(pid), path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void send_master_signal(int signo)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan pid_t pid;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!pid_file_read(pidfile_path, &pid)) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_fatal("Dovecot is not running (read from %s)", pidfile_path);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher return;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (kill(pid, signo) < 0)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_fatal("kill(%s, %d) failed: %m", dec2str(pid), signo);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan exit(0);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void create_pid_file(const char *path)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *pid;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan int fd;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan pid = t_strconcat(dec2str(getpid()), "\n", NULL);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (fd == -1)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("open(%s) failed: %m", path);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (write_full(fd, pid, strlen(pid)) < 0)
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_fatal("write() failed in %s: %m", path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)close(fd);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void
056302a92862fda16351d7192600746746f38e5dStephen Gallaghersig_settings_reload(const siginfo_t *si ATTR_UNUSED,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan void *context ATTR_UNUSED)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct master_service_settings_input input;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const struct master_settings *set;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher void **sets;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct service_list *new_services;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *error;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_warning("SIGHUP received - reloading configuration");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* see if hostname changed */
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan hostpid_init();
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan memset(&input, 0, sizeof(input));
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher input.roots = set_roots;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher input.module = MASTER_SERVICE_NAME;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan input.config_path = services_get_config_socket_path(services);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (master_service_settings_read(master_service, &input, &error) < 0) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_error("Error reading configuration: %s", error);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan sets = master_service_settings_get_others(master_service);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher set = sets[0];
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (services_create(set, child_process_env,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan &new_services, &error) < 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* new configuration is invalid, keep the old */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_error("Config reload failed: %s", error);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan return;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan new_services->config->config_file_path =
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher p_strdup(new_services->pool,
056302a92862fda16351d7192600746746f38e5dStephen Gallagher services->config->config_file_path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* switch to new configuration. */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)services_listen_using(new_services, services);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan services_destroy(services);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher services = new_services;
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher services_monitor_start(services);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void
056302a92862fda16351d7192600746746f38e5dStephen Gallaghersig_log_reopen(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan service_signal(services->log, SIGUSR1);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan master_service_init_log(master_service, "master: ");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_set_fatal_handler(master_fatal_callback);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivansig_reap_children(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher services_monitor_reap_children();
056302a92862fda16351d7192600746746f38e5dStephen Gallagher}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher si->si_signo, dec2str(si->si_pid),
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher dec2str(si->si_uid),
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher lib_signal_code_to_str(si->si_signo, si->si_code));
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan master_service_stop(master_service);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void main_log_startup(void)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#define STARTUP_STRING PACKAGE_NAME" v"VERSION" starting up"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher rlim_t core_limit;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan core_dumps_disabled = restrict_get_core_limit(&core_limit) == 0 &&
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher core_limit == 0;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (core_dumps_disabled)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i_info(STARTUP_STRING" (core dumps disabled)");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan else
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher i_info(STARTUP_STRING);
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher}
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void main_init(bool log_error)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher{
056302a92862fda16351d7192600746746f38e5dStephen Gallagher drop_capabilities();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan /* deny file access from everyone else except owner */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan (void)umask(0077);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (log_error) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan fprintf(stderr, "Writing to error logs and killing myself..\n");
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan i_debug("This is Dovecot's debug log");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_info("This is Dovecot's info log");
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i_warning("This is Dovecot's warning log");
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_error("This is Dovecot's error log");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("This is Dovecot's fatal log");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan main_log_startup();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan lib_signals_init();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan lib_signals_ignore(SIGPIPE, TRUE);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lib_signals_ignore(SIGALRM, FALSE);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lib_signals_set_handler(SIGHUP, TRUE, sig_settings_reload, NULL);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lib_signals_set_handler(SIGUSR1, TRUE, sig_log_reopen, NULL);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan lib_signals_set_handler(SIGCHLD, TRUE, sig_reap_children, NULL);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan create_pid_file(pidfile_path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan services_monitor_start(services);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void main_deinit(void)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (unlink(pidfile_path) < 0)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i_error("unlink(%s) failed: %m", pidfile_path);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_free(pidfile_path);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan services_destroy(services);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan service_pids_deinit();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic const char *get_full_config_path(struct service_list *list)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher const char *path;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher char cwd[PATH_MAX];
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan path = master_service_get_config_path(master_service);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (*path == '/')
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return path;
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (getcwd(cwd, sizeof(cwd)) == NULL)
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan i_fatal("getcwd() failed: %m");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return p_strconcat(list->pool, cwd, "/", path, NULL);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagherstatic void master_time_moved(time_t old_time, time_t new_time)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher{
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher unsigned long secs;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (new_time >= old_time)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher return;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher /* time moved backwards. disable launching new service processes
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher until */
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher secs = old_time - new_time + 1;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (secs > SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher secs = SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher services_throttle_time_sensitives(services, secs);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_warning("Time moved backwards by %lu seconds, "
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "waiting for %lu secs until new services are launched again.",
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher (unsigned long)(old_time - new_time), secs);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher}
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagherstatic void daemonize(void)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher{
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher pid_t pid;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher pid = fork();
056302a92862fda16351d7192600746746f38e5dStephen Gallagher if (pid < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_fatal("fork() failed: %m");
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher if (pid != 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher _exit(0);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (setsid() < 0)
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher i_fatal("setsid() failed: %m");
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* update my_pid */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan hostpid_init();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivanstatic void print_help(void)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan{
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher fprintf(stderr,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher"Usage: dovecot [-F] [-c <config file>] [-p] [-n] [-a]\n"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan" [-cb <config binary path>] [--help] [--version]\n"
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan" [--build-options] [--log-error] [reload] [stop]\n");
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan}
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivanstatic void print_build_options(void)
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan printf("Build options:"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifdef IOLOOP_EPOLL
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " ioloop=epoll"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#ifdef IOLOOP_KQUEUE
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " ioloop=kqueue"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef IOLOOP_POLL
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " ioloop=poll"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef IOLOOP_SELECT
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher " ioloop=select"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef IOLOOP_NOTIFY_DNOTIFY
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan " notify=dnotify"
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher#endif
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher#ifdef IOLOOP_NOTIFY_INOTIFY
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher " notify=inotify"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifdef IOLOOP_NOTIFY_KQUEUE
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " notify=kqueue"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#ifdef HAVE_IPV6
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " ipv6"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef HAVE_GNUTLS
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " gnutls"
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef HAVE_OPENSSL
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher " openssl"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef SQL_DRIVER_PLUGINS
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "\nSQL driver plugins:"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#else
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher "\nSQL drivers:"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef BUILD_MYSQL
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan " mysql"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef BUILD_PGSQL
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " postgresql"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#ifdef BUILD_SQLITE
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " sqlite"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher "\nPassdb:"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef PASSDB_BSDAUTH
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " bsdauth"
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef PASSDB_CHECKPASSWORD
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher " checkpassword"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef PASSDB_LDAP
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher " ldap"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef PASSDB_PAM
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " pam"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher#ifdef PASSDB_PASSWD
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher " passwd"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef PASSDB_PASSWD_FILE
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " passwd-file"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef PASSDB_SHADOW
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " shadow"
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#endif
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher#ifdef PASSDB_SQL
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher " sql"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef PASSDB_VPOPMAIL
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " vpopmail"
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan "\nUserdb:"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifdef USERDB_CHECKPASSWORD
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " checkpassword"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifdef USERDB_LDAP
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher " ldap"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifndef BUILTIN_LDAP
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher "(plugin)"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher#endif
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher#ifdef USERDB_PASSWD
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan " passwd"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#ifdef USERDB_PREFETCH
056302a92862fda16351d7192600746746f38e5dStephen Gallagher " prefetch"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#ifdef USERDB_PASSWD_FILE
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " passwd-file"
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher#endif
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#ifdef USERDB_SQL
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan " sql"
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef USERDB_STATIC
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher " static"
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef USERDB_VPOPMAIL
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher " vpopmail"
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#endif
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan "\n");
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan}
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagherint main(int argc, char *argv[])
056302a92862fda16351d7192600746746f38e5dStephen Gallagher{
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan struct master_settings *set;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan unsigned int child_process_env_idx = 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char *getopt_str, *error, *env_tz, *doveconf_arg = NULL;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher failure_callback_t *orig_info_callback, *orig_debug_callback;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher void **sets;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan bool foreground = FALSE, ask_key_pass = FALSE, log_error = FALSE;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan int c, send_signal = 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan#ifdef DEBUG
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher if (getenv("GDB") == NULL)
c938f4ba417328fe62eded0806b2d9ca053f34a5Stephen Gallagher fd_debug_verify_leaks(3, 1024);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan else
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher child_process_env[child_process_env_idx++] = "GDB=1";
056302a92862fda16351d7192600746746f38e5dStephen Gallagher#endif
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan master_service = master_service_init(MASTER_SERVICE_NAME,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan MASTER_SERVICE_FLAG_STANDALONE |
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher argc, argv);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_set_failure_prefix("");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan io_loop_set_time_moved_callback(current_ioloop, master_time_moved);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher master_uid = geteuid();
056302a92862fda16351d7192600746746f38e5dStephen Gallagher master_gid = getegid();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan getopt_str = t_strconcat("Fanp-", master_service_getopt_string(), NULL);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan while ((c = getopt(argc, argv, getopt_str)) > 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (c == '-')
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher switch (c) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher case 'F':
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher foreground = TRUE;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher case 'a':
056302a92862fda16351d7192600746746f38e5dStephen Gallagher doveconf_arg = "-a";
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case 'n':
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan doveconf_arg = "-n";
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan break;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan case 'p':
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan /* Ask SSL private key password */
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan ask_key_pass = TRUE;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher break;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher default:
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (!master_service_parse_option(master_service,
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher c, optarg)) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher print_help();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan exit(FATAL_DEFAULT);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher break;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (doveconf_arg != NULL) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan const char **args;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher args = t_new(const char *, 5);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher args[0] = DOVECOT_CONFIG_BIN_PATH;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher args[1] = doveconf_arg;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher args[2] = "-c";
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher args[3] = master_service_get_config_path(master_service);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan args[4] = NULL;
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher execv(args[0], (char **)args);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher i_fatal("execv(%s) failed: %m", args[0]);
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher }
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
52261fe16203dec6e6f69177c6d0a810b47d073fStephen Gallagher while (optind < argc) {
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (strcmp(argv[optind], "--version") == 0) {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher printf("%s\n", VERSION);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else if (strcmp(argv[optind], "--build-options") == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan print_build_options();
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher return 0;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher } else if (strcmp(argv[optind], "--log-error") == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan log_error = TRUE;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan foreground = TRUE;
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } else if (strcmp(argv[optind], "--help") == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan print_help();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan return 0;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher } else if (strcmp(argv[optind], "reload") == 0) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher send_signal = SIGHUP;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher } else if (strcmp(argv[optind], "stop") == 0) {
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan send_signal = SIGTERM;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher } else {
056302a92862fda16351d7192600746746f38e5dStephen Gallagher print_help();
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("Unknown argument: %s", argv[optind]);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan }
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan optind++;
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan do {
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan null_fd = open("/dev/null", O_WRONLY);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (null_fd == -1)
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher i_fatal("Can't open /dev/null: %m");
056302a92862fda16351d7192600746746f38e5dStephen Gallagher fd_close_on_exec(null_fd, TRUE);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan } while (null_fd <= STDERR_FILENO);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher if (master_service_settings_read_simple(master_service, set_roots,
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher &error) < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("Error reading configuration: %s", error);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan sets = master_service_settings_get_others(master_service);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher set = sets[0];
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher if (ask_key_pass) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher askpass("Give the password for SSL keys: ",
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher ssl_manual_key_password,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan sizeof(ssl_manual_key_password));
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher }
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (dup2(null_fd, STDIN_FILENO) < 0 ||
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan dup2(null_fd, STDOUT_FILENO) < 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_fatal("dup2(null_fd) failed: %m");
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher pidfile_path =
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_strconcat(set->base_dir, "/"MASTER_PID_FILE_NAME, NULL);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan if (send_signal != 0)
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan send_master_signal(send_signal);
cbe7c54c2caf718bdea7ca6660ba8193d759d2d5Stephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher master_service_init_log(master_service, "master: ");
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback,
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan &orig_info_callback, &orig_debug_callback);
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan i_set_fatal_handler(startup_fatal_handler);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan i_set_error_handler(startup_error_handler);
f9fdc87c80f2744780c6a0f2bf5b1b57bcbb095aYuri Chornoivan
bde69429374859acff41273c0771d2b5f5c199b1Yuri Chornoivan if (!log_error) {
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher pid_file_check_running(pidfile_path);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher master_settings_do_fixes(set);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher fatal_log_check(set);
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher auth_warning_print(set);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher }
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher /* save TZ environment. AIX depends on it to get the timezone
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher correctly. */
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher env_tz = getenv("TZ");
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher /* clean up the environment of everything */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher env_clean();
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher /* put back the TZ */
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (env_tz != NULL) {
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher const char *env = t_strconcat("TZ=", env_tz, NULL);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher env_put(env);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher child_process_env[child_process_env_idx++] = env;
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher }
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_assert(child_process_env_idx <
056302a92862fda16351d7192600746746f38e5dStephen Gallagher sizeof(child_process_env) / sizeof(child_process_env[0]));
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher child_process_env[child_process_env_idx++] = NULL;
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher /* create service structures from settings. if there are any errors in
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher service configuration we'll catch it here. */
056302a92862fda16351d7192600746746f38e5dStephen Gallagher service_pids_init();
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (services_create(set, child_process_env, &services, &error) < 0)
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_fatal("%s", error);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher services->config->config_file_path = get_full_config_path(services);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (!log_error) {
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher /* if any listening fails, fail completely */
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (services_listen(services) <= 0)
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_fatal("Failed to start listeners");
056302a92862fda16351d7192600746746f38e5dStephen Gallagher
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (!foreground)
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher daemonize();
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher if (chdir(set->base_dir) < 0)
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_fatal("chdir(%s) failed: %m", set->base_dir);
056302a92862fda16351d7192600746746f38e5dStephen Gallagher }
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
b355dcb54194f498921743ca33304eac35d89718Stephen Gallagher i_set_fatal_handler(master_fatal_callback);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher i_set_error_handler(orig_error_callback);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher
056302a92862fda16351d7192600746746f38e5dStephen Gallagher main_init(log_error);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher master_service_run(master_service, NULL);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher main_deinit();
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher master_service_deinit(&master_service);
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher return 0;
056302a92862fda16351d7192600746746f38e5dStephen Gallagher}
9643e7da1a54a9edb2360ab8f855664a8b4397caStephen Gallagher