main.c revision 3839f925645b1ecfb2e321d1741b63526a27d590
/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "array.h"
#include "ioloop.h"
#include "lib-signals.h"
#include "network.h"
#include "env-util.h"
#include "fd-close-on-exec.h"
#include "write-full.h"
#include "restrict-process-size.h"
#include "askpass.h"
#include "auth-process.h"
#include "capabilities.h"
#include "dict-process.h"
#include "login-process.h"
#include "mail-process.h"
#include "syslog-util.h"
#include "listener.h"
#include "ssl-init.h"
#include "log.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <syslog.h>
/* Try to raise our fd limit this high at startup. If the limit is already
higher, it's not dropped. */
#define DOVECOT_MASTER_FD_MIN_LIMIT 65536
#define FATAL_FILENAME "master-fatal.lastlog"
static pid_t master_original_pid;
char program_path[PATH_MAX];
char ssl_manual_key_password[100];
const char *env_tz;
bool auth_success_written;
#ifdef DEBUG
bool gdb;
#endif
{
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. */
if (getpid() == master_original_pid) {
/* write the error message to a file */
if (fd != -1) {
}
}
/* write it to log as well */
else
}
static void fatal_log_check(void)
{
const char *path;
char buf[1024];
int fd;
if (fd == -1)
return;
if (ret < 0)
else {
i_warning("Last died with error (see error log for more "
"information): %s", buf);
}
}
{
i_info("If you have trouble with authentication failures,\n"
"enable auth_debug setting. "
}
}
{
int facility;
} else {
/* log to file or stderr */
}
}
static void settings_reload(void)
{
i_warning("SIGHUP received - reloading configuration");
/* restart auth and login processes */
i_warning("Invalid configuration, keeping old one");
else {
if (!IS_INETD())
}
}
{
/* warn about being killed because of some signal, except SIGINT (^C)
which is too common at least while testing :) */
}
void *context ATTR_UNUSED)
{
}
void *context ATTR_UNUSED)
{
}
{
return TRUE;
return TRUE;
return FALSE;
}
{
return TRUE;
return TRUE;
}
return FALSE;
}
static void open_null_fd(void)
{
if (null_fd == -1)
}
static void open_fds(void)
{
/* make sure all fds between 0..3 are used. */
while (null_fd < 4) {
if (null_fd == -1)
i_fatal("dup(null_fd) failed: %m");
}
if (!IS_INETD()) {
T_BEGIN {
} T_END;
}
/* close stdin and stdout. */
i_fatal("dup2(0) failed: %m");
i_fatal("dup2(1) failed: %m");
}
static void create_pid_file(const char *path)
{
const char *pid;
int fd;
if (fd == -1)
}
static void main_log_startup(void)
{
else
}
{
/* deny file access from everyone else except owner */
(void)umask(0077);
if (!have_stderr(settings_root)) {
i_fatal("dup2(2) failed: %m");
}
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");
}
log_init();
ssl_init();
"/master.pid", NULL));
}
static void main_deinit(void)
{
"/master.pid", NULL));
ssl_deinit();
i_error("close(null_fd) failed: %m");
log_deinit();
closelog();
}
{
if (pid < 0)
i_fatal("fork() failed: %m");
if (pid != 0)
_exit(0);
if (setsid() < 0)
i_fatal("setsid() failed: %m");
}
static void print_help(void)
{
"Usage: dovecot [-F] [-c <config file>] [-p] [-n] [-a]\n"
" [--version] [--build-options] [--exec-mail <protocol> [<args>]]\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
"SQL drivers:"
#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_SIA
" sia"
#endif
#ifdef PASSDB_SQL
" sql"
#endif
#ifdef PASSDB_VPOPMAIL
" vpopmail"
#endif
"\nUserdb:"
#ifdef USERDB_NSS
" nss"
#endif
#ifdef USERDB_LDAP
" ldap"
#endif
#ifdef USERDB_PASSWD
" passwd"
#endif
#ifdef USERDB_PASSWD_FILE
" passwd-file"
#endif
#ifdef USERDB_PREFETCH
" prefetch"
#endif
#ifdef USERDB_SQL
" sql"
#endif
#ifdef USERDB_STATIC
" static"
#endif
#ifdef USERDB_VPOPMAIL
" vpopmail"
#endif
"\n");
}
{
/* parse arguments */
int i;
#ifdef DEBUG
#endif
lib_init();
master_uid = geteuid();
inetd_login_fd = -1;
for (i = 1; i < argc; i++) {
/* foreground */
foreground = TRUE;
dump_config = TRUE;
/* config file */
i++;
configfile = argv[i];
/* Ask SSL private key password */
ask_key_pass = TRUE;
/* <protocol> [<args>]
read configuration and execute mail process */
i++;
exec_protocol = argv[i];
break;
return 0;
return 0;
foreground = TRUE;
} else {
print_help();
}
}
/* need to have this open before reading settings */
open_null_fd();
/* starting through inetd. */
inetd_login_fd = dup(0);
if (inetd_login_fd == -1)
i_fatal("dup(0) failed: %m");
foreground = TRUE;
}
if (dump_config) {
/* print the config file path before parsing it, so in case
of errors it's still shown */
}
/* read and verify settings before forking */
T_BEGIN {
dump_config || log_error))
} T_END;
if (dump_config) {
return 0;
}
if (ask_key_pass) T_BEGIN {
const char *prompt;
"%s: ",
sizeof(ssl_manual_key_password));
} T_END;
/* save TZ environment. AIX depends on it to get the timezone
correctly. */
/* clean up the environment of everything */
env_clean();
/* put back the TZ */
if (exec_protocol != NULL) {
/* Put back user and home */
}
if (!log_error)
open_fds();
if (!foreground)
ioloop = io_loop_create();
main_deinit();
lib_deinit();
return 0;
}