Currently only the standalone applications (e.g. deliver) uses this.
--HG--
branch : HEAD
src/lib-imap/Makefile
src/lib-index/Makefile
src/lib-mail/Makefile
+src/lib-master/Makefile
src/lib-ntlm/Makefile
src/lib-otp/Makefile
src/lib-dovecot/Makefile
lib-charset \
lib-mail \
lib-imap \
+ lib-master \
lib-dict \
lib-settings
lib-ntlm \
lib-otp \
auth \
- config \
dict \
master \
login-common \
imap \
$(POP3D) \
$(DELIVER) \
+ config \
tests \
util \
plugins
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
- -I$(top_srcdir)/src/lib-auth \
-I$(top_srcdir)/src/lib-settings \
- -I$(top_srcdir)/src/lib-dict \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
- -I$(top_srcdir)/src/lib-settings \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-storage \
-I$(top_srcdir)/src/lib-storage/index \
-I$(top_srcdir)/src/lib-storage/index/raw \
- -DBINDIR=\""$(bindir)"\" \
- -DSYSCONFDIR=\""$(sysconfdir)"\" \
- -DPKG_RUNDIR=\""$(rundir)"\" \
- -DMODULEDIR=\""$(moduledir)"\"
+ -DPKG_RUNDIR=\""$(rundir)"\"
deliver_LDFLAGS = -export-dynamic
deliver_DEPENDENCIES = $(libs)
deliver_SOURCES = \
- auth-client.c \
deliver.c \
deliver-settings.c \
duplicate.c \
smtp-client.c
headers = \
- auth-client.h \
deliver.h \
deliver-settings.h \
duplicate.h \
#include <stddef.h>
#include <stdlib.h>
+static bool deliver_settings_check(void *_set, pool_t pool, const char **error_r);
+
#undef DEF
#undef DEFLIST
#define DEF(type, name) \
{ SET_DEFLIST, name, offsetof(struct deliver_settings, field), defines }
static struct setting_define deliver_setting_defines[] = {
- DEF(SET_STR, base_dir),
- DEF(SET_STR, log_path),
- DEF(SET_STR, info_log_path),
- DEF(SET_STR, log_timestamp),
- DEF(SET_STR, syslog_facility),
- DEF(SET_BOOL, version_ignore),
-
- DEF(SET_STR, mail_plugins),
- DEF(SET_STR, mail_plugin_dir),
-
- DEF(SET_STR, mail_uid),
- DEF(SET_STR, mail_gid),
- DEF(SET_STR, mail_chroot),
- DEF(SET_STR, mail_access_groups),
-
DEF(SET_STR, postmaster_address),
DEF(SET_STR, hostname),
DEF(SET_STR, sendmail_path),
DEF(SET_STR, rejection_subject),
DEF(SET_STR, rejection_reason),
- DEF(SET_STR, auth_socket_path),
DEF(SET_STR, deliver_log_format),
DEF(SET_BOOL, quota_full_tempfail),
};
static struct deliver_settings deliver_default_settings = {
- MEMBER(base_dir) PKG_RUNDIR,
- MEMBER(log_path) "",
- MEMBER(info_log_path) "",
- MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
- MEMBER(syslog_facility) "mail",
- MEMBER(version_ignore) FALSE,
-
- MEMBER(mail_plugins) "",
- MEMBER(mail_plugin_dir) MODULEDIR,
-
- MEMBER(mail_uid) "",
- MEMBER(mail_gid) "",
- MEMBER(mail_chroot) "",
- MEMBER(mail_access_groups) "",
-
MEMBER(postmaster_address) "",
MEMBER(hostname) "",
MEMBER(sendmail_path) "/usr/lib/sendmail",
MEMBER(rejection_subject) "Rejected: %s",
MEMBER(rejection_reason)
"Your message to <%t> was automatically rejected:%n%r",
- MEMBER(auth_socket_path) "auth-master",
MEMBER(deliver_log_format) "msgid=%m: %$",
MEMBER(quota_full_tempfail) FALSE
};
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
- MEMBER(struct_size) sizeof(struct deliver_settings)
+ MEMBER(struct_size) sizeof(struct deliver_settings),
+#ifdef CONFIG_BINARY
+ MEMBER(check_func) NULL
+#else
+ MEMBER(check_func) deliver_settings_check
+#endif
};
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct deliver_settings *set, const char **str)
-{
- if (*str != NULL && **str != '\0' && **str != '/') {
- *str = p_strconcat(settings_pool,
- set->base_dir, "/", *str, NULL);
- }
-}
-
-struct setting_parser_context *
-deliver_settings_read(struct deliver_settings **set_r,
- struct mail_user_settings **user_set_r)
+static bool deliver_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+ const char **error_r)
{
- static const struct setting_parser_info *roots[] = {
- &deliver_setting_parser_info,
- &mail_user_setting_parser_info
- };
- void **sets;
- struct deliver_settings *deliver_set;
- struct setting_parser_context *parser;
-
- if (settings_pool == NULL)
- settings_pool = pool_alloconly_create("deliver settings", 1024);
- else
- p_clear(settings_pool);
+ struct deliver_settings *set = _set;
- mail_storage_namespace_defines_init(settings_pool);
-
- parser = settings_parser_init_list(settings_pool,
- roots, N_ELEMENTS(roots),
- SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
- if (settings_parse_environ(parser) < 0) {
- i_fatal_status(EX_CONFIG, "Error reading configuration: %s",
- settings_parser_get_error(parser));
- }
-
- sets = settings_parser_get_list(parser);
-
- deliver_set = sets[0];
- if (*deliver_set->hostname == '\0')
- deliver_set->hostname = my_hostname;
- fix_base_path(deliver_set, &deliver_set->auth_socket_path);
-
- if (*deliver_set->postmaster_address == '\0') {
- i_fatal_status(EX_CONFIG,
- "postmaster_address setting not given");
+ if (*set->postmaster_address == '\0') {
+ *error_r = "postmaster_address setting not given";
+ return FALSE;
}
-
- *set_r = deliver_set;
- *user_set_r = sets[1];
- return parser;
-}
-
-void deliver_settings_add(struct setting_parser_context *parser,
- const ARRAY_TYPE(const_string) *extra_fields)
-{
- const char *const *str, *p, *line;
- unsigned int i, count;
-
- str = array_get(extra_fields, &count);
- for (i = 0; i < count; i++) T_BEGIN {
- p = strchr(str[i], '=');
- if (p != NULL)
- line = str[i];
- else
- line = t_strconcat(str[i], "=yes", NULL);
- if (settings_parse_line(parser, str[i]) < 0) {
- i_fatal_status(EX_CONFIG,
- "Invalid userdb input '%s': %s", str[i],
- settings_parser_get_error(parser));
- }
- } T_END;
-
+ return TRUE;
}
struct mail_user_settings;
struct deliver_settings {
- const char *base_dir;
- const char *log_path;
- const char *info_log_path;
- const char *log_timestamp;
- const char *syslog_facility;
- bool version_ignore;
-
- const char *mail_plugins;
- const char *mail_plugin_dir;
-
- const char *mail_uid;
- const char *mail_gid;
- const char *mail_chroot;
- const char *mail_access_groups;
-
- /* deliver: */
const char *postmaster_address;
const char *hostname;
const char *sendmail_path;
const char *rejection_subject;
const char *rejection_reason;
- const char *auth_socket_path;
const char *deliver_log_format;
bool quota_full_tempfail;
ARRAY_DEFINE(plugin_envs, const char *);
};
-struct setting_parser_context *
-deliver_settings_read(struct deliver_settings **set_r,
- struct mail_user_settings **user_set_r);
-void deliver_settings_add(struct setting_parser_context *parser,
- const ARRAY_TYPE(const_string) *extra_fields);
+extern struct setting_parser_info deliver_setting_parser_info;
#endif
/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
-/* This is getting pretty horrible. Especially the config file parsing.
- Dovecot v2.0 should have a config file handling process which should help
- with this.. */
-
#include "lib.h"
#include "lib-signals.h"
-#include "file-lock.h"
-#include "array.h"
#include "ioloop.h"
-#include "hostpid.h"
-#include "home-expand.h"
#include "env-util.h"
#include "fd-set-nonblock.h"
#include "istream.h"
#include "istream-seekable.h"
-#include "module-dir.h"
#include "str.h"
#include "str-sanitize.h"
#include "strescape.h"
#include "var-expand.h"
#include "rfc822-parser.h"
#include "message-address.h"
+#include "imap-utf7.h"
+#include "master-service.h"
+#include "mail-storage-service.h"
#include "mail-namespace.h"
#include "raw-storage.h"
-#include "imap-utf7.h"
-#include "settings-parser.h"
-#include "dict.h"
-#include "auth-client.h"
#include "mail-send.h"
#include "duplicate.h"
#include "mbox-from.h"
-#include "../master/syslog-util.h"
-#include "../master/syslog-util.c" /* ugly, ugly.. */
#include "deliver.h"
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <pwd.h>
-#include <syslog.h>
-#define DEFAULT_CONFIG_FILE SYSCONFDIR"/dovecot.conf"
-#define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
#define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
/* After buffer grows larger than this, create a temporary file to /tmp
NULL
};
-struct deliver_settings *deliver_set;
+const struct deliver_settings *deliver_set;
deliver_mail_func_t *deliver_mail = NULL;
bool mailbox_autosubscribe;
bool mailbox_autocreate;
static bool saved_mail = FALSE;
static char *explicit_envelope_sender = NULL;
-static struct module *modules;
-static struct ioloop *ioloop;
-
-static void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
-{
- /* warn about being killed because of some signal, except SIGINT (^C)
- which is too common at least while testing :) */
- if (si->si_signo != SIGINT) {
- i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
- si->si_signo, dec2str(si->si_pid),
- dec2str(si->si_uid),
- lib_signal_code_to_str(si->si_signo, si->si_code));
- }
- io_loop_stop(current_ioloop);
-}
+static struct master_service *service;
static const char *deliver_get_address(struct mail *mail, const char *header)
{
*status = EX_TEMPFAIL;
}
-static void open_logfile(const char *username)
-{
- const char *prefix, *log_path;
-
- prefix = t_strdup_printf("deliver(%s): ", username);
- log_path = home_expand(deliver_set->log_path);
- if (*log_path == '\0') {
- int facility;
-
- if (!syslog_facility_find(deliver_set->syslog_facility,
- &facility))
- facility = LOG_MAIL;
- i_set_failure_prefix(prefix);
- i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
- } else {
- /* log to file or stderr */
- i_set_failure_file(log_path, prefix);
- }
-
- log_path = home_expand(deliver_set->info_log_path);
- if (*log_path != '\0')
- i_set_info_file(log_path);
-
- i_set_failure_timestamp_format(deliver_set->log_timestamp);
-}
-
static void print_help(void)
{
printf(
" [-f <envelope sender>] [-m <mailbox>] [-n] [-s] [-e] [-k]\n");
}
-void deliver_env_clean(bool preserve_home)
-{
- const char *tz, *home;
-
- tz = getenv("TZ");
- if (tz != NULL)
- tz = t_strconcat("TZ=", tz, NULL);
- home = preserve_home ? getenv("HOME") : NULL;
- if (home != NULL)
- home = t_strconcat("HOME=", home, NULL);
-
- /* Note that if the original environment was set with env_put(), the
- environment strings will be invalid after env_clean(). That's why
- we t_strconcat() them above. */
- env_clean();
-
- if (tz != NULL) env_put(tz);
- if (home != NULL) env_put(home);
-}
-
-static void plugin_get_home(void)
-{
- const char *const *envs;
- unsigned int i, count;
-
- /* kludgy. this should be removed some day, but for now don't break
- existing setups that rely on it. */
- if (array_is_created(&deliver_set->plugin_envs)) {
- envs = array_get(&deliver_set->plugin_envs, &count);
- for (i = 0; i < count; i++) {
- if (strncmp(envs[i], "home=", 5) == 0) {
- env_put(t_strconcat("HOME=", envs[i]+5, NULL));
- break;
- }
- }
- }
-}
-
int main(int argc, char *argv[])
{
- const char *config_path = DEFAULT_CONFIG_FILE;
+ enum mail_storage_service_flags service_flags = 0;
const char *mailbox = "INBOX";
- const char *home, *destaddr, *user, *errstr, *path, *orig_user;
- ARRAY_TYPE(const_string) extra_fields = ARRAY_INIT;
- struct setting_parser_context *parser;
+ const char *destaddr, *user, *errstr, *path, *getopt_str;
struct mail_user *mail_user, *raw_mail_user;
struct mail_namespace *raw_ns;
struct mail_namespace_settings raw_ns_set;
struct istream *input;
struct mailbox_transaction_context *t;
struct mailbox_header_lookup_ctx *headers_ctx;
- struct mail_user_settings *user_set;
- const struct mail_storage_settings *mail_set;
struct mail *mail;
char cwd[PATH_MAX];
uid_t process_euid;
bool stderr_rejection = FALSE;
- bool keep_environment = FALSE;
- bool user_auth = FALSE;
- bool doveconf_env;
time_t mtime;
- int i, ret;
- pool_t userdb_pool = NULL;
+ int ret, c;
string_t *str;
enum mail_error error;
i_set_failure_exit_callback(failure_exit_callback);
- lib_init();
- ioloop = io_loop_create();
-
- lib_signals_init();
- lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
- lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
- lib_signals_ignore(SIGPIPE, TRUE);
- lib_signals_ignore(SIGALRM, FALSE);
+ service = master_service_init("lda", MASTER_SERVICE_FLAG_STANDALONE,
+ argc, argv);
#ifdef SIGXFSZ
lib_signals_ignore(SIGXFSZ, TRUE);
#endif
- deliver_set = i_new(struct deliver_settings, 1);
mailbox_autocreate = TRUE;
-
- destaddr = user = path = NULL;
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-a") == 0) {
+ destaddr = path = NULL;
+
+ user = getenv("USER");
+ getopt_str = t_strconcat("a:d:p:ekm:nsf:",
+ master_service_getopt_string(), NULL);
+ while ((c = getopt(argc, argv, getopt_str)) > 0) {
+ switch (c) {
+ case 'a':
/* destination address */
- i++;
- if (i == argc)
- i_fatal_status(EX_USAGE, "Missing -a argument");
- destaddr = argv[i];
- } else if (strcmp(argv[i], "-d") == 0) {
+ destaddr = optarg;
+ break;
+ case 'd':
/* destination user */
- i++;
- if (i == argc)
- i_fatal_status(EX_USAGE, "Missing -d argument");
- user = argv[i];
- user_auth = TRUE;
- } else if (strcmp(argv[i], "-p") == 0) {
+ user = optarg;
+ service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+ break;
+ case 'p':
/* input path */
- i++;
- if (i == argc)
- i_fatal_status(EX_USAGE, "Missing -p argument");
- path = argv[i];
+ path = optarg;
if (*path != '/') {
/* expand relative paths before we chdir */
if (getcwd(cwd, sizeof(cwd)) == NULL)
i_fatal("getcwd() failed: %m");
path = t_strconcat(cwd, "/", path, NULL);
}
- } else if (strcmp(argv[i], "-e") == 0) {
+ break;
+ case 'e':
stderr_rejection = TRUE;
- } else if (strcmp(argv[i], "-c") == 0) {
- /* config file path */
- i++;
- if (i == argc) {
- i_fatal_status(EX_USAGE,
- "Missing config file path argument");
- }
- config_path = argv[i];
- } else if (strcmp(argv[i], "-k") == 0) {
- keep_environment = TRUE;
- } else if (strcmp(argv[i], "-m") == 0) {
- /* destination mailbox */
- i++;
- if (i == argc)
- i_fatal_status(EX_USAGE, "Missing -m argument");
- /* Ignore -m "". This allows doing -m ${extension}
+ break;
+ case 'm':
+ /* destination mailbox.
+ Ignore -m "". This allows doing -m ${extension}
in Postfix to handle user+mailbox */
- if (*argv[i] != '\0') {
+ if (*optarg != '\0') {
str = t_str_new(256);
- if (imap_utf8_to_utf7(argv[i], str) < 0) {
+ if (imap_utf8_to_utf7(optarg, str) < 0) {
i_fatal("Mailbox name not UTF-8: %s",
mailbox);
}
mailbox = str_c(str);
}
- } else if (strcmp(argv[i], "-n") == 0) {
+ break;
+ case 'n':
mailbox_autocreate = FALSE;
- } else if (strcmp(argv[i], "-s") == 0) {
+ break;
+ case 's':
mailbox_autosubscribe = TRUE;
- } else if (strcmp(argv[i], "-f") == 0) {
+ break;
+ case 'f':
/* envelope sender address */
- i++;
- if (i == argc)
- i_fatal_status(EX_USAGE, "Missing -f argument");
explicit_envelope_sender =
- i_strdup(address_sanitize(argv[i]));
- } else if (argv[i][0] != '\0') {
- print_help();
- i_fatal_status(EX_USAGE,
- "Unknown argument: %s", argv[i]);
+ i_strdup(address_sanitize(optarg));
+ break;
+ default:
+ if (!master_service_parse_option(service, c, optarg)) {
+ print_help();
+ i_fatal_status(EX_USAGE,
+ "Unknown argument: %c", c);
+ }
+ break;
}
}
-
- doveconf_env = getenv("DOVECONF_ENV") != NULL;
- if (user == NULL)
- user = getenv("USER");
- if (!keep_environment && !doveconf_env) {
- deliver_env_clean(!user_auth);
- env_put(t_strconcat("USER=", user, NULL));
- }
- if (!doveconf_env) {
- /* currently we need to be executed via doveconf. */
-#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
- const char **conf_argv;
-
- conf_argv = i_new(const char *, 6 + (argc + 1) + 1);
- conf_argv[0] = DOVECOT_CONFIG_BIN_PATH;
- conf_argv[1] = "-s";
- conf_argv[2] = "lda";
- conf_argv[3] = "-c";
- conf_argv[4] = config_path;
- conf_argv[5] = "--exec";
- memcpy(conf_argv+6, argv, (argc+1) * sizeof(argv[0]));
- execv(conf_argv[0], (char **)conf_argv);
- i_fatal_status(EX_CONFIG, "execv(%s) failed: %m", conf_argv[0]);
+ if (optind != argc) {
+ print_help();
+ i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
}
process_euid = geteuid();
- if (user_auth)
+ if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0)
;
else if (process_euid != 0) {
/* we're non-root. get our username and possibly our home. */
struct passwd *pw;
+ const char *home;
home = getenv("HOME");
if (user != NULL && home != NULL) {
"destination user parameter (-d user) not given");
}
- mail_storage_init();
- mail_storage_register_all();
- mailbox_list_register_all();
-
- parser = deliver_settings_read(&deliver_set, &user_set);
- open_logfile(user);
-
- mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
- if (deliver_set->mail_plugins == '\0')
- modules = NULL;
- else {
- const char *version;
-
- version = deliver_set->version_ignore ? NULL : PACKAGE_VERSION;
- modules = module_dir_load(deliver_set->mail_plugin_dir,
- deliver_set->mail_plugins,
- TRUE, version);
- }
-
- if (user_auth) {
- userdb_pool = pool_alloconly_create("userdb lookup replys", 512);
- orig_user = user;
- ret = auth_client_lookup_and_restrict(deliver_set->auth_socket_path,
- mail_set->mail_debug,
- &user, process_euid,
- userdb_pool,
- &extra_fields);
- if (ret != 0)
- return ret;
-
- if (strcmp(user, orig_user) != 0) {
- /* auth lookup changed the user. */
- if (mail_set->mail_debug)
- i_info("userdb changed username to %s", user);
- i_set_failure_prefix(t_strdup_printf("deliver(%s): ",
- user));
- }
- /* if user was changed, it was allocated from userdb_pool
- which we'll free soon. */
- user = t_strdup(user);
- }
-
- if (userdb_pool != NULL) {
- settings_parse_set_expanded(parser, TRUE);
- deliver_settings_add(parser, &extra_fields);
- pool_unref(&userdb_pool);
- }
-
- home = getenv("HOME");
- if (home == NULL) {
- plugin_get_home();
- home = getenv("HOME");
- }
-
- /* If possible chdir to home directory, so that core file
- could be written in case we crash. */
- if (home != NULL) {
- if (chdir(home) < 0) {
- if (errno != ENOENT)
- i_error("chdir(%s) failed: %m", home);
- else if (mail_set->mail_debug)
- i_info("Home dir not found: %s", home);
- }
- }
-
- env_put(t_strconcat("USER=", user, NULL));
- (void)umask(0077);
-
- dict_drivers_register_builtin();
- duplicate_init(mail_set);
- mail_users_init(deliver_set->auth_socket_path, mail_set->mail_debug);
-
- module_dir_init(modules);
-
- mail_user = mail_user_alloc(user, user_set);
- mail_user_set_home(mail_user, home);
- mail_user_set_vars(mail_user, geteuid(), "deliver", NULL, NULL);
- if (mail_user_init(mail_user, &errstr) < 0)
- i_fatal("Mail user initialization failed: %s", errstr);
- if (mail_namespaces_init(mail_user, &errstr) < 0)
- i_fatal("Namespace initialization failed: %s", errstr);
+ service_flags |= MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT;
+ mail_user = mail_storage_service_init_user(service, user,
+ &deliver_setting_parser_info, service_flags);
+ deliver_set = mail_storage_service_get_settings(service);
+ duplicate_init(mail_user_set_get_storage_set(mail_user->set));
/* create a separate mail user for the internal namespace */
- raw_mail_user = mail_user_alloc(user, user_set);
+ raw_mail_user = mail_user_alloc(user, mail_user->unexpanded_set);
mail_user_set_home(raw_mail_user, "/");
if (mail_user_init(raw_mail_user, &errstr) < 0)
i_fatal("Raw user initialization failed: %s", errstr);
- settings_parser_deinit(&parser);
-
memset(&raw_ns_set, 0, sizeof(raw_ns_set));
raw_ns_set.location = "/tmp";
mail_user_unref(&mail_user);
mail_user_unref(&raw_mail_user);
-
- module_dir_unload(&modules);
- mail_storage_deinit();
- mail_users_deinit();
-
duplicate_deinit();
- dict_drivers_unregister_builtin();
- lib_signals_deinit();
-
- io_loop_destroy(&ioloop);
- lib_deinit();
+ mail_storage_service_deinit_user();
+ master_service_deinit(&service);
return EX_OK;
}
#include "mail-storage.h"
#include "deliver-settings.h"
-extern struct deliver_settings *deliver_set;
+extern const struct deliver_settings *deliver_set;
extern bool mailbox_autosubscribe;
extern bool mailbox_autocreate;
extern bool tried_default_save;
extern deliver_mail_func_t *deliver_mail;
-void deliver_env_clean(bool preserve_home);
-
/* Save a mail into given mailbox with given flags and keywords. */
int deliver_save(struct mail_namespace *namespaces,
struct mail_storage **storage_r, const char *mailbox,
#include "lib.h"
#include "deliver.h"
+#include "master-service.h"
#include "smtp-client.h"
#include <unistd.h>
if (dup2(fd, STDIN_FILENO) < 0)
i_fatal("dup2() failed: %m");
- deliver_env_clean(TRUE);
+ master_service_env_clean(TRUE);
(void)execv(sendmail_path, (void *)argv);
i_fatal("execv(%s) failed: %m", sendmail_path);
sql_drivers_register_all();
restrict_access_by_env(NULL, FALSE);
+ restrict_access_allow_coredumps(TRUE);
}
static void main_init(void)
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
- -I$(top_srcdir)/src/lib-storage \
- -DPKG_RUNDIR=\""$(rundir)"\" \
- -DMODULEDIR=\""$(moduledir)"\"
+ -I$(top_srcdir)/src/lib-storage
imap_LDFLAGS = -export-dynamic
#include <stdlib.h>
#include <unistd.h>
-static bool imap_settings_check(void *_set, pool_t pool, const char **error_r);
-
#undef DEF
#undef DEFLIST
#define DEF(type, name) \
{ SET_DEFLIST, name, offsetof(struct imap_settings, field), defines }
static struct setting_define imap_setting_defines[] = {
- DEF(SET_STR, base_dir),
- DEF(SET_STR, auth_socket_path),
-
DEF(SET_BOOL, mail_debug),
DEF(SET_BOOL, shutdown_clients),
DEF(SET_BOOL, verbose_proctitle),
- DEF(SET_STR, mail_plugins),
- DEF(SET_STR, mail_plugin_dir),
-
DEF(SET_UINT, imap_max_line_length),
DEF(SET_STR, imap_capability),
DEF(SET_STR, imap_client_workarounds),
};
static struct imap_settings imap_default_settings = {
- MEMBER(base_dir) PKG_RUNDIR,
- MEMBER(auth_socket_path) "auth-master",
-
MEMBER(mail_debug) FALSE,
MEMBER(shutdown_clients) FALSE,
MEMBER(verbose_proctitle) FALSE,
- MEMBER(mail_plugins) "",
- MEMBER(mail_plugin_dir) MODULEDIR,
-
/* RFC-2683 recommends at least 8000 bytes. Some clients however don't
break large message sets to multiple commands, so we're pretty
liberal by default. */
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
MEMBER(struct_size) sizeof(struct imap_settings),
- MEMBER(check_func) imap_settings_check
+ MEMBER(check_func) NULL
};
static pool_t settings_pool = NULL;
-static void fix_base_path(struct imap_settings *set, const char **str)
-{
- if (*str != NULL && **str != '\0' && **str != '/') {
- *str = p_strconcat(settings_pool,
- set->base_dir, "/", *str, NULL);
- }
-}
-
-/* <settings checks> */
-static bool imap_settings_check(void *_set, pool_t pool ATTR_UNUSED,
- const char **error_r)
-{
- struct imap_settings *set = _set;
-
-#ifndef CONFIG_BINARY
- fix_base_path(set, &set->auth_socket_path);
-#endif
-
- if (*set->mail_plugins != '\0' &&
- access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
- *error_r = t_strdup_printf(
- "mail_plugin_dir: access(%s) failed: %m",
- set->mail_plugin_dir);
- return FALSE;
- }
- return TRUE;
-}
-/* </settings checks> */
-
static void
parse_expand_vars(struct setting_parser_context *parser, const char *value)
{
else
p_clear(settings_pool);
- mail_storage_namespace_defines_init(settings_pool);
+ settings_parser_info_update(settings_pool,
+ mail_storage_get_dynamic_parsers());
parser = settings_parser_init_list(settings_pool,
roots, N_ELEMENTS(roots),
struct mail_user_settings;
struct imap_settings {
- const char *base_dir;
- const char *auth_socket_path;
-
bool mail_debug;
bool shutdown_clients;
bool verbose_proctitle;
- const char *mail_plugins;
- const char *mail_plugin_dir;
-
/* imap: */
unsigned int imap_max_line_length;
const char *imap_capability;
imap_settings_read(set_r, user_set_r);
/* Load the plugins before chrooting. Their init() is called later. */
- modules = *(*set_r)->mail_plugins == '\0' ? NULL :
- module_dir_load((*set_r)->mail_plugin_dir,
- (*set_r)->mail_plugins, TRUE, version);
+ modules = *(*user_set_r)->mail_plugins == '\0' ? NULL :
+ module_dir_load((*user_set_r)->mail_plugin_dir,
+ (*user_set_r)->mail_plugins, TRUE, version);
restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
restrict_access_allow_coredumps(TRUE);
log_error_callback, NULL);
}
+ module_dir_init(modules);
dict_drivers_register_builtin();
- mail_users_init(set->auth_socket_path, set->mail_debug);
+ mail_users_init(user_set->auth_socket_path, set->mail_debug);
clients_init();
commands_init();
- module_dir_init(modules);
-
user = mail_user_alloc(username, user_set);
mail_user_set_home(user, home);
if (mail_user_init(user, &error) < 0)
#ifndef AUTH_MASTER_H
#define AUTH_MASTER_H
-#define AUTH_SERVICE_INTERNAL "internal"
-
struct auth_user_reply {
uid_t uid;
gid_t gid;
../lib-mail/libmail.la \
../lib-auth/libauth.la \
../lib-charset/libcharset.la \
+ ../lib-master/libmaster.la \
../lib/liblib.la
libdovecot_la_LIBADD = \
--- /dev/null
+noinst_LTLIBRARIES = libmaster.la
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-settings \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DPKG_RUNDIR=\""$(rundir)"\"
+
+libmaster_la_SOURCES = \
+ master-service.c \
+ master-service-settings.c \
+ syslog-util.c
+
+noinst_HEADERS = \
+ master-service.h \
+ master-service-private.h \
+ master-service-settings.h \
+ syslog-util.h
--- /dev/null
+#ifndef MASTER_SERVICE_PRIVATE_H
+#define MASTER_SERVICE_PRIVATE_H
+
+#include "master-service.h"
+
+struct master_service {
+ struct ioloop *ioloop;
+
+ char *name;
+ enum master_service_flags flags;
+
+ int argc;
+ char **argv;
+
+ const char *version_string;
+ const char *config_path;
+ int syslog_facility;
+
+ pool_t set_pool;
+ const struct master_service_settings *set;
+ struct setting_parser_context *set_parser;
+
+ unsigned int keep_environment:1;
+ unsigned int log_directly:1;
+};
+
+#endif
--- /dev/null
+/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "settings-parser.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define DOVECOT_CONFIG_BIN_PATH BINDIR"/doveconf"
+
+#undef DEF
+#define DEF(type, name) \
+ { type, #name, offsetof(struct master_service_settings, name), NULL }
+
+static struct setting_define master_service_setting_defines[] = {
+ DEF(SET_STR, log_path),
+ DEF(SET_STR, info_log_path),
+ DEF(SET_STR, log_timestamp),
+ DEF(SET_STR, syslog_facility),
+ DEF(SET_BOOL, version_ignore),
+
+ SETTING_DEFINE_LIST_END
+};
+
+static struct master_service_settings master_service_default_settings = {
+ MEMBER(log_path) "",
+ MEMBER(info_log_path) "",
+ MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT,
+ MEMBER(syslog_facility) "mail",
+ MEMBER(version_ignore) FALSE
+};
+
+struct setting_parser_info master_service_setting_parser_info = {
+ MEMBER(defines) master_service_setting_defines,
+ MEMBER(defaults) &master_service_default_settings,
+
+ MEMBER(parent) NULL,
+ MEMBER(dynamic_parsers) NULL,
+
+ MEMBER(parent_offset) (size_t)-1,
+ MEMBER(type_offset) (size_t)-1,
+ MEMBER(struct_size) sizeof(struct master_service_settings)
+};
+
+static void ATTR_NORETURN
+master_service_exec_config(struct master_service *service, bool preserve_home)
+{
+ const char **conf_argv;
+
+ if (!service->keep_environment)
+ master_service_env_clean(preserve_home);
+
+ /* @UNSAFE */
+ conf_argv = t_new(const char *, 6 + (service->argc + 1) + 1);
+ conf_argv[0] = DOVECOT_CONFIG_BIN_PATH;
+ conf_argv[1] = "-s";
+ conf_argv[2] = service->name;
+ conf_argv[3] = "-c";
+ conf_argv[4] = service->config_path;
+ conf_argv[5] = "--exec";
+ memcpy(conf_argv+6, service->argv,
+ (service->argc+1) * sizeof(conf_argv[0]));
+ execv(conf_argv[0], (char **)conf_argv);
+ i_fatal("execv(%s) failed: %m", conf_argv[0]);
+}
+
+int master_service_settings_read(struct master_service *service,
+ const struct setting_parser_info *roots[],
+ const struct dynamic_settings_parser *dyn_parsers,
+ bool preserve_home, const char **error_r)
+{
+ ARRAY_DEFINE(all_roots, const struct setting_parser_info *);
+ const struct setting_parser_info *tmp_root;
+ struct setting_parser_context *parser;
+ const char *error;
+ void **sets;
+ unsigned int i;
+
+ if (getenv("DOVECONF_ENV") == NULL)
+ master_service_exec_config(service, preserve_home);
+
+ if (service->set_pool != NULL)
+ p_clear(service->set_pool);
+ else {
+ service->set_pool =
+ pool_alloconly_create("master service settings", 4096);
+ }
+
+ if (dyn_parsers != NULL)
+ settings_parser_info_update(service->set_pool, dyn_parsers);
+
+ p_array_init(&all_roots, service->set_pool, 8);
+ tmp_root = &master_service_setting_parser_info;
+ array_append(&all_roots, &tmp_root, 1);
+ for (i = 0; roots[i] != NULL; i++)
+ array_append(&all_roots, &roots[i], 1);
+
+ parser = settings_parser_init_list(service->set_pool,
+ array_idx(&all_roots, 0), array_count(&all_roots),
+ SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
+
+ if (settings_parse_environ(parser) < 0) {
+ *error_r = settings_parser_get_error(parser);
+ return -1;
+ }
+
+ if (settings_parser_check(parser, service->set_pool, &error) < 0) {
+ *error_r = t_strdup_printf("Invalid settings: %s", error);
+ return -1;
+ }
+
+ sets = settings_parser_get_list(parser);
+ service->set = sets[0];
+ service->set_parser = parser;
+
+ if (service->set->version_ignore &&
+ (service->flags & MASTER_SERVICE_FLAG_STANDALONE) != 0) {
+ /* running standalone. we want to ignore plugin versions. */
+ service->version_string = NULL;
+ }
+
+ /* if we change any settings afterwards, they're in expanded form.
+ especially all settings from userdb are already expanded. */
+ settings_parse_set_expanded(service->set_parser, TRUE);
+ return 0;
+}
+
+const struct master_service_settings *
+master_service_settings_get(struct master_service *service)
+{
+ void **sets;
+
+ sets = settings_parser_get_list(service->set_parser);
+ return sets[0];
+}
+
+void **master_service_settings_get_others(struct master_service *service)
+{
+ return settings_parser_get_list(service->set_parser) + 1;
+}
--- /dev/null
+#ifndef MASTER_SERVICE_SETTINGS_H
+#define MASTER_SERVICE_SETTINGS_H
+
+struct setting_parser_info;
+struct dynamic_settings_parser;
+
+struct master_service_settings {
+ const char *log_path;
+ const char *info_log_path;
+ const char *log_timestamp;
+ const char *syslog_facility;
+ bool version_ignore;
+};
+
+int master_service_settings_read(struct master_service *service,
+ const struct setting_parser_info *roots[],
+ const struct dynamic_settings_parser *dyn_parsers,
+ bool preserve_home, const char **error_r);
+const struct master_service_settings *
+master_service_settings_get(struct master_service *service);
+void **master_service_settings_get_others(struct master_service *service);
+
+#endif
--- /dev/null
+/* Copyright (C) 2005-2009 Timo Sirainen */
+
+#include "lib.h"
+#include "lib-signals.h"
+#include "ioloop.h"
+#include "env-util.h"
+#include "home-expand.h"
+#include "restrict-access.h"
+#include "fd-close-on-exec.h"
+#include "syslog-util.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#define DEFAULT_CONFIG_FILE_PATH SYSCONFDIR"/dovecot.conf"
+
+/* getenv(MASTER_CONFIG_FILE_ENV) provides path to configuration file/socket */
+#define MASTER_CONFIG_FILE_ENV "CONFIG_FILE"
+
+/* getenv(MASTER_DOVECOT_VERSION_ENV) provides master's version number */
+#define MASTER_DOVECOT_VERSION_ENV "DOVECOT_VERSION"
+
+const char *master_service_getopt_string(void)
+{
+ return "c:Lk";
+}
+
+static void sig_die(const siginfo_t *si, void *context)
+{
+ struct master_service *service = context;
+
+ /* warn about being killed because of some signal, except SIGINT (^C)
+ which is too common at least while testing :) */
+ if (si->si_signo != SIGINT) {
+ i_warning("Killed with signal %d (by pid=%s uid=%s code=%s)",
+ si->si_signo, dec2str(si->si_pid),
+ dec2str(si->si_uid),
+ lib_signal_code_to_str(si->si_signo, si->si_code));
+ }
+ io_loop_stop(service->ioloop);
+}
+
+static void master_service_verify_version(struct master_service *service)
+{
+ if (service->version_string != NULL &&
+ strcmp(service->version_string, PACKAGE_VERSION) != 0) {
+ i_fatal("Dovecot version mismatch: "
+ "Master is v%s, %s is v"PACKAGE_VERSION" "
+ "(if you don't care, set version_ignore=yes)",
+ service->name, service->version_string);
+ }
+}
+
+struct master_service *
+master_service_init(const char *name, enum master_service_flags flags,
+ int argc, char *argv[])
+{
+ struct master_service *service;
+
+ i_assert(name != NULL);
+
+ /* NOTE: we start rooted, so keep the code minimal until
+ restrict_access_by_env() is called */
+ lib_init();
+ /* Set a logging prefix temporarily. This will be ignored once the log
+ is properly initialized */
+ i_set_failure_prefix(t_strdup_printf("%s(init): ", name));
+
+ if (getenv("LOG_TO_MASTER") == NULL)
+ flags |= MASTER_SERVICE_FLAG_STANDALONE;
+
+ service = i_new(struct master_service, 1);
+ service->argc = argc;
+ service->argv = argv;
+ service->name = i_strdup(name);
+ service->flags = flags;
+ service->ioloop = io_loop_create();
+ service->config_path = getenv(MASTER_CONFIG_FILE_ENV);
+ if (service->config_path == NULL)
+ service->config_path = DEFAULT_CONFIG_FILE_PATH;
+
+ if ((flags & MASTER_SERVICE_FLAG_STANDALONE) == 0)
+ service->version_string = getenv(MASTER_DOVECOT_VERSION_ENV);
+ else
+ service->version_string = PACKAGE_VERSION;
+
+ /* set up some kind of logging until we know exactly how and where
+ we want to log */
+ if (getenv("LOG_TO_MASTER") != NULL)
+ i_set_failure_internal();
+ if (getenv("USER") != NULL) {
+ i_set_failure_prefix(t_strdup_printf("%s(%s): ",
+ name, getenv("USER")));
+ } else {
+ i_set_failure_prefix(t_strdup_printf("%s: ", name));
+ }
+
+ /* set default signal handlers */
+ lib_signals_init();
+ lib_signals_ignore(SIGPIPE, TRUE);
+ lib_signals_ignore(SIGALRM, FALSE);
+ lib_signals_set_handler(SIGINT, TRUE, sig_die, service);
+ lib_signals_set_handler(SIGTERM, TRUE, sig_die, service);
+
+ master_service_verify_version(service);
+ return service;
+}
+
+void master_service_init_log(struct master_service *service, const char *prefix)
+{
+ const char *path;
+
+ if (getenv("LOG_TO_MASTER") != NULL && !service->log_directly) {
+ /* logging via master process */
+ i_set_failure_internal();
+ i_set_failure_prefix(prefix);
+ return;
+ }
+
+ if (*service->set->log_path == '\0') {
+ /* log to syslog */
+ int facility;
+
+ if (!syslog_facility_find(service->set->syslog_facility,
+ &facility))
+ facility = LOG_MAIL;
+ i_set_failure_syslog("dovecot", LOG_NDELAY, facility);
+ i_set_failure_prefix(prefix);
+ } else {
+ /* log to file or stderr */
+ path = home_expand(service->set->log_path);
+ i_set_failure_file(path, prefix);
+ }
+
+ path = home_expand(service->set->info_log_path);
+ if (*path != '\0')
+ i_set_info_file(path);
+ i_set_failure_timestamp_format(service->set->log_timestamp);
+}
+
+bool master_service_parse_option(struct master_service *service,
+ int opt, const char *arg)
+{
+ switch (opt) {
+ case 'c':
+ service->config_path = arg;
+ break;
+ case 'k':
+ service->keep_environment = TRUE;
+ break;
+ case 'L':
+ service->log_directly = TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void master_service_env_clean(bool preserve_home)
+{
+ const char *user, *tz, *home;
+
+ user = getenv("USER");
+ if (user != NULL)
+ user = t_strconcat("USER=", user, NULL);
+ tz = getenv("TZ");
+ if (tz != NULL)
+ tz = t_strconcat("TZ=", tz, NULL);
+ home = preserve_home ? getenv("HOME") : NULL;
+ if (home != NULL)
+ home = t_strconcat("HOME=", home, NULL);
+
+ /* Note that if the original environment was set with env_put(), the
+ environment strings will be invalid after env_clean(). That's why
+ we t_strconcat() them above. */
+ env_clean();
+
+ if (user != NULL) env_put(user);
+ if (tz != NULL) env_put(tz);
+ if (home != NULL) env_put(home);
+}
+
+const char *master_service_get_config_path(struct master_service *service)
+{
+ return service->config_path;
+}
+
+const char *master_service_get_version_string(struct master_service *service)
+{
+ return service->version_string;
+}
+
+void master_service_run(struct master_service *service)
+{
+ io_loop_run(service->ioloop);
+}
+
+void master_service_stop(struct master_service *service)
+{
+ io_loop_stop(service->ioloop);
+}
+
+void master_service_deinit(struct master_service **_service)
+{
+ struct master_service *service = *_service;
+
+ *_service = NULL;
+ lib_signals_deinit();
+ io_loop_destroy(&service->ioloop);
+
+ i_free(service->name);
+ i_free(service);
+
+ lib_deinit();
+}
--- /dev/null
+#ifndef MASTER_SERVICE_H
+#define MASTER_SERVICE_H
+
+#include "network.h"
+
+enum master_service_flags {
+ /* stdin/stdout already contains a client which we want to serve */
+ MASTER_SERVICE_FLAG_STD_CLIENT = 0x01,
+ /* this process is currently running standalone without a master */
+ MASTER_SERVICE_FLAG_STANDALONE = 0x02
+};
+
+struct master_service;
+
+const char *master_service_getopt_string(void);
+
+/* Start service initialization. */
+struct master_service *
+master_service_init(const char *name, enum master_service_flags flags,
+ int argc, char *argv[]);
+/* Parser command line option. Returns TRUE if processed. */
+bool master_service_parse_option(struct master_service *service,
+ int opt, const char *arg);
+
+/* Clean environment from everything except TZ, USER and optionally HOME. */
+void master_service_env_clean(bool preserve_home);
+
+/* Initialize logging. */
+void master_service_init_log(struct master_service *service,
+ const char *prefix);
+
+/* Returns configuration file path. */
+const char *master_service_get_config_path(struct master_service *service);
+/* Returns PACKAGE_VERSION or NULL if version_ignore=yes. This function is
+ useful mostly as parameter to module_dir_load(). */
+const char *master_service_get_version_string(struct master_service *service);
+
+/* Start the service. Blocks until finished */
+void master_service_run(struct master_service *service);
+/* Stop a running service. */
+void master_service_stop(struct master_service *service);
+
+/* Deinitialize the service. */
+void master_service_deinit(struct master_service **service);
+
+#endif
--- /dev/null
+/* Copyright (c) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "syslog-util.h"
+#include <syslog.h>
+
+struct syslog_facility_list syslog_facilities[] = {
+#ifdef LOG_AUTH
+ { "auth", LOG_AUTH },
+#endif
+#ifdef LOG_AUTHPRIV
+ { "authpriv", LOG_AUTHPRIV },
+#endif
+#ifdef LOG_CRON
+ { "cron", LOG_CRON },
+#endif
+#ifdef LOG_DAEMON
+ { "daemon", LOG_DAEMON },
+#endif
+#ifdef LOG_FTP
+ { "ftp", LOG_FTP },
+#endif
+#ifdef LOG_KERN
+ { "kern", LOG_KERN },
+#endif
+#ifdef LOG_LPR
+ { "lpr", LOG_LPR },
+#endif
+#ifdef LOG_MAIL
+ { "mail", LOG_MAIL },
+#endif
+#ifdef LOG_NEWS
+ { "news", LOG_NEWS },
+#endif
+#ifdef LOG_SYSLOG
+ { "syslog", LOG_SYSLOG },
+#endif
+#ifdef LOG_UUCP
+ { "uucp", LOG_UUCP },
+#endif
+ { "user", LOG_USER },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+
+ { NULL, 0 }
+};
+
+bool syslog_facility_find(const char *name, int *facility_r)
+{
+ int i;
+
+ for (i = 0; syslog_facilities[i].name != NULL; i++) {
+ if (strcmp(syslog_facilities[i].name, name) == 0) {
+ *facility_r = syslog_facilities[i].facility;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
--- /dev/null
+#ifndef SYSLOG_UTIL_H
+#define SYSLOG_UTIL_H
+
+struct syslog_facility_list {
+ const char *name;
+ int facility;
+};
+
+extern struct syslog_facility_list syslog_facilities[];
+
+/* Returns TRUE if found. */
+bool syslog_facility_find(const char *name, int *facility_r);
+
+#endif
}
static void
-info_update_real(pool_t pool, struct setting_parser_info *parent,
- const struct dynamic_settings_parser *parsers)
+info_update_real(pool_t pool, const struct dynamic_settings_parser *parsers)
{
/* @UNSAFE */
+ struct setting_parser_info *parent;
ARRAY_DEFINE(defines, struct setting_define);
ARRAY_TYPE(dynamic_settings_parser) dynamic_parsers;
struct dynamic_settings_parser new_parser;
unsigned int i, j;
size_t offset, new_struct_size;
+ parent = parsers[0].info->parent;
+
t_array_init(&defines, 128);
/* add existing defines */
for (j = 0; parent->defines[j].key != NULL; j++)
parent->struct_size = new_struct_size;
}
-void
-settings_parser_info_update(pool_t pool, struct setting_parser_info *parent,
- const struct dynamic_settings_parser *parsers)
+void settings_parser_info_update(pool_t pool,
+ const struct dynamic_settings_parser *parsers)
{
- T_BEGIN {
- info_update_real(pool, parent, parsers);
+ if (parsers[0].name != NULL) T_BEGIN {
+ info_update_real(pool, parsers);
} T_END;
}
void *settings_dup(const struct setting_parser_info *info,
const void *set, pool_t pool);
/* parsers is a name=NULL -terminated list. The parsers are appended as
- dynamic_settings_list structures to parent. The new structures are allocated
- from the given pool. */
-void
-settings_parser_info_update(pool_t pool, struct setting_parser_info *parent,
- const struct dynamic_settings_parser *parsers);
+ dynamic_settings_list structures to their parent. All must have the same
+ parent. The new structures are allocated from the given pool. */
+void settings_parser_info_update(pool_t pool,
+ const struct dynamic_settings_parser *parsers);
/* Return pointer to beginning of settings for given name, or NULL if there is
no such registered name. */
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
- -DMODULEDIR=\""$(moduledir)"\" \
$(SQL_CFLAGS)
dist_sources = \
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-dict \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
- -DPKG_RUNDIR=\""$(rundir)"\"
+ -DPKG_RUNDIR=\""$(rundir)"\" \
+ -DMODULEDIR=\""$(moduledir)"\"
libdovecot_storage_la_SOURCES = \
mail.c \
mail-search.c \
mail-search-build.c \
mail-storage.c \
+ mail-storage-service.c \
mail-storage-settings.c \
mail-user.c \
mailbox-list.c \
mail-thread.h \
mail-storage.h \
mail-storage-private.h \
+ mail-storage-service.h \
mail-storage-settings.h \
mail-user.h \
mailbox-list.h \
namespaces = NULL; ns_p = &namespaces;
- mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+ mail_set = mail_user_set_get_storage_set(user->set);
if (array_is_created(&user->set->namespaces))
ns_set = array_get(&user->set->namespaces, &count);
else {
ns->prefix = i_strdup("");
ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX |
NAMESPACE_FLAG_SUBSCRIPTIONS;
- ns->mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+ ns->mail_set = mail_user_set_get_storage_set(user->set);
user->namespaces = ns;
return ns;
}
--- /dev/null
+/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "dict.h"
+#include "module-dir.h"
+#include "restrict-access.h"
+#include "settings-parser.h"
+#include "auth-master.h"
+#include "master-service-private.h"
+#include "master-service-settings.h"
+#include "mail-user.h"
+#include "mail-namespace.h"
+#include "mail-storage.h"
+#include "mail-storage-service.h"
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+
+struct mail_storage_service_multi_ctx {
+ struct master_service *service;
+ enum mail_storage_service_flags flags;
+
+ unsigned int modules_initialized:1;
+};
+
+static struct module *modules = NULL;
+
+static void
+master_service_set(struct master_service *service,
+ const char *key, const char *value)
+{
+ const char *str;
+
+ str = t_strconcat(key, "=", value, NULL);
+ if (settings_parse_line(service->set_parser, str) < 0) {
+ i_fatal("Invalid userdb input '%s': %s", str,
+ settings_parser_get_error(service->set_parser));
+ }
+}
+
+static bool validate_chroot(const struct mail_user_settings *user_set,
+ const char *dir)
+{
+ const char *const *chroot_dirs;
+
+ if (*dir == '\0')
+ return FALSE;
+
+ if (*user_set->valid_chroot_dirs == '\0')
+ return FALSE;
+
+ chroot_dirs = t_strsplit(user_set->valid_chroot_dirs, ":");
+ while (*chroot_dirs != NULL) {
+ if (**chroot_dirs != '\0' &&
+ strncmp(dir, *chroot_dirs, strlen(*chroot_dirs)) == 0)
+ return TRUE;
+ chroot_dirs++;
+ }
+ return FALSE;
+}
+
+static int
+user_reply_handle(struct master_service *service,
+ const struct mail_user_settings *user_set,
+ const struct auth_user_reply *reply,
+ const char **system_groups_user_r, const char **error_r)
+{
+ const char *const *str, *p, *line;
+ unsigned int i, count;
+ int ret = 0;
+
+ *system_groups_user_r = NULL;
+
+ if (reply->uid != (uid_t)-1) {
+ if (reply->uid == 0) {
+ *error_r = "userdb returned 0 as uid";
+ return -1;
+ }
+ master_service_set(service, "mail_uid", dec2str(reply->uid));
+ }
+ if (reply->gid != (uid_t)-1)
+ master_service_set(service, "mail_gid", dec2str(reply->gid));
+
+ if (reply->home != NULL)
+ master_service_set(service, "mail_home", reply->home);
+
+ if (reply->chroot != NULL) {
+ if (!validate_chroot(user_set, reply->chroot)) {
+ *error_r = t_strdup_printf(
+ "userdb returned invalid chroot directory: %s "
+ "(see valid_chroot_dirs setting)",
+ reply->chroot);
+ return -1;
+ }
+ master_service_set(service, "mail_chroot", reply->chroot);
+ }
+
+ str = array_get(&reply->extra_fields, &count);
+ for (i = 0; i < count && ret == 0; i++) T_BEGIN {
+ line = str[i];
+ if (strncmp(line, "system_groups_user=", 19) == 0) {
+ *system_groups_user_r = line + 19;
+ continue;
+ }
+ if (strncmp(line, "mail=", 5) == 0)
+ line = t_strconcat("mail_location=", line + 5, NULL);
+ else if ((p = strchr(str[i], '=')) == NULL)
+ line = t_strconcat(str[i], "=yes", NULL);
+ else
+ line = str[i];
+ ret = settings_parse_line(service->set_parser, line);
+ } T_END;
+
+ if (ret < 0) {
+ *error_r = t_strdup_printf("Invalid userdb input '%s': %s",
+ str[i], settings_parser_get_error(service->set_parser));
+ }
+ return ret;
+}
+
+static int
+service_auth_userdb_lookup(struct master_service *service, bool debug,
+ const struct mail_user_settings *user_set,
+ const char **user, const char **system_groups_user_r,
+ const char **error_r)
+{
+ struct auth_master_connection *conn;
+ struct auth_user_reply reply;
+ const char *system_groups_user, *orig_user = *user;
+ unsigned int len;
+ pool_t pool;
+ int ret;
+
+ pool = pool_alloconly_create("userdb lookup", 1024);
+ conn = auth_master_init(user_set->auth_socket_path, debug);
+ ret = auth_master_user_lookup(conn, *user, service->name,
+ pool, &reply);
+ if (ret > 0) {
+ len = reply.chroot == NULL ? 0 : strlen(reply.chroot);
+
+ *user = t_strdup(reply.user);
+ if (user_reply_handle(service, user_set, &reply,
+ &system_groups_user, error_r) < 0)
+ ret = -1;
+ *system_groups_user_r = t_strdup(system_groups_user);
+ } else {
+ if (ret == 0)
+ *error_r = "unknown user";
+ else
+ *error_r = "userdb lookup failed";
+ *system_groups_user_r = NULL;
+ }
+
+ if (ret > 0 && strcmp(*user, orig_user) != 0) {
+ if (mail_user_set_get_storage_set(user_set)->mail_debug)
+ i_info("changed username to %s", *user);
+ i_set_failure_prefix(t_strdup_printf("%s(%s): ", service->name,
+ *user));
+ }
+
+ auth_master_deinit(&conn);
+ pool_unref(&pool);
+ return ret;
+}
+
+static bool parse_uid(const char *str, uid_t *uid_r)
+{
+ struct passwd *pw;
+ char *p;
+
+ if (*str >= '0' && *str <= '9') {
+ *uid_r = (uid_t)strtoul(str, &p, 10);
+ if (*p == '\0')
+ return TRUE;
+ }
+
+ pw = getpwnam(str);
+ if (pw == NULL)
+ return FALSE;
+
+ *uid_r = pw->pw_uid;
+ return TRUE;
+}
+
+static bool parse_gid(const char *str, gid_t *gid_r)
+{
+ struct group *gr;
+ char *p;
+
+ if (*str >= '0' && *str <= '9') {
+ *gid_r = (gid_t)strtoul(str, &p, 10);
+ if (*p == '\0')
+ return TRUE;
+ }
+
+ gr = getgrnam(str);
+ if (gr == NULL)
+ return FALSE;
+
+ *gid_r = gr->gr_gid;
+ return TRUE;
+}
+
+static void
+service_drop_privileges(const struct mail_user_settings *set,
+ const char *system_groups_user,
+ bool disallow_root, bool keep_setuid_root)
+{
+ struct restrict_access_settings rset;
+ uid_t current_euid, setuid_uid = 0;
+
+ current_euid = geteuid();
+ restrict_access_init(&rset);
+ if (*set->mail_uid != '\0') {
+ if (!parse_uid(set->mail_uid, &rset.uid))
+ i_fatal("Unknown mail_uid user: %s", set->mail_uid);
+ if (rset.uid < (uid_t)set->first_valid_uid ||
+ (set->last_valid_uid != 0 &&
+ rset.uid > (uid_t)set->last_valid_uid)) {
+ i_fatal("Mail access for users with UID %s "
+ "not permitted (see first_valid_uid in config file).",
+ dec2str(rset.uid));
+ }
+ }
+ if (*set->mail_gid != '\0') {
+ if (!parse_gid(set->mail_gid, &rset.gid))
+ i_fatal("Unknown mail_gid group: %s", set->mail_gid);
+ if (rset.gid < (gid_t)set->first_valid_gid ||
+ (set->last_valid_gid != 0 &&
+ rset.gid > (gid_t)set->last_valid_gid)) {
+ i_fatal("Mail access for users with GID %s "
+ "not permitted (see first_valid_gid in config file).",
+ dec2str(rset.gid));
+ }
+ }
+ if (*set->mail_privileged_group != '\0') {
+ if (!parse_uid(set->mail_privileged_group, &rset.privileged_gid))
+ i_fatal("Unknown mail_gid group: %s", set->mail_gid);
+ }
+ if (*set->mail_access_groups != '\0')
+ rset.extra_groups = set->mail_access_groups;
+
+ rset.first_valid_gid = set->first_valid_gid;
+ rset.last_valid_gid = set->last_valid_gid;
+ /* we can't chroot if we want to switch between users. there's not
+ much point either (from security point of view) */
+ rset.chroot_dir = *set->mail_chroot == '\0' || keep_setuid_root ?
+ NULL : set->mail_chroot;
+ rset.system_groups_user = system_groups_user;
+
+ if (disallow_root &&
+ (rset.uid == 0 || (rset.uid == (uid_t)-1 && current_euid == 0)))
+ i_fatal("Mail access not allowed for root");
+
+ if (keep_setuid_root && current_euid != rset.uid) {
+ if (current_euid != 0) {
+ /* we're changing the UID, switch back to root first */
+ if (seteuid(0) < 0)
+ i_fatal("seteuid(0) failed: %m");
+ }
+ setuid_uid = rset.uid;
+ rset.uid = (uid_t)-1;
+ }
+ restrict_access(&rset, *set->mail_home == '\0' ? NULL : set->mail_home,
+ disallow_root);
+ if (keep_setuid_root) {
+ if (seteuid(setuid_uid) < 0)
+ i_fatal("seteuid(%s) failed: %m", dec2str(setuid_uid));
+ }
+}
+
+static void
+mail_storage_service_init_settings(struct master_service *service,
+ const struct setting_parser_info *set_root,
+ bool preserve_home)
+{
+ const struct setting_parser_info *set_roots[3];
+ const char *error;
+
+ (void)umask(0077);
+
+ mail_storage_init();
+ mail_storage_register_all();
+ mailbox_list_register_all();
+
+ set_roots[0] = &mail_user_setting_parser_info;
+ set_roots[1] = set_root;
+ set_roots[2] = NULL;
+
+ /* read settings after registering storages so they can have their
+ own setting definitions too */
+ if (master_service_settings_read(service, set_roots,
+ mail_storage_get_dynamic_parsers(),
+ preserve_home, &error) < 0)
+ i_fatal("Error reading configuration: %s", error);
+}
+
+static int
+mail_storage_service_init_post(struct master_service *service, const char *user,
+ const struct mail_user_settings *user_set,
+ struct mail_user **mail_user_r,
+ const char **error_r)
+{
+ const struct mail_storage_settings *mail_set;
+ struct mail_user *mail_user;
+ const char *home;
+
+ mail_set = mail_user_set_get_storage_set(user_set);
+
+ /* If possible chdir to home directory, so that core file
+ could be written in case we crash. */
+ home = user_set->mail_home;
+ if (*home != '\0') {
+ if (chdir(home) < 0) {
+ if (errno != ENOENT)
+ i_error("chdir(%s) failed: %m", home);
+ else if (mail_set->mail_debug)
+ i_info("Home dir not found: %s", home);
+ }
+ }
+
+ mail_user = mail_user_alloc(user, user_set);
+ if (*home != '\0')
+ mail_user_set_home(mail_user, home);
+ mail_user_set_vars(mail_user, geteuid(), service->name, NULL, NULL);
+ if (mail_user_init(mail_user, error_r) < 0 ||
+ mail_namespaces_init(mail_user, error_r) < 0) {
+ *error_r = t_strdup(*error_r);
+ mail_user_unref(&mail_user);
+ return -1;
+ }
+ *mail_user_r = mail_user;
+ return 0;
+}
+
+struct mail_user *
+mail_storage_service_init_user(struct master_service *service, const char *user,
+ const struct setting_parser_info *set_root,
+ enum mail_storage_service_flags flags)
+{
+ const struct master_service_settings *set;
+ const struct mail_user_settings *user_set;
+ const struct mail_storage_settings *mail_set;
+ struct mail_user *mail_user;
+ void **sets;
+ const char *orig_user, *home, *system_groups_user, *error;
+ unsigned int len;
+ bool userdb_lookup;
+
+ userdb_lookup = (flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0;
+ mail_storage_service_init_settings(service, set_root, !userdb_lookup);
+
+ /* now that we've read settings, we can set up logging */
+ master_service_init_log(service,
+ t_strdup_printf("%s(%s): ", service->name, user));
+
+ set = master_service_settings_get(service);
+ sets = master_service_settings_get_others(service);
+ user_set = sets[0];
+ mail_set = mail_user_set_get_storage_set(user_set);
+
+ if (userdb_lookup) {
+ /* userdb lookup may change settings, do it as soon as
+ possible. */
+ orig_user = user;
+ if (service_auth_userdb_lookup(service, mail_set->mail_debug,
+ user_set, &user,
+ &system_groups_user,
+ &error) <= 0) {
+ i_fatal("%s", error);
+ }
+ } else {
+ home = getenv("HOME");
+ system_groups_user = NULL;
+ if (*user_set->mail_home == '\0' && home != NULL)
+ master_service_set(service, "mail_home", home);
+ }
+ home = user_set->mail_home;
+
+ len = strlen(user_set->mail_chroot);
+ if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
+ strncmp(home, user_set->mail_chroot, len - 2) == 0) {
+ /* If chroot ends with "/.", strip chroot dir from home dir */
+ home += len - 2;
+ master_service_set(service, "mail_home", home);
+ }
+
+ modules = *user_set->mail_plugins == '\0' ? NULL :
+ module_dir_load(user_set->mail_plugin_dir,
+ user_set->mail_plugins, TRUE,
+ master_service_get_version_string(service));
+
+ service_drop_privileges(user_set, system_groups_user,
+ (flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, FALSE);
+ /* privileges are now dropped */
+
+ dict_drivers_register_builtin();
+ module_dir_init(modules);
+ mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
+ if (mail_storage_service_init_post(service, user, user_set,
+ &mail_user, &error) < 0)
+ i_fatal("%s", error);
+ return mail_user;
+}
+
+void mail_storage_service_deinit_user(void)
+{
+ module_dir_unload(&modules);
+ mail_storage_deinit();
+ mail_users_deinit();
+ dict_drivers_unregister_builtin();
+}
+
+struct mail_storage_service_multi_ctx *
+mail_storage_service_multi_init(struct master_service *service,
+ const struct setting_parser_info *set_root,
+ enum mail_storage_service_flags flags)
+{
+ struct mail_storage_service_multi_ctx *ctx;
+ const struct master_service_settings *set;
+ const struct mail_user_settings *user_set;
+ const struct mail_storage_settings *mail_set;
+ void **sets;
+
+ ctx = i_new(struct mail_storage_service_multi_ctx, 1);
+ ctx->service = service;
+ ctx->flags = flags;
+
+ mail_storage_service_init_settings(service, set_root, FALSE);
+
+ /* do all the global initialization. delay initializing plugins until
+ we drop privileges the first time. */
+ master_service_init_log(service,
+ t_strdup_printf("%s: ", service->name));
+
+ set = master_service_settings_get(service);
+ sets = master_service_settings_get_others(service);
+ user_set = sets[0];
+ mail_set = mail_user_set_get_storage_set(user_set);
+
+ modules = *user_set->mail_plugins == '\0' ? NULL :
+ module_dir_load(user_set->mail_plugin_dir,
+ user_set->mail_plugins, TRUE,
+ master_service_get_version_string(service));
+
+ dict_drivers_register_builtin();
+ mail_users_init(user_set->auth_socket_path, mail_set->mail_debug);
+ return ctx;
+}
+
+int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
+ const char *user,
+ struct mail_user **mail_user_r,
+ const char **error_r)
+{
+ const struct mail_user_settings *user_set;
+ const struct mail_storage_settings *mail_set;
+ const char *orig_user, *system_groups_user;
+ void **sets;
+ unsigned int len;
+ int ret;
+
+ sets = master_service_settings_get_others(ctx->service);
+ user_set = sets[0];
+ mail_set = mail_user_set_get_storage_set(user_set);
+
+ if ((ctx->flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
+ orig_user = user;
+ ret = service_auth_userdb_lookup(ctx->service,
+ mail_set->mail_debug,
+ user_set, &user,
+ &system_groups_user,
+ error_r);
+ if (ret <= 0)
+ return ret;
+ } else {
+ system_groups_user = NULL;
+ }
+
+ service_drop_privileges(user_set, system_groups_user,
+ (ctx->flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0, TRUE);
+
+ if (!ctx->modules_initialized) {
+ /* privileges dropped for the first time. initialize the
+ modules now to avoid code running as root. */
+ module_dir_init(modules);
+ ctx->modules_initialized = TRUE;
+ }
+
+ /* we couldn't do chrooting, so if chrooting was enabled fix
+ the home directory */
+ len = strlen(user_set->mail_chroot);
+ if (len > 2 && strcmp(user_set->mail_chroot + len - 2, "/.") == 0 &&
+ strncmp(user_set->mail_home, user_set->mail_chroot, len - 2) == 0) {
+ /* home dir already contains the chroot dir */
+ } else if (len > 0) {
+ master_service_set(ctx->service, "mail_home",
+ t_strconcat(user_set->mail_chroot, "/",
+ user_set->mail_home, NULL));
+ }
+ if (mail_storage_service_init_post(ctx->service, user,
+ user_set, mail_user_r, error_r) < 0)
+ return -1;
+ return 1;
+}
+
+void mail_storage_service_multi_deinit(struct mail_storage_service_multi_ctx **_ctx)
+{
+ struct mail_storage_service_multi_ctx *ctx = *_ctx;
+
+ *_ctx = NULL;
+ i_free(ctx);
+ mail_storage_service_deinit_user();
+}
+
+void *mail_storage_service_get_settings(struct master_service *service)
+{
+ void **sets;
+
+ sets = master_service_settings_get_others(service);
+ return sets[1];
+}
--- /dev/null
+#ifndef MAIL_STORAGE_SERVICE_H
+#define MAIL_STORAGE_SERVICE_H
+
+enum mail_storage_service_flags {
+ MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT = 0x01,
+ MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP = 0x02
+};
+
+struct setting_parser_info;
+
+struct mail_user *
+mail_storage_service_init_user(struct master_service *service, const char *user,
+ const struct setting_parser_info *set_root,
+ enum mail_storage_service_flags flags);
+void mail_storage_service_deinit_user(void);
+
+struct mail_storage_service_multi_ctx *
+mail_storage_service_multi_init(struct master_service *service,
+ const struct setting_parser_info *set_root,
+ enum mail_storage_service_flags flags);
+/* Returns 1 if ok, 0 if user wasn't found, -1 if error. */
+int mail_storage_service_multi_next(struct mail_storage_service_multi_ctx *ctx,
+ const char *user,
+ struct mail_user **mail_user_r,
+ const char **error_r);
+void mail_storage_service_multi_deinit(struct mail_storage_service_multi_ctx **ctx);
+
+/* Return the settings pointed to by set_root parameter in _init() */
+void *mail_storage_service_get_settings(struct master_service *service);
+
+#endif
#include <stddef.h>
+#define MAIL_STORAGE_SET_DRIVER_NAME "MAIL"
+
static bool mail_storage_settings_check(void *_set, pool_t pool, const char **error_r);
static bool namespace_settings_check(void *_set, pool_t pool, const char **error_r);
+static bool mail_user_settings_check(void *_set, pool_t pool, const char **error_r);
#undef DEF
#define DEF(type, name) \
offsetof(struct mail_user_settings, field), defines }
static struct setting_define mail_user_setting_defines[] = {
+ DEF(SET_STR, base_dir),
+ DEF(SET_STR, auth_socket_path),
+
+ DEF(SET_STR, mail_uid),
+ DEF(SET_STR, mail_gid),
+ DEF(SET_STR_VARS, mail_home),
+ DEF(SET_STR, mail_chroot),
+ DEF(SET_STR, mail_access_groups),
+ DEF(SET_STR, mail_privileged_group),
+ DEF(SET_STR, valid_chroot_dirs),
+
+ DEF(SET_UINT, first_valid_uid),
+ DEF(SET_UINT, last_valid_uid),
+ DEF(SET_UINT, first_valid_gid),
+ DEF(SET_UINT, last_valid_gid),
+
+ DEF(SET_STR, mail_plugins),
+ DEF(SET_STR, mail_plugin_dir),
+
DEFLIST(namespaces, "namespace", &mail_namespace_setting_parser_info),
{ SET_STRLIST, "plugin", offsetof(struct mail_user_settings, plugin_envs), NULL },
};
static struct mail_user_settings mail_user_default_settings = {
+ MEMBER(base_dir) PKG_RUNDIR,
+ MEMBER(auth_socket_path) "auth-master",
+
+ MEMBER(mail_uid) "",
+ MEMBER(mail_gid) "",
+ MEMBER(mail_home) "",
+ MEMBER(mail_chroot) "",
+ MEMBER(mail_access_groups) "",
+ MEMBER(mail_privileged_group) "",
+ MEMBER(valid_chroot_dirs) "",
+
+ MEMBER(first_valid_uid) 500,
+ MEMBER(last_valid_uid) 0,
+ MEMBER(first_valid_gid) 1,
+ MEMBER(last_valid_gid) 0,
+
+ MEMBER(mail_plugins) "",
+ MEMBER(mail_plugin_dir) MODULEDIR,
+
MEMBER(namespaces) ARRAY_INIT,
MEMBER(plugin_envs) ARRAY_INIT
};
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
- MEMBER(struct_size) sizeof(struct mail_user_settings)
+ MEMBER(struct_size) sizeof(struct mail_user_settings),
+ MEMBER(check_func) mail_user_settings_check
};
const void *
return dset;
}
+const struct mail_storage_settings *
+mail_user_set_get_storage_set(const struct mail_user_settings *set)
+{
+ return mail_user_set_get_driver_settings(set,
+ MAIL_STORAGE_SET_DRIVER_NAME);
+}
+
const void *mail_storage_get_driver_settings(struct mail_storage *storage)
{
return mail_user_set_get_driver_settings(storage->ns->user->set,
return index_flags;
}
-void mail_storage_namespace_defines_init(pool_t pool)
+const struct dynamic_settings_parser *mail_storage_get_dynamic_parsers(void)
{
struct dynamic_settings_parser *parsers;
struct mail_storage *const *storages;
storages = array_get(&mail_storage_classes, &count);
parsers = t_new(struct dynamic_settings_parser, count + 1);
- parsers[0].name = "MAIL";
+ parsers[0].name = MAIL_STORAGE_SET_DRIVER_NAME;
parsers[0].info = &mail_storage_setting_parser_info;
for (i = 0, j = 1; i < count; i++) {
parsers[j].info = storages[i]->v.get_setting_parser_info();
j++;
}
+ return parsers;
+}
- settings_parser_info_update(pool, parsers[j-1].info->parent, parsers);
+static void
+fix_base_path(struct mail_user_settings *set, pool_t pool, const char **str)
+{
+ if (*str != NULL && **str != '\0' && **str != '/')
+ *str = p_strconcat(pool, set->base_dir, "/", *str, NULL);
}
/* <settings checks> */
}
return TRUE;
}
+
+static bool mail_user_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+ const char **error_r)
+{
+ struct mail_user_settings *set = _set;
+
+#ifndef CONFIG_BINARY
+ fix_base_path(set, pool, &set->auth_socket_path);
+#endif
+
+ if (*set->mail_plugins != '\0' &&
+ access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
+ *error_r = t_strdup_printf(
+ "mail_plugin_dir: access(%s) failed: %m",
+ set->mail_plugin_dir);
+ return FALSE;
+ }
+ return TRUE;
+}
/* </settings checks> */
};
struct mail_user_settings {
+ const char *base_dir;
+ const char *auth_socket_path;
+
+ const char *mail_uid;
+ const char *mail_gid;
+ const char *mail_home;
+ const char *mail_chroot;
+ const char *mail_access_groups;
+ const char *mail_privileged_group;
+ const char *valid_chroot_dirs;
+
+ unsigned int first_valid_uid, last_valid_uid;
+ unsigned int first_valid_gid, last_valid_gid;
+
+ const char *mail_plugins;
+ const char *mail_plugin_dir;
+
ARRAY_DEFINE(namespaces, struct mail_namespace_settings *);
ARRAY_DEFINE(plugin_envs, const char *);
};
const void *
mail_user_set_get_driver_settings(const struct mail_user_settings *set,
const char *driver);
+const struct mail_storage_settings *
+mail_user_set_get_storage_set(const struct mail_user_settings *set);
const void *mail_storage_get_driver_settings(struct mail_storage *storage);
enum mail_index_open_flags
mail_storage_settings_to_index_flags(const struct mail_storage_settings *set);
-void mail_storage_namespace_defines_init(pool_t pool);
+const struct dynamic_settings_parser *mail_storage_get_dynamic_parsers(void);
#endif
#include "var-expand.h"
#include "settings-parser.h"
#include "auth-master.h"
+#include "master-service.h"
#include "mail-storage-settings.h"
#include "mail-namespace.h"
#include "mail-storage.h"
i_assert(username != NULL);
i_assert(*username != '\0');
- pool = pool_alloconly_create("mail user", 2048);
+ pool = pool_alloconly_create("mail user", 4096);
user = p_new(pool, struct mail_user, 1);
user->pool = pool;
user->refcount = 1;
if (mail_user_expand_plugins_envs(user, error_r) < 0)
return -1;
- mail_set = mail_user_set_get_driver_settings(user->set, "MAIL");
+ mail_set = mail_user_set_get_storage_set(user->set);
user->mail_debug = mail_set->mail_debug;
user->initialized = TRUE;
userdb_pool = pool_alloconly_create("userdb lookup", 512);
ret = auth_master_user_lookup(auth_master_conn, user->username,
- AUTH_SERVICE_INTERNAL,
- userdb_pool, &reply);
+ "lib-storage", userdb_pool, &reply);
if (ret < 0)
*home_r = NULL;
else {
}
const char *mail_user_plugin_getenv(struct mail_user *user, const char *name)
+{
+ return mail_user_set_plugin_getenv(user->set, name);
+}
+
+const char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
+ const char *name)
{
const char *const *envs;
- unsigned int i, count, name_len = strlen(name);
+ unsigned int i, count;
- if (!array_is_created(&user->set->plugin_envs))
+ if (!array_is_created(&set->plugin_envs))
return NULL;
- envs = array_get(&user->set->plugin_envs, &count);
- for (i = 0; i < count; i++) {
- if (strncmp(envs[i], name, name_len) == 0 &&
- envs[i][name_len] == '=')
- return envs[i] + name_len + 1;
+ envs = array_get(&set->plugin_envs, &count);
+ for (i = 0; i < count; i += 2) {
+ if (strcmp(envs[i], name) == 0)
+ return envs[i+1];
}
return NULL;
}
void mail_users_init(const char *auth_socket_path, bool debug)
{
- const char *base_dir;
-
- if (auth_socket_path == NULL) {
- base_dir = getenv("BASE_DIR");
- if (base_dir == NULL)
- base_dir = PKG_RUNDIR;
- auth_socket_path = t_strconcat(base_dir, "/auth-master", NULL);
- }
auth_master_conn = auth_master_init(auth_socket_path, debug);
}
const char *mail_user_get_temp_prefix(struct mail_user *user);
/* If name exists in plugin_envs, return its value. */
const char *mail_user_plugin_getenv(struct mail_user *user, const char *name);
+const char *mail_user_set_plugin_getenv(const struct mail_user_settings *set,
+ const char *name);
/* Add more namespaces to user's namespaces. The ->next pointers may be
changed, so the namespaces pointer will be updated to user->namespaces. */
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
+ -I$(top_srcdir)/src/lib-master \
-DSYSCONFDIR=\""$(sysconfdir)"\" \
-DPKG_RUNDIR=\""$(rundir)"\" \
-DPKG_STATEDIR=\""$(statedir)"\" \
-DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
-DBINDIR=\""$(bindir)"\" \
- -DMODULEDIR=\""$(moduledir)"\" \
-DSSLDIR=\""$(ssldir)\""
dovecot_LDADD = \
mail-process.c \
master-settings.c \
main.c \
- syslog-util.c \
ssl-init.c \
sysinfo-get.c
mail-process.h \
master-login-interface.h \
master-settings.h \
- syslog-util.h \
ssl-init.h \
sysinfo-get.h
#include "hash.h"
#include "str.h"
#include "env-util.h"
-#include "syslog-util.h"
#include "child-process.h"
#include <unistd.h>
void child_process_init_env(const struct master_settings *set)
{
- int facility;
-
/* remove all environment, we don't need them */
env_clean();
if (env_tz != NULL)
env_put(t_strconcat("TZ=", env_tz, NULL));
- if (master_set == NULL ||
- !syslog_facility_find(set->syslog_facility, &facility))
- facility = LOG_MAIL;
- env_put(t_strdup_printf("SYSLOG_FACILITY=%d", facility));
-
if (master_set != NULL && !set->version_ignore)
env_put("DOVECOT_VERSION="PACKAGE_VERSION);
#ifdef DEBUG
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
- -I$(top_srcdir)/src/lib-settings \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage \
- -I$(top_srcdir)/src/lib-storage/index \
-DPKG_RUNDIR=\""$(rundir)"\"
lib20_convert_plugin_la_LDFLAGS = -module -avoid-version
convert-plugin.c
noinst_HEADERS = \
- convert-settings.h \
convert-storage.h \
convert-plugin.h
pkglibexec_PROGRAMS = convert-tool
convert_tool_SOURCES = \
- convert-settings.c \
convert-tool.c
common_objects = \
+++ /dev/null
-/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "settings-parser.h"
-#include "mail-storage-settings.h"
-#include "convert-settings.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#undef DEF
-#define DEF(type, name) \
- { type, #name, offsetof(struct convert_settings, name), NULL }
-
-static struct setting_define convert_setting_defines[] = {
- DEF(SET_STR, base_dir),
- DEF(SET_STR, auth_socket_path),
-
- { SET_STRLIST, "plugin", offsetof(struct convert_settings, plugin_envs), NULL },
-
- SETTING_DEFINE_LIST_END
-};
-
-static struct convert_settings convert_default_settings = {
- MEMBER(base_dir) PKG_RUNDIR,
- MEMBER(auth_socket_path) "auth-master"
-};
-
-struct setting_parser_info convert_setting_parser_info = {
- MEMBER(defines) convert_setting_defines,
- MEMBER(defaults) &convert_default_settings,
-
- MEMBER(parent) NULL,
- MEMBER(dynamic_parsers) NULL,
-
- MEMBER(parent_offset) (size_t)-1,
- MEMBER(type_offset) (size_t)-1,
- MEMBER(struct_size) sizeof(struct convert_settings)
-};
-
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct convert_settings *set, const char **str)
-{
- if (*str != NULL && **str != '\0' && **str != '/') {
- *str = p_strconcat(settings_pool,
- set->base_dir, "/", *str, NULL);
- }
-}
-
-void convert_settings_read(const struct convert_settings **set_r,
- const struct mail_user_settings **user_set_r)
-{
- static const struct setting_parser_info *roots[] = {
- &convert_setting_parser_info,
- &mail_user_setting_parser_info
- };
- struct setting_parser_context *parser;
- struct convert_settings *set;
- void **sets;
-
- if (settings_pool == NULL)
- settings_pool = pool_alloconly_create("convert settings", 1024);
- else
- p_clear(settings_pool);
-
- mail_storage_namespace_defines_init(settings_pool);
-
- parser = settings_parser_init_list(settings_pool,
- roots, N_ELEMENTS(roots),
- SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
- if (settings_parse_environ(parser) < 0) {
- i_fatal("Error reading configuration: %s",
- settings_parser_get_error(parser));
- }
-
- sets = settings_parser_get_list(parser);
- set = sets[0];
- fix_base_path(set, &set->auth_socket_path);
-
- *set_r = set;
- *user_set_r = sets[1];
- settings_parser_deinit(&parser);
-}
+++ /dev/null
-#ifndef CONVERT_SETTINGS_H
-#define CONVERT_SETTINGS_H
-
-struct mail_user_settings;
-
-struct convert_settings {
- const char *base_dir;
- const char *auth_socket_path;
-
- ARRAY_DEFINE(plugin_envs, const char *);
-};
-
-void convert_settings_read(const struct convert_settings **set_r,
- const struct mail_user_settings **user_set_r);
-
-#endif
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
-#include "ioloop.h"
-#include "randgen.h"
-#include "lib-signals.h"
+#include "env-util.h"
+#include "master-service.h"
#include "mail-namespace.h"
-#include "mail-storage-private.h"
-#include "convert-settings.h"
+#include "mail-storage.h"
+#include "mail-storage-service.h"
#include "convert-storage.h"
#include <stdlib.h>
+#include <unistd.h>
#define USAGE_STRING \
"Usage: <username> <home dir> <source mail env> <dest mail env>\n" \
" [skip_broken_mailboxes] [skip_dotfiles] [alt_hierarchy_char=<c>]"
-int main(int argc, const char *argv[])
+int main(int argc, char *argv[])
{
- struct ioloop *ioloop;
+ struct master_service *service;
struct mail_user *user;
- const struct convert_settings *set;
- const struct mail_user_settings *user_set;
- const struct mail_storage_settings *mail_set;
- struct convert_plugin_settings set2;
+ struct convert_plugin_settings set;
struct mail_namespace *dest_ns;
struct mail_namespace_settings ns_set;
const char *error;
- int i, ret = 0;
+ int i, c, ret = 0;
- lib_init();
- lib_signals_init();
- random_init();
- mail_storage_init();
- mail_storage_register_all();
- mailbox_list_register_all();
+ service = master_service_init("convert-tool",
+ MASTER_SERVICE_FLAG_STANDALONE,
+ argc, argv);
- convert_settings_read(&set, &user_set);
- mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
- mail_users_init(set->auth_socket_path, mail_set->mail_debug);
-
- if (argc <= 4)
+ while ((c = getopt(argc, argv, master_service_getopt_string())) > 0) {
+ if (!master_service_parse_option(service, c, optarg))
+ i_fatal(USAGE_STRING);
+ }
+ if (argc - optind < 4)
i_fatal(USAGE_STRING);
- ioloop = io_loop_create();
+ env_put(t_strconcat("HOME=", argv[optind+1], NULL));
- memset(&set2, 0, sizeof(set2));
- for (i = 5; i < argc; i++) {
+ memset(&set, 0, sizeof(set));
+ for (i = optind + 4; i < argc; i++) {
if (strcmp(argv[i], "skip_broken_mailboxes") != 0)
- set2.skip_broken_mailboxes = TRUE;
+ set.skip_broken_mailboxes = TRUE;
else if (strcmp(argv[i], "skip_dotdirs") != 0)
- set2.skip_dotdirs = TRUE;
+ set.skip_dotdirs = TRUE;
else if (strncmp(argv[i], "alt_hierarchy_char=", 19) != 0)
- set2.alt_hierarchy_char = argv[i][19];
+ set.alt_hierarchy_char = argv[i][19];
+ else
+ i_fatal(USAGE_STRING);
}
- user = mail_user_alloc(argv[1], user_set);
- mail_user_set_home(user, argv[2]);
- mail_user_set_vars(user, geteuid(), "convert", NULL, NULL);
- if (mail_user_init(user, &error) < 0)
- i_fatal("Mail user initialization failed: %s", error);
+ master_service_init_log(service,
+ t_strdup_printf("convert-tool(%s): ", argv[optind]));
+ user = mail_storage_service_init_user(service, argv[optind], NULL, 0);
memset(&ns_set, 0, sizeof(ns_set));
ns_set.location = argv[4];
"mail storage with data '%s': %s", argv[4], error);
}
- ret = convert_storage(argv[3], dest_ns, &set2);
+ ret = convert_storage(argv[3], dest_ns, &set);
if (ret > 0)
i_info("Successfully converted");
else if (ret == 0)
i_error("Source storage not found");
else
i_error("Internal failure");
- mail_user_unref(&user);
- io_loop_destroy(&ioloop);
- mail_storage_deinit();
- mail_users_deinit();
- lib_signals_deinit();
- lib_deinit();
+ mail_user_unref(&user);
+ mail_storage_service_deinit_user();
+ master_service_deinit(&service);
return ret <= 0 ? 1 : 0;
}
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-auth \
- -I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-dict \
+ -I$(top_srcdir)/src/lib-settings \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
expire-plugin.c
noinst_HEADERS = \
- auth-client.h \
expire-env.h \
- expire-plugin.h \
- expire-settings.h
+ expire-plugin.h
pkglibexec_PROGRAMS = expire-tool
expire_tool_SOURCES = \
- auth-client.c \
- expire-settings.c \
expire-tool.c
libs = \
$(top_builddir)/src/lib-storage/libdovecot-storage.la \
$(top_builddir)/src/lib-dovecot/libdovecot.la
-expire_tool_LDADD = $(libs)
+expire_tool_LDADD = $(libs) expire-env.o
expire_tool_DEPENDENCIES = $(libs)
int ret;
pool = pool_alloconly_create("userdb lookup", 512);
- ret = auth_master_user_lookup(conn, user, AUTH_SERVICE_INTERNAL,
+ ret = auth_master_user_lookup(conn, user, MASTER_SERVICE_INTERNAL,
pool, &reply);
if (ret > 0)
auth_set_env(user, &reply);
+++ /dev/null
-/* Copyright (c) 2008-2009 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "settings-parser.h"
-#include "mail-storage-settings.h"
-#include "expire-settings.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#undef DEF
-#define DEF(type, name) \
- { type, #name, offsetof(struct expire_settings, name), NULL }
-
-static struct setting_define expire_setting_defines[] = {
- DEF(SET_STR, base_dir),
- DEF(SET_STR, auth_socket_path),
-
- { SET_STRLIST, "plugin", offsetof(struct expire_settings, plugin_envs), NULL },
-
- SETTING_DEFINE_LIST_END
-};
-
-static struct expire_settings expire_default_settings = {
- MEMBER(base_dir) PKG_RUNDIR,
- MEMBER(auth_socket_path) "auth-master"
-};
-
-struct setting_parser_info expire_setting_parser_info = {
- MEMBER(defines) expire_setting_defines,
- MEMBER(defaults) &expire_default_settings,
-
- MEMBER(parent) NULL,
- MEMBER(dynamic_parsers) NULL,
-
- MEMBER(parent_offset) (size_t)-1,
- MEMBER(type_offset) (size_t)-1,
- MEMBER(struct_size) sizeof(struct expire_settings)
-};
-
-static pool_t settings_pool = NULL;
-
-static void fix_base_path(struct expire_settings *set, const char **str)
-{
- if (*str != NULL && **str != '\0' && **str != '/') {
- *str = p_strconcat(settings_pool,
- set->base_dir, "/", *str, NULL);
- }
-}
-
-static void
-parse_expand_vars(struct setting_parser_context *parser, const char *value)
-{
- const char *const *expanded;
-
- expanded = t_strsplit(value, " ");
- settings_parse_set_keys_expandeded(parser, settings_pool, expanded);
- /* settings from userdb are in the VARS_EXPANDED list. for each
- unknown setting in the list assume it's a plugin setting. */
- for (; *expanded != NULL; expanded++) {
- if (settings_parse_is_valid_key(parser, *expanded))
- continue;
-
- value = getenv(t_str_ucase(*expanded));
- if (value == NULL)
- continue;
-
- settings_parse_line(parser, t_strconcat("plugin/", *expanded,
- "=", value, NULL));
- }
-}
-
-void expire_settings_read(const struct expire_settings **set_r,
- const struct mail_user_settings **user_set_r)
-{
- static const struct setting_parser_info *roots[] = {
- &expire_setting_parser_info,
- &mail_user_setting_parser_info
- };
- struct setting_parser_context *parser;
- struct expire_settings *set;
- const char *value;
- void **sets;
-
- if (settings_pool == NULL)
- settings_pool = pool_alloconly_create("expire settings", 1024);
- else
- p_clear(settings_pool);
-
- mail_storage_namespace_defines_init(settings_pool);
-
- parser = settings_parser_init_list(settings_pool,
- roots, N_ELEMENTS(roots),
- SETTINGS_PARSER_FLAG_IGNORE_UNKNOWN_KEYS);
-
- if (settings_parse_environ(parser) < 0) {
- i_fatal("Error reading configuration: %s",
- settings_parser_get_error(parser));
- }
-
- value = getenv("VARS_EXPANDED");
- if (value != NULL)
- parse_expand_vars(parser, value);
-
- sets = settings_parser_get_list(parser);
- set = sets[0];
- fix_base_path(set, &set->auth_socket_path);
-
- *set_r = set;
- *user_set_r = sets[1];
- settings_parser_deinit(&parser);
-}
+++ /dev/null
-#ifndef CONVERT_SETTINGS_H
-#define CONVERT_SETTINGS_H
-
-struct mail_user_settings;
-
-struct expire_settings {
- const char *base_dir;
- const char *auth_socket_path;
-
- ARRAY_DEFINE(plugin_envs, const char *);
-};
-
-void expire_settings_read(const struct expire_settings **set_r,
- const struct mail_user_settings **user_set_r);
-
-#endif
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
-#include "ioloop.h"
#include "env-util.h"
-#include "file-lock.h"
-#include "randgen.h"
-#include "lib-signals.h"
#include "dict.h"
+#include "master-service.h"
+#include "master-service-settings.h"
#include "mail-index.h"
#include "mail-search-build.h"
#include "mail-storage.h"
+#include "mail-storage-service.h"
#include "mail-namespace.h"
#include "auth-client.h"
#include "auth-master.h"
#include "expire-env.h"
-#include "expire-settings.h"
#include <stdlib.h>
-/* ugly, but automake doesn't like having it built as both static and
- dynamic object.. */
-#include "expire-env.c"
-
struct expire_context {
- struct auth_master_connection *auth_conn;
-
- char *user;
+ struct mail_storage_service_multi_ctx *multi;
struct mail_user *mail_user;
- const struct expire_settings *set;
bool testrun;
};
-static int user_init(struct expire_context *ctx, const char *user)
-{
- const struct mail_user_settings *user_set;
- const char *error;
- int ret;
-
- env_clean();
- if ((ret = auth_client_put_user_env(ctx->auth_conn, user)) <= 0) {
- if (ret < 0)
- return ret;
-
- /* user no longer exists */
- return 0;
- }
-
- expire_settings_read(&ctx->set, &user_set);
-
- ctx->mail_user = mail_user_alloc(user, user_set);
- mail_user_set_home(ctx->mail_user, getenv("HOME"));
- mail_user_set_vars(ctx->mail_user, geteuid(), "expire", NULL, NULL);
- if (mail_user_init(ctx->mail_user, &error) < 0) {
- i_error("Mail user initialization failed: %s", error);
- return -1;
- }
- if (mail_namespaces_init(ctx->mail_user, &error) < 0) {
- i_error("Namespace initialization failed: %s", error);
- return -1;
- }
- return 1;
-}
-
-static void user_deinit(struct expire_context *ctx)
-{
- mail_user_unref(&ctx->mail_user);
- i_free_and_null(ctx->user);
-}
-
static int
mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
const char *mailbox,
*oldest_r = 0;
- if (ctx->user != NULL && strcmp(user, ctx->user) != 0)
- user_deinit(ctx);
- if (ctx->user == NULL) {
- if ((ret = user_init(ctx, user)) <= 0) {
- if (ctx->testrun)
- i_info("User lookup failed: %s", user);
+ if (ctx->mail_user != NULL &&
+ strcmp(user, ctx->mail_user->username) != 0)
+ mail_user_unref(&ctx->mail_user);
+ if (ctx->mail_user == NULL) {
+ i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ",
+ user));
+ ret = mail_storage_service_multi_next(ctx->multi, user,
+ &ctx->mail_user, &errstr);
+ if (ret <= 0) {
+ if (ret < 0 || ctx->testrun)
+ i_error("User init failed: %s", errstr);
return ret;
}
- ctx->user = i_strdup(user);
+ i_info("success: %s %d", ctx->mail_user->username, (int)geteuid());
}
ns_mailbox = mailbox;
return ret < 0 ? -1 : 0;
}
-static const char *expire_getenv(struct expire_context *ctx, const char *name)
-{
- const char *const *envs;
- unsigned int i, count, name_len = strlen(name);
-
- if (!array_is_created(&ctx->set->plugin_envs))
- return NULL;
-
- envs = array_get(&ctx->set->plugin_envs, &count);
- for (i = 0; i < count; i++) {
- if (strncmp(envs[i], name, name_len) == 0 &&
- envs[i][name_len] == '=')
- return envs[i] + name_len + 1;
- }
- return NULL;
-}
-
-static void expire_run(bool testrun)
+static void expire_run(struct master_service *service, bool testrun)
{
struct expire_context ctx;
struct dict *dict = NULL;
- struct dict_transaction_context *trans;
const struct mail_user_settings *user_set;
- const struct mail_storage_settings *mail_set;
+ void **sets;
+ struct dict_transaction_context *trans;
struct dict_iterate_context *iter;
struct expire_env *env;
time_t oldest;
unsigned int expunge_secs, altmove_secs;
- const char *p, *key, *value;
- const char *userp, *mailbox;
+ const char *p, *key, *value, *expire, *expire_altmove, *expire_dict;
+ const char *userp = NULL, *mailbox;
int ret;
- dict_drivers_register_builtin();
- mail_storage_init();
- mail_storage_register_all();
- mailbox_list_register_all();
-
memset(&ctx, 0, sizeof(ctx));
- expire_settings_read(&ctx.set, &user_set);
- mail_set = mail_user_set_get_driver_settings(user_set, "MAIL");
- mail_users_init(ctx.set->auth_socket_path, mail_set->mail_debug);
+ ctx.multi = mail_storage_service_multi_init(service, NULL,
+ MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP);
+
+ sets = master_service_settings_get_others(service);
+ user_set = sets[0];
- if (expire_getenv(&ctx, "EXPIRE") == NULL &&
- expire_getenv(&ctx, "EXPIRE_ALTMOVE") == NULL)
+ expire = mail_user_set_plugin_getenv(user_set, "expire");
+ expire_altmove = mail_user_set_plugin_getenv(user_set, "expire_altmove");
+ expire_dict = mail_user_set_plugin_getenv(user_set, "expire_dict");
+
+ if (expire == NULL && expire_altmove == NULL)
i_fatal("expire and expire_altmove settings not set");
- if (expire_getenv(&ctx, "EXPIRE_DICT") == NULL)
+ if (expire_dict == NULL)
i_fatal("expire_dict setting not set");
ctx.testrun = testrun;
- ctx.auth_conn = auth_master_init(ctx.set->auth_socket_path,
- mail_set->mail_debug);
- env = expire_env_init(expire_getenv(&ctx, "EXPIRE"),
- expire_getenv(&ctx, "EXPIRE_ALTMOVE"));
- dict = dict_init(expire_getenv(&ctx, "EXPIRE_DICT"),
- DICT_DATA_TYPE_UINT32, "");
+ env = expire_env_init(expire, expire_altmove);
+ dict = dict_init(expire_dict, DICT_DATA_TYPE_UINT32, "");
if (dict == NULL)
i_fatal("dict_init() failed");
}
}
}
+ if (testrun && userp == NULL)
+ i_info("No entries in dictionary");
+
dict_iterate_deinit(&iter);
if (!testrun)
dict_transaction_commit(&trans);
dict_transaction_rollback(&trans);
dict_deinit(&dict);
- if (ctx.user != NULL)
- user_deinit(&ctx);
- auth_master_deinit(&ctx.auth_conn);
-
- mail_storage_deinit();
- mail_users_deinit();
- dict_drivers_unregister_builtin();
+ if (ctx.mail_user != NULL)
+ mail_user_unref(&ctx.mail_user);
+ mail_storage_service_multi_deinit(&ctx.multi);
}
-int main(int argc ATTR_UNUSED, const char *argv[])
+int main(int argc, char *argv[])
{
- struct ioloop *ioloop;
+ struct master_service *service;
+ const char *getopt_str;
bool test = FALSE;
+ int c;
- lib_init();
- lib_signals_init();
- random_init();
+ service = master_service_init("expire-tool",
+ MASTER_SERVICE_FLAG_STANDALONE,
+ argc, argv);
- while (argv[1] != NULL) {
- if (strcmp(argv[1], "--test") == 0)
+ getopt_str = t_strconcat("t", master_service_getopt_string(), NULL);
+ while ((c = getopt(argc, argv, getopt_str)) > 0) {
+ switch (c) {
+ case 't':
test = TRUE;
- else
- i_fatal("Unknown parameter: %s", argv[1]);
- argv++;
+ break;
+ default:
+ if (!master_service_parse_option(service, c, optarg))
+ i_fatal("Unknown parameter: -%c", c);
+ break;
+ }
}
+ if (optind != argc)
+ i_fatal("Unknown parameter: %s", argv[optind]);
- ioloop = io_loop_create();
- expire_run(test);
- io_loop_destroy(&ioloop);
+ expire_run(service, test);
- lib_signals_deinit();
- lib_deinit();
+ master_service_deinit(&service);
return 0;
}
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-dict \
-I$(top_srcdir)/src/lib-mail \
- -I$(top_srcdir)/src/lib-storage \
- -DPKG_RUNDIR=\""$(rundir)"\" \
- -DMODULEDIR=\""$(moduledir)"\"
+ -I$(top_srcdir)/src/lib-storage
pop3_LDFLAGS = -export-dynamic
pop3_settings_read(set_r, user_set_r);
/* Load the plugins before chrooting. Their init() is called later. */
- modules = *(*set_r)->mail_plugins == '\0' ? NULL :
- module_dir_load((*set_r)->mail_plugin_dir,
- (*set_r)->mail_plugins, TRUE, version);
+ modules = *(*user_set_r)->mail_plugins == '\0' ? NULL :
+ module_dir_load((*user_set_r)->mail_plugin_dir,
+ (*user_set_r)->mail_plugins, TRUE, version);
restrict_access_by_env(getenv("HOME"), !IS_STANDALONE());
restrict_access_allow_coredumps(TRUE);
}
dict_drivers_register_builtin();
- mail_users_init(set->auth_socket_path, set->mail_debug);
+ mail_users_init(user_set->auth_socket_path, set->mail_debug);
clients_init();
module_dir_init(modules);
#include <stdlib.h>
#include <unistd.h>
-static bool pop3_settings_check(void *_set, pool_t pool, const char **error_r);
-
#undef DEF
#undef DEFLIST
#define DEF(type, name) \
{ SET_DEFLIST, name, offsetof(struct pop3_settings, field), defines }
static struct setting_define pop3_setting_defines[] = {
- DEF(SET_STR, base_dir),
- DEF(SET_STR, auth_socket_path),
-
DEF(SET_BOOL, mail_debug),
DEF(SET_BOOL, shutdown_clients),
DEF(SET_BOOL, verbose_proctitle),
- DEF(SET_STR, mail_plugins),
- DEF(SET_STR, mail_plugin_dir),
-
DEF(SET_BOOL, pop3_no_flag_updates),
DEF(SET_BOOL, pop3_enable_last),
DEF(SET_BOOL, pop3_reuse_xuidl),
};
static struct pop3_settings pop3_default_settings = {
- MEMBER(base_dir) PKG_RUNDIR,
- MEMBER(auth_socket_path) "auth-master",
-
MEMBER(mail_debug) FALSE,
MEMBER(shutdown_clients) FALSE,
MEMBER(verbose_proctitle) FALSE,
- MEMBER(mail_plugins) "",
- MEMBER(mail_plugin_dir) MODULEDIR,
-
MEMBER(pop3_no_flag_updates) FALSE,
MEMBER(pop3_enable_last) FALSE,
MEMBER(pop3_reuse_xuidl) FALSE,
MEMBER(parent_offset) (size_t)-1,
MEMBER(type_offset) (size_t)-1,
MEMBER(struct_size) sizeof(struct pop3_settings),
- MEMBER(check_func) pop3_settings_check
+ MEMBER(check_func) NULL
};
static pool_t settings_pool = NULL;
-static void fix_base_path(struct pop3_settings *set, const char **str)
-{
- if (*str != NULL && **str != '\0' && **str != '/') {
- *str = p_strconcat(settings_pool,
- set->base_dir, "/", *str, NULL);
- }
-}
-
-/* <settings checks> */
-static bool pop3_settings_check(void *_set, pool_t pool ATTR_UNUSED,
- const char **error_r)
-{
- struct pop3_settings *set = _set;
-
-#ifndef CONFIG_BINARY
- fix_base_path(set, &set->auth_socket_path);
-#endif
-
- if (*set->mail_plugins != '\0' &&
- access(set->mail_plugin_dir, R_OK | X_OK) < 0) {
- *error_r = t_strdup_printf(
- "mail_plugin_dir: access(%s) failed: %m",
- set->mail_plugin_dir);
- return FALSE;
- }
- return TRUE;
-}
-/* </settings checks> */
-
static void
parse_expand_vars(struct setting_parser_context *parser, const char *value)
{
else
p_clear(settings_pool);
- mail_storage_namespace_defines_init(settings_pool);
+ settings_parser_info_update(settings_pool,
+ mail_storage_get_dynamic_parsers());
parser = settings_parser_init_list(settings_pool,
roots, N_ELEMENTS(roots),
struct mail_user_settings;
struct pop3_settings {
- const char *base_dir;
- const char *auth_socket_path;
-
bool mail_debug;
bool shutdown_clients;
bool verbose_proctitle;
- const char *mail_plugins;
- const char *mail_plugin_dir;
-
/* pop3: */
bool pop3_no_flag_updates;
bool pop3_enable_last;
maildirlock \
threadview
-sbin_PROGRAMS = dovecotpw
+sbin_PROGRAMS = dovecotpw doveadm
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
+ -I$(top_srcdir)/src/lib-auth \
+ -I$(top_srcdir)/src/lib-dict \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-mail \
-I$(top_srcdir)/src/lib-imap \
-I$(top_srcdir)/src/lib-index \
- -I$(top_srcdir)/src/lib-storage/index/maildir \
+ -I$(top_srcdir)/src/lib-storage \
-I$(top_srcdir)/src/auth
rawlog_LDADD = \
dovecotpw_SOURCES = \
dovecotpw.c
+
+doveadm_LDADD = \
+ ../lib-dovecot/libdovecot.la \
+ ../lib-storage/libdovecot-storage.la
+doveadm_SOURCES = \
+ doveadm.c
+