main.c revision 8d3278a82b964217d95c340ec6f82037cdc59d19
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "common.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "ioloop.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "file-lock.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "network.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "lib-signals.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "restrict-access.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "fd-close-on-exec.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "base64.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "buffer.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "istream.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "process-title.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "module-dir.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "var-expand.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "dict.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "mail-storage.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "mail-namespace.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <stdio.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <stdlib.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <unistd.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <syslog.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define IS_STANDALONE() \
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (getenv("LOGGED_IN") == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestruct client_workaround_list {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *name;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore enum client_workarounds num;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic struct client_workaround_list client_workaround_list[] = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore { "outlook-no-nuls", WORKAROUND_OUTLOOK_NO_NULS },
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore { "oe-ns-eoh", WORKAROUND_OE_NS_EOH },
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore { NULL, 0 }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestruct ioloop *ioloop;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid (*hook_client_created)(struct client **client) = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic struct module *modules = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic char log_prefix[128]; /* syslog() needs this to be permanent */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic struct io *log_io = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* warn about being killed because of some signal, except SIGINT (^C)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore which is too common at least while testing :) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (si->si_signo != SIGINT) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore si->si_signo, dec2str(si->si_pid),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dec2str(si->si_uid),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signal_code_to_str(si->si_signo, si->si_code));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore io_loop_stop(ioloop);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void log_error_callback(void *context ATTR_UNUSED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* the log fd is closed, don't die when trying to log later */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_failure_ignore_errors(TRUE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore io_loop_stop(ioloop);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic enum client_workarounds
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreparse_workarounds(const struct pop3_settings *set)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore enum client_workarounds client_workarounds = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct client_workaround_list *list;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *const *str;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore str = t_strsplit_spaces(set->pop3_client_workarounds, " ,");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (; *str != NULL; str++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore list = client_workaround_list;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (; list->name != NULL; list++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (strcasecmp(*str, list->name) == 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore client_workarounds |= list->num;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (list->name == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("Unknown client workaround: %s", *str);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return client_workarounds;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic enum uidl_keys parse_uidl_keymask(const char *format)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore enum uidl_keys mask = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (; *format != '\0'; format++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (format[0] == '%' && format[1] != '\0') {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (var_get_key(++format)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case 'v':
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mask |= UIDL_UIDVALIDITY;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case 'u':
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mask |= UIDL_UID;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case 'm':
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mask |= UIDL_MD5;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case 'f':
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mask |= UIDL_FILE_NAME;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return mask;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void open_logfile(void)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *user;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (getenv("LOG_TO_MASTER") != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_failure_internal();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (getenv("LOG_PREFIX") != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_strocpy(log_prefix, getenv("LOG_PREFIX"), sizeof(log_prefix));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore user = getenv("USER");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (user == NULL) user = "??";
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (strlen(user) >= sizeof(log_prefix)-6) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* quite a long user name, cut it */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore user = t_strndup(user, sizeof(log_prefix)-6-2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore user = t_strconcat(user, "..", NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_snprintf(log_prefix, sizeof(log_prefix), "pop3(%s): ", user);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (getenv("USE_SYSLOG") != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *env = getenv("SYSLOG_FACILITY");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_failure_syslog(log_prefix, LOG_NDELAY,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore env == NULL ? LOG_MAIL : atoi(env));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* log to file or stderr */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_failure_file(getenv("LOGFILE"), log_prefix);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (getenv("INFOLOGFILE") != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_info_file(getenv("INFOLOGFILE"));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_set_failure_timestamp_format(getenv("LOGSTAMP"));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void main_preinit(const struct pop3_settings **set_r,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const struct mail_user_settings **user_set_r)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *version;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore version = getenv("DOVECOT_VERSION");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (version != NULL && strcmp(version, PACKAGE_VERSION) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("Dovecot version mismatch: "
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "Master is v%s, pop3 is v"PACKAGE_VERSION" "
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "(if you don't care, set version_ignore=yes)", version);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Log file or syslog opening probably requires roots */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore open_logfile();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_storage_init();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_storage_register_all();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mailbox_list_register_all();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* read settings after registering storages so they can have their
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore own setting definitions too */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore pop3_settings_read(set_r, user_set_r);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Load the plugins before chrooting. Their init() is called later. */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore modules = *(*user_set_r)->mail_plugins == '\0' ? NULL :
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore module_dir_load((*user_set_r)->mail_plugin_dir,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (*user_set_r)->mail_plugins, TRUE, version);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore restrict_access_allow_coredumps(TRUE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic bool main_init(const struct pop3_settings *set,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const struct mail_user_settings *user_set)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct mail_user *user;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct client *client;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *str, *error;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bool ret = TRUE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_init();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_ignore(SIGPIPE, TRUE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_ignore(SIGALRM, FALSE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (getenv("USER") == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("USER environment missing");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (set->mail_debug) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *home;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore home = getenv("HOME");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_info("Effective uid=%s, gid=%s, home=%s",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dec2str(geteuid()), dec2str(getegid()),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore home != NULL ? home : "(none)");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (set->shutdown_clients) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* If master dies, the log fd gets closed and we'll quit */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore log_io = io_add(STDERR_FILENO, IO_ERROR,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore log_error_callback, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dict_drivers_register_builtin();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_users_init(user_set->auth_socket_path, set->mail_debug);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore clients_init();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore module_dir_init(modules);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore user = mail_user_alloc(getenv("USER"), user_set);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_user_set_home(user, getenv("HOME"));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (mail_user_init(user, &error) < 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("Mail user initialization failed: %s", error);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (mail_namespaces_init(user, &error) < 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("Namespace initialization failed: %s", error);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore client = client_create(0, 1, user, set);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (client == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore client->workarounds = parse_workarounds(set);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore client->uidl_keymask = parse_uidl_keymask(set->pop3_uidl_format);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (client->uidl_keymask == 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_fatal("pop3_uidl_format setting doesn't contain any "
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "%% variables.");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!IS_STANDALONE())
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore client_send_line(client, "+OK Logged in.");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore str = getenv("CLIENT_INPUT");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (str != NULL) T_BEGIN {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore buffer_t *buf = t_base64_decode_str(str);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (buf->used > 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!i_stream_add_data(client->input, buf->data,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore buf->used))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore i_panic("Couldn't add client input to stream");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ret = client_handle_input(client);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } T_END;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return ret;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void main_deinit(void)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (log_io != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore io_remove(&log_io);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore clients_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore module_dir_unload(&modules);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_storage_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mail_users_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dict_drivers_unregister_builtin();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_signals_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore closelog();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint main(int argc ATTR_UNUSED, char *argv[], char *envp[])
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const struct pop3_settings *set;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const struct mail_user_settings *user_set;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#ifdef DEBUG
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!IS_STANDALONE() && getenv("GDB") == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore fd_debug_verify_leaks(3, 1024);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#endif
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (IS_STANDALONE() && getuid() == 0 &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore net_getpeername(1, NULL, NULL) == 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore printf("-ERR pop3 binary must not be started from "
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "inetd, use pop3-login instead.\n");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* NOTE: we start rooted, so keep the code minimal until
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore restrict_access_by_env() is called */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_init();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore main_preinit(&set, &user_set);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore process_title_init(argv, envp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ioloop = io_loop_create();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (main_init(set, user_set))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore io_loop_run(ioloop);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore main_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore io_loop_destroy(&ioloop);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore lib_deinit();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore