main.c revision 7df48840258676571b69d91d532d3d6b627db420
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenconst char *process_names[PROCESS_TYPE_MAX] = {
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenstatic const char *configfile = SYSCONFDIR "/" PACKAGE ".conf";
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenstatic void listen_fds_close(struct server_settings *server);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenint validate_str(const char *str, size_t max_len)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen for (i = 0; i < max_len; i++) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* remove all environment, we don't need them */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* we'll log through master process */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void sig_quit(int signo __attr_unused__)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_set_failure_syslog("dovecot", LOG_NDELAY, LOG_MAIL);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* log to file or stderr */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_set_failure_timestamp_format(set->log_timestamp);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void settings_reload(void)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen struct server_settings *old_set = settings_root;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_warning("SIGHUP received - reloading configuration");
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen /* restart auth and login processes */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_warning("Invalid configuration, keeping old one");
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainenstatic const char *get_exit_status_message(enum fatal_exit_status status)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return "Can't open log file";
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return "Can't write to log file";
7a87427770874f38d1d299635b37d699f9772860Timo Sirainen return "Internal logging error";
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return "Out of memory";
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return "exec() failed";
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic void timeout_handler(void *context __attr_unused__)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* get the type and remove from hash */
4b8c92b4773677a7b4064816e469eeafc976ba75Timo Sirainen /* write errors to syslog */
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen process_type_name = process_names[process_type];
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("child %s (%s) killed with signal %d",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (pid == -1 && errno != EINTR && errno != ECHILD)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic struct ip_addr *resolve_ip(const char *name, unsigned int *port)
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen const char *p;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* IPv6 address */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (*p == '\0')
7d81a331d0af7a7e2c6fecaee11e80a525bec507Timo Sirainen else if (*p != ':')
7d81a331d0af7a7e2c6fecaee11e80a525bec507Timo Sirainen i_fatal("Invalid data after ']' in address %s", name);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* IPv4 any */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* IPv6 any */
acf3b7bf3a8891b118a71c45e6c48d17bc90b259Timo Sirainen /* Return the first IP if there happens to be multiple. */
acf3b7bf3a8891b118a71c45e6c48d17bc90b259Timo Sirainen ret = net_gethostbyname(name, &ip, &ips_count);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainenstatic void listen_protocols(struct settings *set, int retry)
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen const char *const *proto;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen normal_port = set->protocol == MAIL_PROTOCOL_IMAP ? 143 : 110;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ssl_port = set->protocol == MAIL_PROTOCOL_IMAP ? 993 : 995;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* resolve */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen normal_ip = resolve_ip(set->listen, &normal_port);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen ssl_ip = resolve_ip(set->ssl_listen, &ssl_port);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (ssl_ip == NULL && set->ssl_listen == NULL)
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen /* register wanted protocols */
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen proto = t_strsplit_spaces(set->protocols, " ");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen } else if (strcasecmp(*proto, "imaps") == 0) {
acf3b7bf3a8891b118a71c45e6c48d17bc90b259Timo Sirainen } else if (strcasecmp(*proto, "pop3s") == 0) {
7a87427770874f38d1d299635b37d699f9772860Timo Sirainen i_fatal("Protocol %s given more than once", *proto);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen for (i = 0; i < 10; i++) {
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen if (*fd != -1 || errno != EADDRINUSE || !retry)
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen /* wait a while and try again. we're SIGHUPing
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen so we most likely just closed it ourself.. */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen for (server = settings_root; server != NULL; server = server->next) {
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainenstatic void listen_fds_close(struct server_settings *server)
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainen for (; server != NULL; server = server->next) {
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainen i_error("close(imap.ssl_listen_fd) failed: %m");
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainen i_error("close(pop3.ssl_listen_fd) failed: %m");
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainenstatic int have_stderr_set(struct settings *set)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen strcmp(set->info_log_path, "/dev/stderr") == 0)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int have_stderr(struct server_settings *server)
return TRUE;
return TRUE;
return FALSE;
static void open_fds(void)
if (!IS_INETD())
const char *pid;
int fd;
static void main_init(void)
log_init();
ssl_init();
static void main_deinit(void)
if (lib_signal_kill != 0)
ssl_deinit();
log_deinit();
closelog();
if (pid < 0)
if (pid != 0)
_exit(0);
if (setsid() < 0)
static void print_help(void)
#ifdef DEBUG
lib_init();
print_help();
env_clean();
open_fds();
if (!foreground)
main_init();
main_deinit();
lib_deinit();