main.c revision 51b4c2c50a1eb94b9f9c6589afcf82586cf9a2f1
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen#include "lib-signals.h"
55a210942dc7da58b2fd0b11bed8da6b030af5c1Timo Sirainen#include "rawlog.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "restrict-access.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "fd-close-on-exec.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "process-title.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage.h"
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <syslog.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen#define IS_STANDALONE() \
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen (getenv("LOGGED_IN") == NULL)
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainenstruct ioloop *ioloop;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainenunsigned int max_custom_flag_length, mailbox_check_interval;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic char log_prefix[128]; /* syslog() needs this to be permanent */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenstatic void sig_quit(int signo __attr_unused__)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_loop_stop(ioloop);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void open_logfile(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen user = getenv("USER");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (user == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (IS_STANDALONE())
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen user = getlogin();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (user == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user = "??";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strlen(user) >= sizeof(log_prefix)-6) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* quite a long user name, cut it */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user = t_strndup(user, sizeof(log_prefix)-6-2);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen user = t_strconcat(user, "..", NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
659fe5d24825b160cae512538088020d97a60239Timo Sirainen i_snprintf(log_prefix, sizeof(log_prefix), "imap(%s)", user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (getenv("USE_SYSLOG") != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_set_failure_syslog(log_prefix, LOG_NDELAY, LOG_MAIL);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* log to file or stderr */
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen i_set_failure_file(getenv("LOGFILE"), log_prefix);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d8b77aef97e89f1ccc5cbdaef77be9052279e35fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (getenv("INFOLOGFILE") != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_set_info_file(getenv("INFOLOGFILE"));
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen i_set_failure_timestamp_format(getenv("LOGSTAMP"));
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen}
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenstatic void drop_privileges(void)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* Log file or syslog opening probably requires roots */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen open_logfile();
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen restrict_access_by_env(!IS_STANDALONE());
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
a928e7efabb1672b1476e597106d4b4b81ac6f3cTimo Sirainenstatic void main_init(void)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen{
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen struct client *client;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen struct mail_storage *storage;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *user, *mail, *str;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen int hin, hout;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen lib_init_signals(sig_quit);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen user = getenv("USER");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (user == NULL) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (IS_STANDALONE())
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen user = getlogin();
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (user == NULL)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen i_fatal("USER environment missing");
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen hin = 0; hout = 1;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen rawlog_open(&hin, &hout);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen mail_storage_init();
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen mail_storage_register_all();
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen clients_init();
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
a928e7efabb1672b1476e597106d4b4b81ac6f3cTimo Sirainen mail = getenv("MAIL");
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen if (mail == NULL) {
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen /* support also maildir-specific environment */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail = getenv("MAILDIR");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail = t_strconcat("maildir:", mail, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen storage = mail_storage_create_with_data(mail, user);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (storage == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* failed */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail != NULL && *mail != '\0')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Failed to create storage with data: %s", mail);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *home;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen home = getenv("HOME");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (home == NULL) home = "not set";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("MAIL environment missing and "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "autodetection failed (home %s)", home);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = getenv("MAIL_MAX_FLAG_LENGTH");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen max_custom_flag_length = str != NULL ?
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (unsigned int)strtoul(str, NULL, 10) :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen DEFAULT_MAX_CUSTOM_FLAG_LENGTH;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = getenv("MAILBOX_CHECK_INTERVAL");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mailbox_check_interval = str == NULL ? 0 :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (unsigned int)strtoul(str, NULL, 10);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client = client_create(hin, hout, storage);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (IS_STANDALONE()) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_send_line(client, t_strconcat(
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "* PREAUTH [CAPABILITY "CAPABILITY_STRING"] "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Logged in as ", user, NULL));
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void main_deinit(void)
8a3d609fdd84f5938c82e8e7eeb84a24ab41b317Timo Sirainen{
8a3d609fdd84f5938c82e8e7eeb84a24ab41b317Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen which is too common at least while testing :) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (lib_signal_kill != 0 && lib_signal_kill != 2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_warning("Killed with signal %d", lib_signal_kill);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen clients_deinit();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen closelog();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint main(int argc __attr_unused__, char *argv[], char *envp[])
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#ifdef DEBUG
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (getenv("LOGGED_IN") != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd_debug_verify_leaks(3, 1024);
#endif
/* NOTE: we start rooted, so keep the code minimal until
restrict_access_by_env() is called */
lib_init();
drop_privileges();
process_title_init(argv, envp);
ioloop = io_loop_create(system_pool);
main_init();
io_loop_run(ioloop);
main_deinit();
io_loop_destroy(ioloop);
lib_deinit();
return 0;
}