main.c revision c1b0fc9bde0ca3690aa71c5812406b82eb50b356
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara/* Copyright (C) 2002-2003 Timo Sirainen */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "common.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "ioloop.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "ostream.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "str.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "lib-signals.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "restrict-access.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "fd-close-on-exec.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "process-title.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "randgen.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "module-dir.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "mail-storage.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "commands.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include "namespace.h"
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include <stdlib.h>
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include <unistd.h>
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#include <syslog.h>
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#define IS_STANDALONE() \
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara (getenv("LOGGED_IN") == NULL && getenv("IMAPLOGINTAG") == NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastruct ioloop *ioloop;
f14a485fcb48f77d077a14b766f0acc097093fe5jvergaraunsigned int max_keyword_length, mailbox_check_interval;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergaraunsigned int imap_max_line_length;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic struct module *modules;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic char log_prefix[128]; /* syslog() needs this to be permanent */
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suterstatic pool_t namespace_pool;
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_suter
53247d28ba99538f841a13ea2cde01c3faa3ef36kenneth_sutervoid (*hook_mail_storage_created)(struct mail_storage **storage) = NULL;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergaravoid (*hook_client_created)(struct client **client) = NULL;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastring_t *capability_string;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic void sig_quit(int signo __attr_unused__)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara io_loop_stop(ioloop);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic void open_logfile(void)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara const char *user;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (getenv("LOG_TO_MASTER") != NULL) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_set_failure_internal();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara return;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = getenv("USER");
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara if (user == NULL) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (IS_STANDALONE())
68c6568488f064ce97a76169ef43a8f5f7b1c2f6jvergara user = getlogin();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (user == NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = "??";
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (strlen(user) >= sizeof(log_prefix)-6) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* quite a long user name, cut it */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = t_strndup(user, sizeof(log_prefix)-6-2);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = t_strconcat(user, "..", NULL);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_snprintf(log_prefix, sizeof(log_prefix), "imap(%s)", user);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (getenv("USE_SYSLOG") != NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_set_failure_syslog(log_prefix, LOG_NDELAY, LOG_MAIL);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara else {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* log to file or stderr */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_set_failure_file(getenv("LOGFILE"), log_prefix);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (getenv("INFOLOGFILE") != NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_set_info_file(getenv("INFOLOGFILE"));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara i_set_failure_timestamp_format(getenv("LOGSTAMP"));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic void drop_privileges(void)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* Log file or syslog opening probably requires roots */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara open_logfile();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* Most likely needed. Have to open /dev/urandom before possible
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara chrooting. */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara random_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara restrict_access_by_env(!IS_STANDALONE());
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic void main_init(void)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara struct client *client;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara const char *user, *str;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara lib_init_signals(sig_quit);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = getenv("USER");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (user == NULL) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (IS_STANDALONE())
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara user = getlogin();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (user == NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_fatal("USER environment missing");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara capability_string = str_new(default_pool, sizeof(CAPABILITY_STRING)+32);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara str_append(capability_string, CAPABILITY_STRING);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara mail_storage_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara mail_storage_register_all();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara clients_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara commands_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara modules = getenv("MODULE_DIR") == NULL ? NULL :
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara module_dir_load(getenv("MODULE_DIR"));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara str = getenv("IMAP_MAX_LINE_LENGTH");
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara imap_max_line_length = str != NULL ?
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara (unsigned int)strtoul(str, NULL, 10) :
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara DEFAULT_IMAP_MAX_LINE_LENGTH;
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara str = getenv("MAIL_MAX_KEYWORD_LENGTH");
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara max_keyword_length = str != NULL ?
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara (unsigned int)strtoul(str, NULL, 10) :
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara DEFAULT_MAX_KEYWORD_LENGTH;
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara str = getenv("MAILBOX_CHECK_INTERVAL");
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara mailbox_check_interval = str == NULL ? 0 :
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara (unsigned int)strtoul(str, NULL, 10);
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara
4cf0e2c1065147b79e7d6ffe59e517c38cbc6bdejvergara namespace_pool = pool_alloconly_create("namespaces", 1024);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara client = client_create(0, 1, namespace_init(namespace_pool, user));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara o_stream_cork(client->output);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (IS_STANDALONE()) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara client_send_line(client, t_strconcat(
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara "* PREAUTH [CAPABILITY "CAPABILITY_STRING"] "
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara "Logged in as ", user, NULL));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara } else if (getenv("IMAPLOGINTAG") != NULL) {
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* Support for mailfront */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara client_send_line(client, t_strconcat(getenv("IMAPLOGINTAG"),
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara " OK Logged in.", NULL));
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara }
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara o_stream_flush(client->output);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergarastatic void main_deinit(void)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* warn about being killed because of some signal, except SIGINT (^C)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara which is too common at least while testing :) */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (lib_signal_kill != 0 && lib_signal_kill != 2)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara i_warning("Killed with signal %d", lib_signal_kill);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara module_dir_unload(modules);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara commands_deinit();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara clients_deinit();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara mail_storage_deinit();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara random_deinit();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara pool_unref(namespace_pool);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara str_free(capability_string);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara closelog();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergaraint main(int argc __attr_unused__, char *argv[], char *envp[])
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara{
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#ifdef DEBUG
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara if (getenv("LOGGED_IN") != NULL)
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara fd_debug_verify_leaks(3, 1024);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara#endif
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara /* NOTE: we start rooted, so keep the code minimal until
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara restrict_access_by_env() is called */
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara lib_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara drop_privileges();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara process_title_init(argv, envp);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara ioloop = io_loop_create(system_pool);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara main_init();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara io_loop_run(ioloop);
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara main_deinit();
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara io_loop_destroy(ioloop);
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara lib_deinit();
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara return 0;
11178d20048abeee671d0cdb2aab6dfbaa36293bjvergara}
7056ae8910decb0d96b430451ac58b99526eb0d9jvergara