doveadm-mail.c revision 218153e0aa44a115a2dacab8510fb8de7e1cb78e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib-signals.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "ioloop.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "str.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "module-dir.h"
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen#include "wildcard-match.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "imap-utf7.h"
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen#include "mail-user.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-namespace.h"
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen#include "mail-storage.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-service.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search-build.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "doveadm-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm-print.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm-mail.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdio.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdlib.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct doveadm_mail_cmd_module_register
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_cmd_module_register = { 0 };
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int killed_signo = 0;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstruct doveadm_mail_cmd_context *
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_mail_cmd_alloc_size(size_t size)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen{
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen struct doveadm_mail_cmd_context *ctx;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen pool_t pool;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen ctx = p_malloc(pool, size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->pool = pool;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_user *user)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_namespace *ns;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen continue;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_storage_purge(ns->storage) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(ns->storage, NULL));
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen }
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen }
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen}
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct doveadm_mail_cmd_context *ctx;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.run = cmd_purge_run;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ctx;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct mailbox **box_r)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct mail_namespace *ns;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct mailbox *box;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen string_t *str;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *orig_mailbox = mailbox;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str = t_str_new(128);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (imap_utf8_to_utf7(mailbox, str) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox = str_c(str);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ns == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("Can't find namespace for mailbox %s", mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen if (mailbox_open(box) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Opening mailbox %s failed: %s", orig_mailbox,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(mailbox_get_storage(box),
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_free(&box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen *box_r = box;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen return 0;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenint doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct mailbox **box_r)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen{
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (mailbox_find_and_open(user, mailbox, box_r) < 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return -1;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen i_error("Syncing mailbox %s failed: %s", mailbox,
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen mail_storage_get_last_error(mailbox_get_storage(*box_r),
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen NULL));
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen return -1;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen }
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen return 0;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen}
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstruct mail_search_args *
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainendoveadm_mail_build_search_args(const char *const args[])
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_search_parser *parser;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_search_args *sargs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *error;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser = mail_search_parser_init_cmdline(args);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen if (mail_search_build(mail_search_register_get_human(),
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen parser, "UTF-8", &sargs, &error) < 0)
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen i_fatal("%s", error);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen mail_search_parser_deinit(&parser);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return sargs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
cd2ed64888b42b481cde6bb9548c8520516fa3e9Timo Sirainenstruct force_resync_cmd_context {
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen struct doveadm_mail_cmd_context ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *mailbox;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen};
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void cmd_force_resync_run(struct doveadm_mail_cmd_context *_ctx,
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen struct mail_user *user)
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen{
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen struct force_resync_cmd_context *ctx =
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen (struct force_resync_cmd_context *)_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_storage *storage;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox *box;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen _ctx->failed = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen storage = mailbox_get_storage(box);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->mailbox,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(storage, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen _ctx->failed = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_free(&box);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void cmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen const char *const args[])
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen struct force_resync_cmd_context *ctx =
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen (struct force_resync_cmd_context *)_ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *mailbox = args[0];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox == NULL || args[1] != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_mail_help_name("force-resync");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->mailbox = p_strdup(ctx->ctx.pool, mailbox);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct force_resync_cmd_context *ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct force_resync_cmd_context);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->ctx.v.init = cmd_force_resync_init;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->ctx.v.run = cmd_force_resync_run;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return &ctx->ctx;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen}
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainenstatic int
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen const struct mail_storage_service_input *input,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen const char **error_r)
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen{
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen struct mail_storage_service_user *service_user;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen const char *error;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen int ret;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username));
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, input,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &service_user, &error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret <= 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret < 0) {
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen error);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen }
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen return ret;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen }
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_settings->doveadm_worker_count > 0 && !doveadm_server) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* execute this command via doveadm server */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = doveadm_mail_server_user(ctx, service_user, error_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_service_user_free(&service_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret < 0 ? -1 : 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mail_storage_service_next(ctx->storage_service, service_user,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &ctx->cur_mail_user);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *error_r = "User init failed";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_service_user_free(&service_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.run(ctx, ctx->cur_mail_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_user_unref(&ctx->cur_mail_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_service_user_free(&service_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen char *argv[], const char *username,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_storage_service_flags service_flags)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_storage_service_input input;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *error;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (username == NULL)
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen i_fatal("USER environment is missing and -u option not used");
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen memset(&input, 0, sizeof(input));
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen input.username = username;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service_flags);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen ctx->v.init(ctx, (const void *)argv);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen if (hook_doveadm_mail_init != NULL)
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen hook_doveadm_mail_init(ctx);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen if (ret < 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_fatal("%s", error);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen else if (ret == 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_fatal("User doesn't exist");
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen}
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen killed_signo = si->si_signo;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx, char *argv[],
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *wildcard_user,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_storage_service_flags service_flags)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_storage_service_input input;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen unsigned int user_idx, user_count, interval, n;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const char *user, *error;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen int ret;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen memset(&input, 0, sizeof(input));
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen input.service = "doveadm";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_flags);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.init(ctx, (const void *)argv);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (hook_doveadm_mail_init != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen hook_doveadm_mail_init(ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen user_count = mail_storage_service_all_init(ctx->storage_service);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen n = user_count / 10000;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (interval = 10; n > 0 && interval < 1000; interval *= 10)
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen n /= 10;
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen user_idx = 0;
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (wildcard_user != NULL) {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen continue;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen }
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen input.username = user;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen doveadm_print_sticky("username", user);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen T_BEGIN {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (ret < 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_error("%s", error);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen else if (ret == 0)
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen i_info("User no longer exists, skipping");
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen } T_END;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret == -1)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_verbose) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (++user_idx % interval == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen printf("\r%d / %d", user_idx, user_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen fflush(stdout);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (killed_signo != 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_warning("Killed with signal %d", killed_signo);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_verbose)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen printf("\n");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_set_failure_prefix("doveadm: ");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Failed to iterate through some users");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const args[] ATTR_UNUSED)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const char **username_r)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainenstruct doveadm_mail_cmd_context *
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainendoveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct doveadm_mail_cmd_context *ctx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx = cmd->alloc();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->cmd = cmd;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (ctx->v.init == NULL)
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen ctx->v.init = doveadm_mail_cmd_init_noop;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (ctx->v.get_next_user == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ctx->v.deinit == NULL)
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen ctx->v.deinit = doveadm_mail_cmd_deinit_noop;
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen p_array_init(&ctx->module_contexts, ctx->pool, 5);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return ctx;
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen}
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_storage_service_flags service_flags =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct doveadm_mail_cmd_context *ctx;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *getopt_args, *username, *wildcard_user;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int c;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_debug)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx = doveadm_mail_cmd_init(cmd);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen getopt_args = t_strconcat("AS:u:", ctx->getopt_args, NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen username = getenv("USER");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen wildcard_user = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while ((c = getopt(argc, argv, getopt_args)) > 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (c) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'A':
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen ctx->iterate_all_users = TRUE;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen break;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen case 'S':
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_settings->doveadm_socket_path = optarg;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (doveadm_settings->doveadm_worker_count == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_settings->doveadm_worker_count = 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'u':
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen service_flags |=
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen username = optarg;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strchr(username, '*') != NULL ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen strchr(username, '?') != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen wildcard_user = username;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen default:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->v.parse_arg == NULL ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen !ctx->v.parse_arg(ctx, c))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_help(cmd);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen argv += optind;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (argv[0] != NULL && cmd->usage_args == NULL) {
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen i_fatal("doveadm %s: Unknown parameter: %s",
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen cmd->name, argv[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->args = (const void *)argv;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->iterate_single_user =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen !ctx->iterate_all_users && wildcard_user == NULL;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen if (doveadm_print_is_initialized() && !ctx->iterate_single_user) {
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen doveadm_print_header("username", "Username",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_STICKY |
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen if (ctx->iterate_single_user) {
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen doveadm_mail_single_user(ctx, argv, username, service_flags);
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen doveadm_mail_all_users(ctx, argv, wildcard_user, service_flags);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_mail_server_flush();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ctx->v.deinit(ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_print_flush();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ctx->failed)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen exit(FATAL_DEFAULT);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ctx->search_args != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_search_args_unref(&ctx->search_args);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pool_unref(&ctx->pool);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic bool
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainendoveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *cmdname, int argc, char *argv[])
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int len;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (argc < 2)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen len = strlen(argv[1]);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strncmp(cmdname, argv[1], len) != 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (cmdname[len] == ' ') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* more args */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen argc - 1, argv + 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (cmdname[len] != '\0')
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen /* match */
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen doveadm_mail_cmd(cmd, argc - 1, argv + 1);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen return TRUE;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen}
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainenbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct doveadm_mail_cmd *cmd;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int cmd_name_len;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(argc > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen cmd_name_len = strlen(cmd_name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_cmd(cmd, argc, argv);
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen return TRUE;
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen }
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen /* see if it matches a multi-word command */
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen cmd->name[cmd_name_len] == ' ') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (doveadm_mail_try_run_multi_word(cmd, subcmd,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen argc, argv))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen{
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen /* for now we'll just assume that cmd will be permanently in memory */
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen array_append(&doveadm_mail_cmds, cmd, 1);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen}
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainenconst struct doveadm_mail_cmd *doveadm_mail_cmd_find(const char *cmd_name)
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen{
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen const struct doveadm_mail_cmd *cmd;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen return cmd;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen }
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen return NULL;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen}
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainenvoid doveadm_mail_usage(string_t *out)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen{
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen const struct doveadm_mail_cmd *cmd;
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen str_printfa(out, "%s\t[-u <user>|-A] [-S <socket_path>]",
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen cmd->name);
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen if (cmd->usage_args != NULL)
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen str_printfa(out, " %s", cmd->usage_args);
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen str_append_c(out, '\n');
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen }
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen}
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen fprintf(stderr, "doveadm %s [-u <user>|-A] [-S <socket_path>] %s\n",
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen cmd->name, cmd->usage_args == NULL ? "" : cmd->usage_args);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen exit(1);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenvoid doveadm_mail_try_help_name(const char *cmd_name)
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen{
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen const struct doveadm_mail_cmd *cmd;
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen cmd = doveadm_mail_cmd_find(cmd_name);
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen if (cmd != NULL)
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen doveadm_mail_help(cmd);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
1bea4b9c24fbe2b457950c09cf072292a6701cffTimo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenbool doveadm_mail_has_subcommands(const char *cmd_name)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const struct doveadm_mail_cmd *cmd;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen unsigned int len = strlen(cmd_name);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen if (strncmp(cmd->name, cmd_name, len) == 0 &&
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen cmd->name[len] == ' ')
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen return TRUE;
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen }
db693bf6fcae96d834567f1782257517b7207655Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainenvoid doveadm_mail_help_name(const char *cmd_name)
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen doveadm_mail_try_help_name(cmd_name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("Missing help for command %s", cmd_name);
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen}
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainenstatic struct doveadm_mail_cmd cmd_force_resync = {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen cmd_force_resync_alloc, "force-resync", "<mailbox>"
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen};
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainenstatic struct doveadm_mail_cmd cmd_purge = {
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen cmd_purge_alloc, "purge", NULL
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen};
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainenstatic struct doveadm_mail_cmd *mail_commands[] = {
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen &cmd_force_resync,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &cmd_purge,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &cmd_expunge,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen &cmd_search,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_fetch,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_import,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_altmove,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_mailbox_list,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_mailbox_create,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_mailbox_delete,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_mailbox_rename,
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen &cmd_mailbox_subscribe,
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen &cmd_mailbox_unsubscribe,
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen &cmd_mailbox_status
c668292359474a4aa8c608b30a858337fa3fc813Timo Sirainen};
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainenvoid doveadm_mail_init(void)
de70a6f77fc3b350eeee4e2a0d29dd07ddde431bTimo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct module_dir_load_settings mod_set;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_array_init(&doveadm_mail_cmds, 32);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands); i++)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen doveadm_mail_register_cmd(mail_commands[i]);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen memset(&mod_set, 0, sizeof(mod_set));
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mod_set.version = master_service_get_version_string(master_service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mod_set.require_init_funcs = TRUE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mod_set.debug = doveadm_debug;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mod_set.binary_name = "doveadm";
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* load all configured mail plugins */
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen mail_storage_service_modules =
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen module_dir_load_missing(mail_storage_service_modules,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen doveadm_settings->mail_plugin_dir,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen doveadm_settings->mail_plugins,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen &mod_set);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenvoid doveadm_mail_deinit(void)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen array_free(&doveadm_mail_cmds);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen