main.c revision 55cdf2ed53584247aab18d2689ba24264211ccf6
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "ioloop.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "lib-signals.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fd-close-on-exec.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "env-util.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen#include "abspath.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ipwd.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "str.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "execv-const.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "restrict-process-size.h"
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#include "master-instance.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "master-service.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "master-service-settings.h"
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#include "askpass.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "capabilities.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "master-client.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "service.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "service-anvil.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "service-listen.h"
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include "service-monitor.h"
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#include "service-process.h"
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#include "service-log.h"
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen#include "dovecot-version.h"
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#include <stdio.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <unistd.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <fcntl.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#include <sys/stat.h>
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#define MASTER_SERVICE_NAME "master"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#define FATAL_FILENAME "master-fatal.lastlog"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#define MASTER_PID_FILE_NAME "master.pid"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#define SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS (60*3)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenuid_t master_uid;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainengid_t master_gid;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenbool core_dumps_disabled;
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainenconst char *ssl_manual_key_password;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenint global_master_dead_pipe_fd[2];
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstruct service_list *services;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainenbool startup_finished = FALSE;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainenstatic char *pidfile_path;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainenstatic struct master_instance_list *instances;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainenstatic struct timeout *to_instance;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainenstatic failure_callback_t *orig_fatal_callback;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic failure_callback_t *orig_error_callback;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic const struct setting_parser_info *set_roots[] = {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen &master_setting_parser_info,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen NULL
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen};
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenvoid process_exec(const char *cmd)
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const char *executable, *p, **argv;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen argv = t_strsplit(cmd, " ");
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen executable = argv[0];
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen /* hide the path, it's ugly */
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen p = strrchr(argv[0], '/');
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen if (p != NULL) argv[0] = p+1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen /* prefix with dovecot/ */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen argv[0] = t_strdup_printf("%s/%s", services->set->instance_name,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen argv[0]);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (strncmp(argv[0], PACKAGE, strlen(PACKAGE)) != 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen argv[0] = t_strconcat(PACKAGE"-", argv[0], NULL);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen (void)execv_const(executable, argv);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainenint get_uidgid(const char *user, uid_t *uid_r, gid_t *gid_r,
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen const char **error_r)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct passwd pw;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen if (*user == '\0') {
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen *uid_r = (uid_t)-1;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen *gid_r = (gid_t)-1;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen return 0;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen }
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen switch (i_getpwnam(user, &pw)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen case -1:
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *error_r = t_strdup_printf("getpwnam(%s) failed: %m", user);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen return -1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen case 0:
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen *error_r = t_strdup_printf("User doesn't exist: %s", user);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen default:
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *uid_r = pw.pw_uid;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen *gid_r = pw.pw_gid;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return 0;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint get_gid(const char *group, gid_t *gid_r, const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct group gr;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (*group == '\0') {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *gid_r = (gid_t)-1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return 0;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen switch (i_getgrnam(group, &gr)) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen case -1:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *error_r = t_strdup_printf("getgrnam(%s) failed: %m", group);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return -1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen case 0:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *error_r = t_strdup_printf("Group doesn't exist: %s", group);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return -1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen default:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *gid_r = gr.gr_gid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic void ATTR_NORETURN ATTR_FORMAT(2, 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmaster_fatal_callback(const struct failure_context *ctx,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *format, va_list args)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *path, *str;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen va_list args2;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen pid_t pid;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen int fd;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* if we already forked a child process, this isn't fatal for the
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen main process and there's no need to write the fatal file. */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (str_to_pid(my_pid, &pid) < 0)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen i_unreached();
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (getpid() == pid) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* write the error message to a file (we're chdired to
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen base dir) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen path = t_strconcat(FATAL_FILENAME, NULL);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd != -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen VA_COPY(args2, args);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen str = t_strdup_vprintf(format, args2);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen va_end(args2);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen (void)write_full(fd, str, strlen(str));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_close_fd(&fd);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen orig_fatal_callback(ctx, format, args);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen abort(); /* just to silence the noreturn attribute warnings */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenstatic void ATTR_NORETURN ATTR_FORMAT(2, 0)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenstartup_fatal_handler(const struct failure_context *ctx,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen const char *fmt, va_list args)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen va_list args2;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen VA_COPY(args2, args);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen t_strdup_vprintf(fmt, args2));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen va_end(args2);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen orig_fatal_callback(ctx, fmt, args);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen abort();
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void ATTR_FORMAT(2, 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstartup_error_handler(const struct failure_context *ctx,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *fmt, va_list args)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen va_list args2;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen VA_COPY(args2, args);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen fprintf(stderr, "%s%s\n", failure_log_type_prefixes[ctx->type],
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen t_strdup_vprintf(fmt, args2));
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen va_end(args2);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen orig_error_callback(ctx, fmt, args);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainenstatic void fatal_log_check(const struct master_settings *set)
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen const char *path;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen char buf[1024];
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen ssize_t ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen path = t_strconcat(set->base_dir, "/"FATAL_FILENAME, NULL);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen fd = open(path, O_RDONLY);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (fd == -1)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen ret = read(fd, buf, sizeof(buf)-1);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (ret < 0)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen i_error("read(%s) failed: %m", path);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen else {
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen buf[ret] = '\0';
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen fprintf(stderr, "Last died with error (see error log for more "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "information): %s\n", buf);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_close_fd(&fd);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_unlink(path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool pid_file_read(const char *path, pid_t *pid_r)
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen char buf[32];
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen int fd;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ssize_t ret;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen bool found;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *pid_r = (pid_t)-1;
7889c9f65e23c83fc31cecf304cab4ab070d6aa1Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen fd = open(path, O_RDONLY);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (fd == -1) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (errno == ENOENT)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return FALSE;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen i_fatal("open(%s) failed: %m", path);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen }
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen ret = read(fd, buf, sizeof(buf)-1);
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (ret <= 0) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if (ret == 0)
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen i_error("Empty PID file in %s, overriding", path);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen else
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen i_fatal("read(%s) failed: %m", path);
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen found = FALSE;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen } else {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (buf[ret-1] == '\n')
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ret--;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen buf[ret] = '\0';
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (str_to_pid(buf, pid_r) < 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_error("PID file contains invalid PID value");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen found = FALSE;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen found = !(*pid_r == getpid() ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen (kill(*pid_r, 0) < 0 && errno == ESRCH));
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_close_fd(&fd);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return found;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void pid_file_check_running(const char *path)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen pid_t pid;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (!pid_file_read(path, &pid))
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen i_fatal("Dovecot is already running with PID %s "
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "(read from %s)", dec2str(pid), path);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void create_pid_file(const char *path)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen const char *pid;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen int fd;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen pid = t_strconcat(dec2str(getpid()), "\n", NULL);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd == -1)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_fatal("open(%s) failed: %m", path);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (write_full(fd, pid, strlen(pid)) < 0)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_fatal("write() failed in %s: %m", path);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_close_fd(&fd);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstatic void create_config_symlink(const struct master_settings *set)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen const char *base_config_path;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen base_config_path = t_strconcat(set->base_dir, "/"PACKAGE".conf", NULL);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_unlink_if_exists(base_config_path);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (symlink(services->config->config_file_path, base_config_path) < 0) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_error("symlink(%s, %s) failed: %m",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen services->config->config_file_path, base_config_path);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen}
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenstatic void instance_update_now(struct master_instance_list *list)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen int ret;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen ret = master_instance_list_set_name(list, services->set->base_dir,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen services->set->instance_name);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (ret == 0) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen /* duplicate instance names. allow without warning.. */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen (void)master_instance_list_update(list, services->set->base_dir);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (to_instance != NULL)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen timeout_remove(&to_instance);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen to_instance = timeout_add((3600*12 + rand()%(60*30)) * 1000,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen instance_update_now, list);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstatic void instance_update(const struct master_settings *set)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen const char *path;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen path = t_strconcat(set->state_dir, "/"MASTER_INSTANCE_FNAME, NULL);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen instances = master_instance_list_init(path);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen instance_update_now(instances);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstatic void
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainensig_settings_reload(const siginfo_t *si ATTR_UNUSED,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen void *context ATTR_UNUSED)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct master_service_settings_input input;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct master_service_settings_output output;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen const struct master_settings *set;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen void **sets;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct service_list *new_services;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct service *service;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen const char *error;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_warning("SIGHUP received - reloading configuration");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* see if hostname changed */
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen hostpid_init();
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (services->config->process_avail == 0) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* we can't reload config if there's no config process. */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (service_process_create(services->config) == NULL) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_error("Can't reload configuration because "
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen "we couldn't create a config process");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen memset(&input, 0, sizeof(input));
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen input.roots = set_roots;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen input.module = MASTER_SERVICE_NAME;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen input.config_path = services_get_config_socket_path(services);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (master_service_settings_read(master_service, &input,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen &output, &error) < 0) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_error("Error reading configuration: %s", error);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen sets = master_service_settings_get_others(master_service);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen set = sets[0];
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen if (services_create(set, &new_services, &error) < 0) {
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen /* new configuration is invalid, keep the old */
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen i_error("Config reload failed: %s", error);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen new_services->config->config_file_path =
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen p_strdup(new_services->pool,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen services->config->config_file_path);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen /* switch to new configuration. */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen services_monitor_stop(services, FALSE);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (services_listen_using(new_services, services) < 0) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen services_monitor_start(services);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* anvil never dies. it just gets moved to the new services list */
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen service = service_lookup_type(services, SERVICE_TYPE_ANVIL);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (service != NULL) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen while (service->processes != NULL)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen service_process_destroy(service->processes);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen services_destroy(services, FALSE);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen services = new_services;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen services_monitor_start(services);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainensig_log_reopen(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen service_signal(services->log, SIGUSR1);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen master_service_init_log(master_service, "master: ");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_set_fatal_handler(master_fatal_callback);
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen}
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainenstatic void
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainensig_reap_children(const siginfo_t *si ATTR_UNUSED, void *context ATTR_UNUSED)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen services_monitor_reap_children();
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen{
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen si->si_signo, dec2str(si->si_pid),
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen dec2str(si->si_uid),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen lib_signal_code_to_str(si->si_signo, si->si_code));
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* make sure new processes won't be created by the currently
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen running ioloop. */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen services->destroying = TRUE;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen master_service_stop(master_service);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic struct master_settings *master_settings_read(void)
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct master_service_settings_input input;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct master_service_settings_output output;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen const char *error;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen memset(&input, 0, sizeof(input));
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen input.roots = set_roots;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen input.module = "master";
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen input.parse_full_config = TRUE;
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen input.preserve_environment = TRUE;
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen if (master_service_settings_read(master_service, &input, &output,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen &error) < 0)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen i_fatal("Error reading configuration: %s", error);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return master_service_settings_get_others(master_service)[0];
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenstatic void master_set_import_environment(const struct master_settings *set)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen const char *const *envs, *key, *value;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen ARRAY_TYPE(const_string) keys;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (*set->import_environment == '\0')
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen return;
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen t_array_init(&keys, 8);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen envs = t_strsplit_spaces(set->import_environment, " ");
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen for (; *envs != NULL; envs++) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen value = strchr(*envs, '=');
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (value == NULL)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen key = *envs;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen else {
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen key = t_strdup_until(*envs, value);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen env_put(*envs);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen array_append(&keys, &key, 1);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen array_append_zero(&keys);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen value = t_strarray_join(array_idx(&keys, 0), " ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen env_put(t_strconcat(DOVECOT_PRESERVE_ENVS_ENV"=", value, NULL));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainenstatic void main_log_startup(char **protocols)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen#define STARTUP_STRING PACKAGE_NAME" v"DOVECOT_VERSION_FULL" starting up"
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen string_t *str = t_str_new(128);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rlim_t core_limit;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen str_append(str, STARTUP_STRING);
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen if (protocols[0] == NULL)
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen str_append(str, " without any protocols");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen str_printfa(str, " for %s",
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen t_strarray_join((const char **)protocols, ", "));
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen }
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen core_dumps_disabled = restrict_get_core_limit(&core_limit) == 0 &&
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen core_limit == 0;
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen if (core_dumps_disabled)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen str_append(str, " (core dumps disabled)");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_info("%s", str_c(str));
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void master_set_process_limit(void)
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen{
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen struct service *const *servicep;
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen unsigned int process_limit = 0;
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen rlim_t nproc;
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen /* we'll just count all the processes that can exist and set the
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen process limit so that we won't reach it. it's usually higher than
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen needed, since we'd only need to set it high enough for each
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen separate UID not to reach the limit, but this is difficult to
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen guess: mail processes should probably be counted together for a
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen common vmail user (unless system users are being used), but
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen we can't really guess what the mail processes are. */
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen array_foreach(&services->services, servicep)
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen process_limit += (*servicep)->process_limit;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (restrict_get_process_limit(&nproc) == 0 &&
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen process_limit > nproc)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen restrict_process_count(process_limit);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void main_init(const struct master_settings *set)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen master_set_process_limit();
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen drop_capabilities();
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen /* deny file access from everyone else except owner */
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen (void)umask(0077);
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen main_log_startup(set->protocols_split);
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen lib_signals_init();
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen lib_signals_ignore(SIGPIPE, TRUE);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen lib_signals_ignore(SIGALRM, FALSE);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen lib_signals_set_handler(SIGHUP, LIBSIG_FLAGS_SAFE,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen sig_settings_reload, NULL);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen lib_signals_set_handler(SIGUSR1, LIBSIG_FLAGS_SAFE,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen sig_log_reopen, NULL);
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen lib_signals_set_handler(SIGCHLD, LIBSIG_FLAGS_SAFE,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen sig_reap_children, NULL);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen lib_signals_set_handler(SIGINT, LIBSIG_FLAGS_SAFE, sig_die, NULL);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen lib_signals_set_handler(SIGTERM, LIBSIG_FLAGS_SAFE, sig_die, NULL);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen create_pid_file(pidfile_path);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen create_config_symlink(set);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen instance_update(set);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen master_clients_init();
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen services_monitor_start(services);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen startup_finished = TRUE;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen}
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenstatic void global_dead_pipe_close(void)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (close(global_master_dead_pipe_fd[0]) < 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen i_error("close(global dead pipe) failed: %m");
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen if (close(global_master_dead_pipe_fd[1]) < 0)
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen i_error("close(global dead pipe) failed: %m");
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen global_master_dead_pipe_fd[0] = -1;
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen global_master_dead_pipe_fd[1] = -1;
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen}
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainenstatic void main_deinit(void)
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen{
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen master_clients_deinit();
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen instance_update_now(instances);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen timeout_remove(&to_instance);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen master_instance_list_deinit(&instances);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen /* kill services and wait for them to die before unlinking pid file */
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen global_dead_pipe_close();
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen services_destroy(services, TRUE);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen i_unlink(pidfile_path);
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen i_free(pidfile_path);
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen service_anvil_global_deinit();
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen service_pids_deinit();
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic const char *get_full_config_path(struct service_list *list)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen const char *path;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen path = master_service_get_config_path(master_service);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (*path == '/')
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return path;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return p_strdup(list->pool, t_abspath(path));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void master_time_moved(time_t old_time, time_t new_time)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned long secs;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (new_time >= old_time)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* time moved backwards. disable launching new service processes
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen until */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen secs = old_time - new_time + 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (secs > SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen secs = SERVICE_TIME_MOVED_BACKWARDS_MAX_THROTTLE_SECS;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen services_throttle_time_sensitives(services, secs);
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen i_warning("Time moved backwards by %lu seconds, "
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen "waiting for %lu secs until new services are launched again.",
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen (unsigned long)(old_time - new_time), secs);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void daemonize(void)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen pid_t pid;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen pid = fork();
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (pid < 0)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_fatal("fork() failed: %m");
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (pid != 0)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen _exit(0);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (setsid() < 0)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_fatal("setsid() failed: %m");
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* update my_pid */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen hostpid_init();
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void print_help(void)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen fprintf(stderr,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen"Usage: dovecot [-F] [-c <config file>] [-p] [-n] [-a] [--help] [--version]\n"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen" [--build-options] [--hostdomain] [reload] [stop]\n");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void print_build_options(void)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen printf("Build options:"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_EPOLL
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " ioloop=epoll"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_KQUEUE
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " ioloop=kqueue"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_POLL
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " ioloop=poll"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_SELECT
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " ioloop=select"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_NOTIFY_INOTIFY
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " notify=inotify"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef IOLOOP_NOTIFY_KQUEUE
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " notify=kqueue"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#ifdef HAVE_GNUTLS
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen " gnutls"
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#endif
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#ifdef HAVE_OPENSSL
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen " openssl"
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#endif
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen " io_block_size=%u"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen "\nMail storages: "MAIL_STORAGES"\n"
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#ifdef SQL_DRIVER_PLUGINS
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "SQL driver plugins:"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#else
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "SQL drivers:"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef BUILD_MYSQL
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " mysql"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef BUILD_PGSQL
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen " postgresql"
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#endif
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#ifdef BUILD_SQLITE
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen " sqlite"
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#endif
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen "\nPassdb:"
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen#ifdef PASSDB_BSDAUTH
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen " bsdauth"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef PASSDB_CHECKPASSWORD
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " checkpassword"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef PASSDB_LDAP
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " ldap"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef PASSDB_PAM
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " pam"
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#endif
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen#ifdef PASSDB_PASSWD
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen " passwd"
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen#endif
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen#ifdef PASSDB_PASSWD_FILE
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen " passwd-file"
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#ifdef PASSDB_SHADOW
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen " shadow"
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
ec922832ddc917e48d98fdb409051b9c162b90a3Timo Sirainen#ifdef PASSDB_SQL
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen " sql"
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef PASSDB_VPOPMAIL
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen " vpopmail"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen "\nUserdb:"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef USERDB_CHECKPASSWORD
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen " checkpassword"
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef USERDB_LDAP
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen " ldap"
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#ifndef BUILTIN_LDAP
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen "(plugin)"
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#ifdef USERDB_NSS
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen " nss"
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#endif
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen#ifdef USERDB_PASSWD
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen " passwd"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#ifdef USERDB_PREFETCH
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen " prefetch"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#ifdef USERDB_PASSWD_FILE
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen " passwd-file"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#ifdef USERDB_SQL
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen " sql"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#ifdef USERDB_STATIC
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen " static"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#ifdef USERDB_VPOPMAIL
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen " vpopmail"
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen#endif
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen "\n", IO_BLOCK_SIZE);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen}
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainenint main(int argc, char *argv[])
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen{
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen struct master_settings *set;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen const char *error, *doveconf_arg = NULL;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen failure_callback_t *orig_info_callback, *orig_debug_callback;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen bool foreground = FALSE, ask_key_pass = FALSE;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen bool doubleopts[argc];
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen int i, c;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#ifdef DEBUG
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (getenv("GDB") == NULL)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen fd_debug_verify_leaks(3, 1024);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* drop -- prefix from all --args. ugly, but the only way that it
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen works with standard getopt() in all OSes.. */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen for (i = 1; i < argc; i++) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (strncmp(argv[i], "--", 2) == 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (argv[i][2] == '\0')
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen argv[i] += 2;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen doubleopts[i] = TRUE;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen } else {
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen doubleopts[i] = FALSE;
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen }
86d52f310fe939090c66b780a3b6ffe5d10dc8faTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen master_service = master_service_init(MASTER_SERVICE_NAME,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen MASTER_SERVICE_FLAG_STANDALONE |
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen MASTER_SERVICE_FLAG_DONT_LOG_TO_STDERR |
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen &argc, &argv, "+Fanp");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_unset_failure_prefix();
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen io_loop_set_time_moved_callback(current_ioloop, master_time_moved);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen master_uid = geteuid();
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen master_gid = getegid();
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen while ((c = master_getopt(master_service)) > 0) {
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen switch (c) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen case 'F':
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen foreground = TRUE;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen break;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen case 'a':
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen doveconf_arg = "-a";
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen break;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen case 'n':
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen doveconf_arg = "-n";
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen break;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen case 'p':
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen /* Ask SSL private key password */
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen ask_key_pass = TRUE;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen break;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen default:
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (!master_service_parse_option(master_service,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen c, optarg)) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen print_help();
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen exit(FATAL_DEFAULT);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen }
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen break;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen }
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen }
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen i_assert(optind > 0 && optind <= argc);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen if (doveconf_arg != NULL) {
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen const char **args;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args = t_new(const char *, 5);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args[0] = DOVECOT_CONFIG_BIN_PATH;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args[1] = doveconf_arg;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args[2] = "-c";
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args[3] = master_service_get_config_path(master_service);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen args[4] = NULL;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen execv_const(args[0], args);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen }
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen if (optind == argc) {
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen /* starting Dovecot */
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen } else if (!doubleopts[optind]) {
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen /* dovecot xx -> doveadm xx */
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen (void)execv(BINDIR"/doveadm", argv);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_fatal("execv("BINDIR"/doveadm) failed: %m");
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen } else if (strcmp(argv[optind], "version") == 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen printf("%s\n", DOVECOT_VERSION_FULL);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return 0;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen } else if (strcmp(argv[optind], "hostdomain") == 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen printf("%s\n", my_hostdomain());
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return 0;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else if (strcmp(argv[optind], "build-options") == 0) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen print_build_options();
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return 0;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else if (strcmp(argv[optind], "log-error") == 0) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen fprintf(stderr, "Writing to error logs and killing myself..\n");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen argv[optind] = "log test";
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen (void)execv(BINDIR"/doveadm", argv);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_fatal("execv("BINDIR"/doveadm) failed: %m");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen } else if (strcmp(argv[optind], "help") == 0) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen print_help();
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen } else {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen print_help();
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_fatal("Unknown argument: --%s", argv[optind]);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (pipe(global_master_dead_pipe_fd) < 0)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen i_fatal("pipe() failed: %m");
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen fd_close_on_exec(global_master_dead_pipe_fd[0], TRUE);
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen fd_close_on_exec(global_master_dead_pipe_fd[1], TRUE);
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen set = master_settings_read();
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen if (ask_key_pass) {
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen ssl_manual_key_password =
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen t_askpass("Give the password for SSL keys: ");
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen }
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (dup2(dev_null_fd, STDIN_FILENO) < 0)
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen i_fatal("dup2(dev_null_fd) failed: %m");
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen if (!foreground && dup2(dev_null_fd, STDOUT_FILENO) < 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_fatal("dup2(dev_null_fd) failed: %m");
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen pidfile_path =
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen i_strconcat(set->base_dir, "/"MASTER_PID_FILE_NAME, NULL);
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen master_service_init_log(master_service, "master: ");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen &orig_info_callback, &orig_debug_callback);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_set_fatal_handler(startup_fatal_handler);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_set_error_handler(startup_error_handler);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen pid_file_check_running(pidfile_path);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen master_settings_do_fixes(set);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen fatal_log_check(set);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen T_BEGIN {
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen master_set_import_environment(set);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen } T_END;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen master_service_env_clean();
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* create service structures from settings. if there are any errors in
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen service configuration we'll catch it here. */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen service_pids_init();
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen service_anvil_global_init();
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (services_create(set, &services, &error) < 0)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen i_fatal("%s", error);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
91d4c7b37580b031ed7b0154ae10c643521803f3Timo Sirainen services->config->config_file_path = get_full_config_path(services);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* if any listening fails, fail completely */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (services_listen(services) <= 0)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen i_fatal("Failed to start listeners");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (chdir(set->base_dir) < 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_fatal("chdir(%s) failed: %m", set->base_dir);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_set_fatal_handler(master_fatal_callback);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_set_error_handler(orig_error_callback);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!foreground)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen daemonize();
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen T_BEGIN {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen main_init(set);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen } T_END;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen master_service_run(master_service, NULL);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen main_deinit();
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen master_service_deinit(&master_service);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen