main.c revision f6105538b51070d31d54c05430d2aa8f3b270e09
/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "ioloop.h"
#include "lib-signals.h"
#include "fd-close-on-exec.h"
#include "array.h"
#include "write-full.h"
#include "env-util.h"
#include "hostpid.h"
#include "restrict-process-size.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "askpass.h"
#include "capabilities.h"
#include "service.h"
#include "service-listen.h"
#include "service-monitor.h"
#include "service-log.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#define MASTER_SERVICE_NAME "master"
#define FATAL_FILENAME "master-fatal.lastlog"
#define MASTER_PID_FILE_NAME "master.pid"
struct master_service *master_service;
bool auth_success_written;
bool core_dumps_disabled;
char ssl_manual_key_password[100];
int null_fd;
struct service_list *services;
static char *pidfile_path;
static failure_callback_t *orig_error_callback;
static const struct setting_parser_info *set_roots[] = {
};
{
const char *executable, *p, **argv;
executable = argv[0];
if (extra_args != NULL) {
const char **new_argv;
/* @UNSAFE */
sizeof(const char *) * count2);
}
/* hide the path, it's ugly */
/* prefix with dovecot/ */
"execv(%s) failed: %m", executable);
}
const char **error_r)
{
if (*user == '\0') {
return 0;
}
return -1;
}
return 0;
}
{
if (*group == '\0') {
return 0;
}
return -1;
}
return 0;
}
{
int fd;
/* if we already forked a child process, this isn't fatal for the
main process and there's no need to write the fatal file. */
/* write the error message to a file (we're chdired to
base dir) */
if (fd != -1) {
}
}
abort(); /* just to silence the noreturn attribute warnings */
}
static void ATTR_NORETURN
{
abort();
}
static void
{
}
{
const char *path;
char buf[1024];
int fd;
if (fd == -1)
return;
if (ret < 0)
else {
"information): %s\n", buf);
}
}
static bool
{
struct service_settings *const *services;
unsigned int i, count;
for (i = 0; i < count; i++) {
return TRUE;
}
return FALSE;
}
{
struct service_settings *const *services;
unsigned int i, count;
for (i = 0; i < count; i++) {
return TRUE;
}
}
return FALSE;
}
{
"If you have trouble with authentication failures,\n"
"enable auth_debug setting. See http://wiki.dovecot.org/WhyDoesItNotWork\n"
"This message goes away after the first successful login.\n");
}
}
{
char buf[32];
int fd;
bool found;
if (fd == -1) {
return FALSE;
}
if (ret <= 0) {
if (ret == 0)
else
} else {
ret--;
}
return found;
}
static void pid_file_check_running(const char *path)
{
return;
i_fatal("Dovecot is already running with PID %s "
}
static void send_master_signal(int signo)
{
return;
}
exit(0);
}
static void create_pid_file(const char *path)
{
const char *pid;
int fd;
if (fd == -1)
}
static void
void *context ATTR_UNUSED)
{
struct master_service_settings_input input;
const struct master_settings *set;
void **sets;
struct service_list *new_services;
const char *error;
i_warning("SIGHUP received - reloading configuration");
/* see if hostname changed */
hostpid_init();
return;
}
&new_services, &error) < 0) {
/* new configuration is invalid, keep the old */
return;
}
/* switch to new configuration. */
}
static void
{
}
static void
{
}
{
i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
}
static void main_log_startup(void)
{
core_limit == 0;
if (core_dumps_disabled)
else
}
{
/* deny file access from everyone else except owner */
(void)umask(0077);
if (log_error) {
printf("Writing to error logs and killing myself..\n");
i_info("This is Dovecot's info log");
i_warning("This is Dovecot's warning log");
i_error("This is Dovecot's error log");
i_fatal("This is Dovecot's fatal log");
}
}
static void main_deinit(void)
{
if (unlink(pidfile_path) < 0)
}
{
const char *path;
if (*path == '/')
return path;
i_fatal("getcwd() failed: %m");
}
{
unsigned long secs;
return;
/* time moved backwards. disable launching new service processes
until */
i_warning("Time moved backwards by %lu seconds, "
"waiting for %lu secs until new services are launched again.",
}
static void daemonize(void)
{
if (pid < 0)
i_fatal("fork() failed: %m");
if (pid != 0)
_exit(0);
if (setsid() < 0)
i_fatal("setsid() failed: %m");
/* update my_pid */
hostpid_init();
}
static void print_help(void)
{
"Usage: dovecot [-F] [-c <config file>] [-p] [-n] [-a]\n"
" [-cb <config binary path>] [--version] [--build-options]\n");
}
static void print_build_options(void)
{
printf("Build options:"
#ifdef IOLOOP_EPOLL
" ioloop=epoll"
#endif
#ifdef IOLOOP_KQUEUE
" ioloop=kqueue"
#endif
#ifdef IOLOOP_POLL
" ioloop=poll"
#endif
#ifdef IOLOOP_SELECT
" ioloop=select"
#endif
#ifdef IOLOOP_NOTIFY_DNOTIFY
" notify=dnotify"
#endif
#ifdef IOLOOP_NOTIFY_INOTIFY
" notify=inotify"
#endif
#ifdef IOLOOP_NOTIFY_KQUEUE
" notify=kqueue"
#endif
#ifdef HAVE_IPV6
" ipv6"
#endif
#ifdef HAVE_GNUTLS
" gnutls"
#endif
#ifdef HAVE_OPENSSL
" openssl"
#endif
#ifdef SQL_DRIVER_PLUGINS
"\nSQL driver plugins:"
#else
"\nSQL drivers:"
#endif
#ifdef BUILD_MYSQL
" mysql"
#endif
#ifdef BUILD_PGSQL
" postgresql"
#endif
#ifdef BUILD_SQLITE
" sqlite"
#endif
"\nPassdb:"
#ifdef PASSDB_BSDAUTH
" bsdauth"
#endif
#ifdef PASSDB_CHECKPASSWORD
" checkpassword"
#endif
#ifdef PASSDB_LDAP
" ldap"
#endif
#ifdef PASSDB_PAM
" pam"
#endif
#ifdef PASSDB_PASSWD
" passwd"
#endif
#ifdef PASSDB_PASSWD_FILE
" passwd-file"
#endif
#ifdef PASSDB_SHADOW
" shadow"
#endif
#ifdef PASSDB_SQL
" sql"
#endif
#ifdef PASSDB_VPOPMAIL
" vpopmail"
#endif
"\nUserdb:"
#ifdef USERDB_CHECKPASSWORD
" checkpassword"
#endif
#ifdef USERDB_LDAP
" ldap"
#ifndef BUILTIN_LDAP
"(plugin)"
#endif
#endif
#ifdef USERDB_PASSWD
" passwd"
#endif
#ifdef USERDB_PREFETCH
" prefetch"
#endif
#ifdef USERDB_PASSWD_FILE
" passwd-file"
#endif
#ifdef USERDB_SQL
" sql"
#endif
#ifdef USERDB_STATIC
" static"
#endif
#ifdef USERDB_VPOPMAIL
" vpopmail"
#endif
"\n");
}
{
struct master_settings *set;
unsigned int child_process_env_idx = 0;
void **sets;
int c, send_signal = 0;
#ifdef DEBUG
else
#endif
i_set_failure_prefix("");
master_uid = geteuid();
master_gid = getegid();
if (c == '-')
break;
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:
c, optarg)) {
print_help();
}
break;
}
}
if (doveconf_arg != NULL) {
const char **args;
args[0] = DOVECOT_CONFIG_BIN_PATH;
}
return 0;
return 0;
foreground = TRUE;
} else {
print_help();
}
optind++;
}
do {
if (null_fd == -1)
} while (null_fd <= STDERR_FILENO);
&error) < 0)
if (ask_key_pass) {
askpass("Give the password for SSL keys: ",
sizeof(ssl_manual_key_password));
}
i_fatal("dup2(null_fd) failed: %m");
if (send_signal != 0)
if (!log_error) {
}
/* save TZ environment. AIX depends on it to get the timezone
correctly. */
/* clean up the environment of everything */
env_clean();
/* put back the TZ */
}
sizeof(child_process_env) / sizeof(child_process_env[0]));
/* create service structures from settings. if there are any errors in
service configuration we'll catch it here. */
if (!log_error) {
/* if any listening fails, fail completely */
if (services_listen(services) <= 0)
i_fatal("Failed to start listeners");
if (!foreground)
daemonize();
}
main_deinit();
return 0;
}