main.c revision b849b2f39b86dd1e23bd13b597dffe33ebd94185
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2005-2011 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib-signals.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "fd-close-on-exec.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "env-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen#include "abspath.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ipwd.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "execv-const.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mountpoint-list.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "restrict-process-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-instance.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "master-service-settings.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "askpass.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "capabilities.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "service.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "service-anvil.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "service-listen.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "service-monitor.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "service-process.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "service-log.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include "dovecot-version.h"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include <stdio.h>
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include <stdlib.h>
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include <unistd.h>
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include <fcntl.h>
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#include <sys/stat.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MASTER_SERVICE_NAME "master"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#define FATAL_FILENAME "master-fatal.lastlog"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#define MASTER_PID_FILE_NAME "master.pid"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenuid_t master_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainengid_t master_gid;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenbool core_dumps_disabled;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenconst char *ssl_manual_key_password;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint null_fd, global_master_dead_pipe_fd[2];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct service_list *services;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic char *pidfile_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct master_instance_list *instances;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic struct timeout *to_instance;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic failure_callback_t *orig_fatal_callback;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic failure_callback_t *orig_error_callback;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic const struct setting_parser_info *set_roots[] = {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen &master_setting_parser_info,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen NULL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen};
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid process_exec(const char *cmd, const char *extra_args[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *executable, *p, **argv;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen argv = t_strsplit(cmd, " ");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen executable = argv[0];
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (extra_args != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int count1, count2;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **new_argv;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* @UNSAFE */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen count1 = str_array_length(argv);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen count2 = str_array_length(extra_args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen new_argv = t_new(const char *, count1 + count2 + 1);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen memcpy(new_argv, argv, sizeof(const char *) * count1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(new_argv + count1, extra_args,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sizeof(const char *) * count2);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen argv = new_argv;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* hide the path, it's ugly */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen p = strrchr(argv[0], '/');
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (p != NULL) argv[0] = p+1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* prefix with dovecot/ */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen argv[0] = t_strdup_printf("%s/%s", services->set->instance_name,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen argv[0]);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (strncmp(argv[0], PACKAGE, strlen(PACKAGE)) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen argv[0] = t_strconcat(PACKAGE"-", argv[0], NULL);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen (void)execv_const(executable, argv);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint get_uidgid(const char *user, uid_t *uid_r, gid_t *gid_r,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char **error_r)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct passwd pw;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*user == '\0') {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *uid_r = (uid_t)-1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *gid_r = (gid_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen switch (i_getpwnam(user, &pw)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case -1:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen case 0:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *error_r = t_strdup_printf("User doesn't exist: %s", user);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen default:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *uid_r = pw.pw_uid;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *gid_r = pw.pw_gid;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenint get_gid(const char *group, gid_t *gid_r, const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct group gr;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (*group == '\0') {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *gid_r = (gid_t)-1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen switch (i_getgrnam(group, &gr)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen case -1:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", group);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen case 0:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *error_r = t_strdup_printf("Group doesn't exist: %s", group);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return -1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen default:
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *gid_r = gr.gr_gid;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void ATTR_NORETURN ATTR_FORMAT(2, 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenmaster_fatal_callback(const struct failure_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *format, va_list args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *path, *str;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen va_list args2;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen int fd;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* if we already forked a child process, this isn't fatal for the
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen main process and there's no need to write the fatal file. */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (getpid() == strtol(my_pid, NULL, 10)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* write the error message to a file (we're chdired to
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen base dir) */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen path = t_strconcat(FATAL_FILENAME, NULL);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (fd != -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen VA_COPY(args2, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = t_strdup_vprintf(format, args2);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen write_full(fd, str, strlen(str));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen (void)close(fd);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen orig_fatal_callback(ctx, format, args);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen abort(); /* just to silence the noreturn attribute warnings */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void ATTR_NORETURN
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstartup_fatal_handler(const struct failure_context *ctx,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *fmt, va_list args)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen va_list args2;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen VA_COPY(args2, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_strdup_vprintf(fmt, args2));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen orig_fatal_callback(ctx, fmt, args);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen abort();
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstartup_error_handler(const struct failure_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *fmt, va_list args)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen va_list args2;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen VA_COPY(args2, args);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen t_strdup_vprintf(fmt, args2));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen orig_error_callback(ctx, fmt, args);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void fatal_log_check(const struct master_settings *set)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *path;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen char buf[1024];
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ssize_t ret;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen int fd;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen path = t_strconcat(set->base_dir, "/"FATAL_FILENAME, NULL);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen fd = open(path, O_RDONLY);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (fd == -1)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ret = read(fd, buf, sizeof(buf));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ret < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("read(%s) failed: %m", path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen else {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen buf[ret] = '\0';
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen fprintf(stderr, "Last died with error (see error log for more "
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "information): %s\n", buf);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen close(fd);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (unlink(path) < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("unlink(%s) failed: %m", path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic bool pid_file_read(const char *path, pid_t *pid_r)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char buf[32];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ssize_t ret;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen bool found;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = open(path, O_RDONLY);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (fd == -1) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (errno == ENOENT)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return FALSE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("open(%s) failed: %m", path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ret = read(fd, buf, sizeof(buf));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ret <= 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ret == 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("Empty PID file in %s, overriding", path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen else
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("read(%s) failed: %m", path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen found = FALSE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen } else {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (buf[ret-1] == '\n')
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ret--;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen buf[ret] = '\0';
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen *pid_r = atoi(buf);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen found = !(*pid_r == getpid() ||
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen (kill(*pid_r, 0) < 0 && errno == ESRCH));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)close(fd);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return found;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void pid_file_check_running(const char *path)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen pid_t pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (!pid_file_read(path, &pid))
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("Dovecot is already running with PID %s "
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "(read from %s)", dec2str(pid), path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void create_pid_file(const char *path)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *pid;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen int fd;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen pid = t_strconcat(dec2str(getpid()), "\n", NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (fd == -1)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("open(%s) failed: %m", path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (write_full(fd, pid, strlen(pid)) < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("write() failed in %s: %m", path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)close(fd);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void create_config_symlink(const struct master_settings *set)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *base_config_path;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen base_config_path = t_strconcat(set->base_dir, "/"PACKAGE".conf", NULL);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (unlink(base_config_path) < 0 && errno != ENOENT)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("unlink(%s) failed: %m", base_config_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (symlink(services->config->config_file_path, base_config_path) < 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("symlink(%s, %s) failed: %m",
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services->config->config_file_path, base_config_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void mountpoints_warn_missing(struct mountpoint_list *mountpoints)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mountpoint_list_iter *iter;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct mountpoint_list_rec *rec;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* warn about mountpoints that no longer exist */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen iter = mountpoint_list_iter_init(mountpoints);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen while ((rec = mountpoint_list_iter_next(iter)) != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (MOUNTPOINT_WRONGLY_NOT_MOUNTED(rec)) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_warning("%s is no longer mounted. "
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "If this is intentional, "
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "remove it with doveadm mount",
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rec->mount_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mountpoint_list_iter_deinit(&iter);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mountpoints_update(const struct master_settings *set)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mountpoint_list *mountpoints;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *perm_path, *state_path;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen perm_path = t_strconcat(PKG_STATEDIR"/"MOUNTPOINT_LIST_FNAME, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen state_path = t_strconcat(set->base_dir, "/"MOUNTPOINT_LIST_FNAME, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mountpoints = mountpoint_list_init(perm_path, state_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (mountpoint_list_add_missing(mountpoints, MOUNTPOINT_STATE_DEFAULT,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mountpoint_list_default_ignore_types) == 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mountpoints_warn_missing(mountpoints);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen (void)mountpoint_list_save(mountpoints);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen mountpoint_list_deinit(&mountpoints);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void instance_update_now(struct master_instance_list *list)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen int ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ret = master_instance_list_set_name(list, services->set->base_dir,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services->set->instance_name);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (ret == 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* duplicate instance names. allow without warning.. */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen master_instance_list_update(list, services->set->base_dir);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (to_instance != NULL)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen timeout_remove(&to_instance);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen to_instance = timeout_add((3600*12 + rand()%(60*30)) * 1000,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen instance_update_now, list);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void instance_update(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen instances = master_instance_list_init(MASTER_INSTANCE_PATH);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen instance_update_now(instances);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainensig_settings_reload(const siginfo_t *si ATTR_UNUSED,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen void *context ATTR_UNUSED)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct master_service_settings_input input;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct master_service_settings_output output;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const struct master_settings *set;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen void **sets;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct service_list *new_services;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct service *service;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *error;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_warning("SIGHUP received - reloading configuration");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* see if hostname changed */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen hostpid_init();
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (services->config->process_avail == 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* we can't reload config if there's no config process. */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (service_process_create(services->config) == NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("Can't reload configuration because "
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "we couldn't create a config process");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen memset(&input, 0, sizeof(input));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.roots = set_roots;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.module = MASTER_SERVICE_NAME;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.config_path = services_get_config_socket_path(services);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (master_service_settings_read(master_service, &input,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen &output, &error) < 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("Error reading configuration: %s", error);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen sets = master_service_settings_get_others(master_service);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen set = sets[0];
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (services_create(set, &new_services, &error) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* new configuration is invalid, keep the old */
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen i_error("Config reload failed: %s", error);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen new_services->config->config_file_path =
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen p_strdup(new_services->pool,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen services->config->config_file_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* switch to new configuration. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen services_monitor_stop(services, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (services_listen_using(new_services, services) < 0) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services_monitor_start(services);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* anvil never dies. it just gets moved to the new services list */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen service = service_lookup_type(services, SERVICE_TYPE_ANVIL);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (service != NULL) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen while (service->processes != NULL)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen service_process_destroy(service->processes);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen }
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services_destroy(services, FALSE);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services = new_services;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services_monitor_start(services);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainensig_log_reopen(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen service_signal(services->log, SIGUSR1);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen master_service_init_log(master_service, "master: ");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_set_fatal_handler(master_fatal_callback);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainensig_reap_children(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services_monitor_reap_children();
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen si->si_signo, dec2str(si->si_pid),
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen dec2str(si->si_uid),
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen master_service_stop(master_service);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct master_settings *master_settings_read(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct master_service_settings_input input;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen struct master_service_settings_output output;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *error;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(&input, 0, sizeof(input));
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.roots = set_roots;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.module = "master";
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen input.parse_full_config = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen input.preserve_environment = TRUE;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (master_service_settings_read(master_service, &input, &output,
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen &error) < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("Error reading configuration: %s", error);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return master_service_settings_get_others(master_service)[0];
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void master_set_import_environment(const struct master_settings *set)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen const char *const *envs, *key, *value;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen ARRAY_TYPE(const_string) keys;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (*set->import_environment == '\0')
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_array_init(&keys, 8);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen envs = t_strsplit_spaces(set->import_environment, " ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (; *envs != NULL; envs++) {
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen value = strchr(*envs, '=');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen key = *envs;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen key = t_strdup_until(*envs, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen env_put(*envs);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&keys, &key, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)array_append_space(&keys);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen value = t_strarray_join(array_idx(&keys, 0), " ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen env_put(t_strconcat(DOVECOT_PRESERVE_ENVS_ENV"=", value, NULL));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void main_log_startup(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#define STARTUP_STRING PACKAGE_NAME" v"DOVECOT_VERSION_FULL" starting up"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen rlim_t core_limit;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen core_dumps_disabled = restrict_get_core_limit(&core_limit) == 0 &&
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen core_limit == 0;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (core_dumps_disabled)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_info(STARTUP_STRING" (core dumps disabled)");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen else
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_info(STARTUP_STRING);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic void master_set_process_limit(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct service *const *servicep;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int process_limit = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rlim_t nproc;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we'll just count all the processes that can exist and set the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen process limit so that we won't reach it. it's usually higher than
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen needed, since we'd only need to set it high enough for each
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen separate UID not to reach the limit, but this is difficult to
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen guess: mail processes should probably be counted together for a
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen common vmail user (unless system users are being used), but
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen we can't really guess what the mail processes are. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach(&services->services, servicep)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen process_limit += (*servicep)->process_limit;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (restrict_get_process_limit(&nproc) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen process_limit > nproc)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen restrict_process_count(process_limit);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void main_init(const struct master_settings *set)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_set_process_limit();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen drop_capabilities();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* deny file access from everyone else except owner */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)umask(0077);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen main_log_startup();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_init();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_ignore(SIGPIPE, TRUE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_ignore(SIGALRM, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGHUP, LIBSIG_FLAGS_SAFE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sig_settings_reload, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGUSR1, LIBSIG_FLAGS_SAFE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sig_log_reopen, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGCHLD, LIBSIG_FLAGS_SAFE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sig_reap_children, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGINT, LIBSIG_FLAGS_SAFE, sig_die, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGTERM, LIBSIG_FLAGS_SAFE, sig_die, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen create_pid_file(pidfile_path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen create_config_symlink(set);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mountpoints_update(set);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen instance_update();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen services_monitor_start(services);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void global_dead_pipe_close(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (close(global_master_dead_pipe_fd[0]) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("close(global dead pipe) failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (close(global_master_dead_pipe_fd[1]) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("close(global dead pipe) failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen global_master_dead_pipe_fd[0] = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen global_master_dead_pipe_fd[1] = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void main_deinit(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen instance_update_now(instances);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen timeout_remove(&to_instance);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen master_instance_list_deinit(&instances);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* kill services and wait for them to die before unlinking pid file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen global_dead_pipe_close();
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen services_destroy(services, TRUE);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (unlink(pidfile_path) < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_error("unlink(%s) failed: %m", pidfile_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_free(pidfile_path);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen service_anvil_global_deinit();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen service_pids_deinit();
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainenstatic const char *get_full_config_path(struct service_list *list)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = master_service_get_config_path(master_service);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*path == '/')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return p_strdup(list->pool, t_abspath(path));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void master_time_moved(time_t old_time, time_t new_time)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned long secs;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (new_time >= old_time)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen return;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* time moved backwards. disable launching new service processes
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen until */
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen secs = old_time - new_time + 1;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen if (secs > SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen secs = SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen services_throttle_time_sensitives(services, secs);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_warning("Time moved backwards by %lu seconds, "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "waiting for %lu secs until new services are launched again.",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (unsigned long)(old_time - new_time), secs);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void daemonize(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pid_t pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen pid = fork();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pid < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("fork() failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pid != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen _exit(0);
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (setsid() < 0)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen i_fatal("setsid() failed: %m");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen /* update my_pid */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen hostpid_init();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void print_help(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fprintf(stderr,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen"Usage: dovecot [-F] [-c <config file>] [-p] [-n] [-a] [--help] [--version]\n"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen" [--build-options] [reload] [stop]\n");
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void print_build_options(void)
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen printf("Build options:"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef IOLOOP_EPOLL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " ioloop=epoll"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef IOLOOP_KQUEUE
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " ioloop=kqueue"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef IOLOOP_POLL
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen " ioloop=poll"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef IOLOOP_SELECT
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " ioloop=select"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef IOLOOP_NOTIFY_DNOTIFY
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " notify=dnotify"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef IOLOOP_NOTIFY_INOTIFY
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " notify=inotify"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef IOLOOP_NOTIFY_KQUEUE
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " notify=kqueue"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef HAVE_IPV6
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " ipv6"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef HAVE_GNUTLS
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " gnutls"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef HAVE_OPENSSL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " openssl"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " io_block_size=%u"
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen "\nMail storages: "MAIL_STORAGES"\n"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef SQL_DRIVER_PLUGINS
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "SQL driver plugins:"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#else
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "SQL drivers:"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef BUILD_MYSQL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " mysql"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef BUILD_PGSQL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " postgresql"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef BUILD_SQLITE
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " sqlite"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "\nPassdb:"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_BSDAUTH
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " bsdauth"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_CHECKPASSWORD
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " checkpassword"
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen#endif
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen#ifdef PASSDB_LDAP
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " ldap"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef PASSDB_PAM
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " pam"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_PASSWD
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " passwd"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_PASSWD_FILE
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " passwd-file"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_SHADOW
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " shadow"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_SQL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " sql"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef PASSDB_VPOPMAIL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " vpopmail"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "\nUserdb:"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef USERDB_CHECKPASSWORD
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " checkpassword"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USERDB_LDAP
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " ldap"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifndef BUILTIN_LDAP
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen "(plugin)"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef USERDB_NSS
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " nss"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef USERDB_PASSWD
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " passwd"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USERDB_PREFETCH
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " prefetch"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USERDB_PASSWD_FILE
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " passwd-file"
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#endif
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen#ifdef USERDB_SQL
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen " sql"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USERDB_STATIC
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " static"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef USERDB_VPOPMAIL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen " vpopmail"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "\n", IO_BLOCK_SIZE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainenint main(int argc, char *argv[])
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct master_settings *set;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *error, *doveconf_arg = NULL;
72cbf33ae81fde08384d30c779ff540752d9256cTimo Sirainen failure_callback_t *orig_info_callback, *orig_debug_callback;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen bool foreground = FALSE, ask_key_pass = FALSE;
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen bool doubleopts[argc];
int i, c;
#ifdef DEBUG
if (getenv("GDB") == NULL)
fd_debug_verify_leaks(3, 1024);
#endif
/* drop -- prefix from all --args. ugly, but the only way that it
works with standard getopt() in all OSes.. */
for (i = 1; i < argc; i++) {
if (strncmp(argv[i], "--", 2) == 0) {
if (argv[i][2] == '\0')
break;
argv[i] += 2;
doubleopts[i] = TRUE;
} else {
doubleopts[i] = FALSE;
}
}
master_service = master_service_init(MASTER_SERVICE_NAME,
MASTER_SERVICE_FLAG_STANDALONE |
MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR,
&argc, &argv, "+Fanp");
i_set_failure_prefix("");
io_loop_set_time_moved_callback(current_ioloop, master_time_moved);
master_uid = geteuid();
master_gid = getegid();
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'F':
foreground = TRUE;
break;
case 'a':
doveconf_arg = "-a";
break;
case 'n':
doveconf_arg = "-n";
break;
case 'p':
/* Ask SSL private key password */
ask_key_pass = TRUE;
break;
default:
if (!master_service_parse_option(master_service,
c, optarg)) {
print_help();
exit(FATAL_DEFAULT);
}
break;
}
}
if (doveconf_arg != NULL) {
const char **args;
args = t_new(const char *, 5);
args[0] = DOVECOT_CONFIG_BIN_PATH;
args[1] = doveconf_arg;
args[2] = "-c";
args[3] = master_service_get_config_path(master_service);
args[4] = NULL;
execv_const(args[0], args);
}
if (optind == argc) {
/* starting Dovecot */
} else if (!doubleopts[optind]) {
/* dovecot xx -> doveadm xx */
(void)execv(BINDIR"/doveadm", argv);
i_fatal("execv("BINDIR"/doveadm) failed: %m");
} else if (strcmp(argv[optind], "version") == 0) {
printf("%s\n", DOVECOT_VERSION_FULL);
return 0;
} else if (strcmp(argv[optind], "build-options") == 0) {
print_build_options();
return 0;
} else if (strcmp(argv[optind], "log-error") == 0) {
fprintf(stderr, "Writing to error logs and killing myself..\n");
argv[optind] = "log test";
(void)execv(BINDIR"/doveadm", argv);
i_fatal("execv("BINDIR"/doveadm) failed: %m");
} else if (strcmp(argv[optind], "help") == 0) {
print_help();
return 0;
} else {
print_help();
i_fatal("Unknown argument: --%s", argv[optind]);
}
do {
null_fd = open("/dev/null", O_WRONLY);
if (null_fd == -1)
i_fatal("Can't open /dev/null: %m");
fd_close_on_exec(null_fd, TRUE);
} while (null_fd <= STDERR_FILENO);
if (pipe(global_master_dead_pipe_fd) < 0)
i_fatal("pipe() failed: %m");
fd_close_on_exec(global_master_dead_pipe_fd[0], TRUE);
fd_close_on_exec(global_master_dead_pipe_fd[1], TRUE);
set = master_settings_read();
if (ask_key_pass) {
ssl_manual_key_password =
t_askpass("Give the password for SSL keys: ");
}
if (dup2(null_fd, STDIN_FILENO) < 0 ||
dup2(null_fd, STDOUT_FILENO) < 0)
i_fatal("dup2(null_fd) failed: %m");
pidfile_path =
i_strconcat(set->base_dir, "/"MASTER_PID_FILE_NAME, NULL);
master_service_init_log(master_service, "master: ");
i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback,
&orig_info_callback, &orig_debug_callback);
i_set_fatal_handler(startup_fatal_handler);
i_set_error_handler(startup_error_handler);
pid_file_check_running(pidfile_path);
master_settings_do_fixes(set);
fatal_log_check(set);
T_BEGIN {
master_set_import_environment(set);
} T_END;
master_service_env_clean();
/* create service structures from settings. if there are any errors in
service configuration we'll catch it here. */
service_pids_init();
service_anvil_global_init();
if (services_create(set, &services, &error) < 0)
i_fatal("%s", error);
services->config->config_file_path = get_full_config_path(services);
/* if any listening fails, fail completely */
if (services_listen(services) <= 0)
i_fatal("Failed to start listeners");
if (chdir(set->base_dir) < 0)
i_fatal("chdir(%s) failed: %m", set->base_dir);
if (strcmp(services->service_set->log_path, "/dev/stderr") != 0 &&
strcmp(services->service_set->info_log_path, "/dev/stderr") != 0 &&
strcmp(services->service_set->debug_log_path, "/dev/stderr") != 0) {
if (dup2(null_fd, STDERR_FILENO) < 0)
i_fatal("dup2(null_fd) failed: %m");
}
i_set_fatal_handler(master_fatal_callback);
i_set_error_handler(orig_error_callback);
if (!foreground)
daemonize();
T_BEGIN {
main_init(set);
} T_END;
master_service_run(master_service, NULL);
main_deinit();
master_service_deinit(&master_service);
return 0;
}