doveadm-mail.c revision 4fecb0a09c4d5d0300b047bfd9df5166ee555c9b
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib-signals.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "ioloop.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream-dot.h"
abf015c9682f0f723db87a7c97bc284ef814818fTimo Sirainen#include "istream-seekable.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "str.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "unichar.h"
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen#include "module-dir.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "wildcard-match.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "master-service.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-user.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-namespace.h"
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen#include "mail-storage.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-service.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-storage-hooks.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search-build.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mail-search-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "mailbox-list-iter.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "client-connection.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm-settings.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "doveadm-print.h"
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#include "doveadm-dsync.h"
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#include "doveadm-mail.h"
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#include <stdio.h>
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen#define DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS (5*60*1000)
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstruct doveadm_mail_cmd_module_register
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen doveadm_mail_cmd_module_register = { 0 };
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenchar doveadm_mail_cmd_hide = '\0';
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstatic int killed_signo = 0;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenbool doveadm_is_killed(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen return killed_signo != 0;
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint doveadm_killed_signo(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return killed_signo;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenvoid doveadm_mail_failed_error(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_error error)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen int exit_code = 0;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen switch (error) {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen case MAIL_ERROR_NONE:
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen i_unreached();
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen case MAIL_ERROR_TEMP:
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen exit_code = EX_TEMPFAIL;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen break;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen case MAIL_ERROR_NOTPOSSIBLE:
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen case MAIL_ERROR_EXISTS:
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen case MAIL_ERROR_CONVERSION:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case MAIL_ERROR_INVALIDDATA:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit_code = DOVEADM_EX_NOTPOSSIBLE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen break;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case MAIL_ERROR_PARAMS:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit_code = EX_USAGE;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen break;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case MAIL_ERROR_PERM:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit_code = EX_NOPERM;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen break;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case MAIL_ERROR_NOQUOTA:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit_code = EX_CANTCREAT;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen break;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case MAIL_ERROR_NOTFOUND:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen exit_code = DOVEADM_EX_NOTFOUND;
2eb2cf8eeb763bd5ca9b6848dce32f0303e88ec1Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case MAIL_ERROR_EXPUNGED:
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen case MAIL_ERROR_INUSE:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen exit_code = EX_TEMPFAIL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen }
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen /* tempfail overrides all other exit codes, otherwise use whatever
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen error happened first */
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ctx->exit_code = exit_code;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenvoid doveadm_mail_failed_storage(struct doveadm_mail_cmd_context *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mail_storage *storage)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen enum mail_error error;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(storage, &error);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen doveadm_mail_failed_error(ctx, error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid doveadm_mail_failed_mailbox(struct doveadm_mail_cmd_context *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mailbox *box)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen doveadm_mail_failed_storage(ctx, mailbox_get_storage(box));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenvoid doveadm_mail_failed_list(struct doveadm_mail_cmd_context *ctx,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mailbox_list *list)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen enum mail_error error;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen mailbox_list_get_last_error(list, &error);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen doveadm_mail_failed_error(ctx, error);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstruct doveadm_mail_cmd_context *
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainendoveadm_mail_cmd_alloc_size(size_t size)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct doveadm_mail_cmd_context *ctx;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen pool_t pool;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ctx = p_malloc(pool, size);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ctx->pool = pool;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return ctx;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic int
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mail_namespace *ns;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct mail_storage *storage;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen int ret = 0;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen ns->alias_for != NULL)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen continue;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen storage = mail_namespace_get_default_storage(ns);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_storage_purge(storage) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_get_last_error(storage, NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_failed_storage(ctx, storage);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct doveadm_mail_cmd_context *ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo 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;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void doveadm_mail_cmd_input_input(struct doveadm_mail_cmd_context *ctx)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen{
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen while (i_stream_read(ctx->cmd_input) > 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_skip(ctx->cmd_input, i_stream_get_data_size(ctx->cmd_input));
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (!ctx->cmd_input->eof)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->cmd_input->stream_errno != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("read(%s) failed: %s",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_get_name(ctx->cmd_input),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_get_error(ctx->cmd_input));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_loop_stop(current_ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic void doveadm_mail_cmd_input_timeout(struct doveadm_mail_cmd_context *ctx)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *input;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input = i_stream_create_error_str(ETIMEDOUT, "Timed out in %u secs",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS/1000);
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen i_stream_set_name(input, i_stream_get_name(ctx->cmd_input));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_destroy(&ctx->cmd_input);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->cmd_input = input;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen io_loop_stop(current_ioloop);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void doveadm_mail_cmd_input_read(struct doveadm_mail_cmd_context *ctx)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct ioloop *ioloop;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct io *io;
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen struct timeout *to;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ioloop = io_loop_create();
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io = io_add(ctx->cmd_input_fd, IO_READ,
d7ec773d995888b09c4d8c88a4b0b134a2002361Timo Sirainen doveadm_mail_cmd_input_input, ctx);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen to = timeout_add(DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_mail_cmd_input_timeout, ctx);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* read the pending input from stream. */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen io_loop_set_running(ioloop);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen doveadm_mail_cmd_input_input(ctx);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen if (io_loop_is_running(ioloop))
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen io_loop_run(ioloop);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen io_remove(&io);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen timeout_remove(&to);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen io_loop_destroy(&ioloop);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen i_assert(ctx->cmd_input->eof);
542e28b384a6b26695f3e8de38fd5727d06f3333Timo Sirainen i_stream_seek(ctx->cmd_input, 0);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainenvoid doveadm_mail_get_input(struct doveadm_mail_cmd_context *ctx)
18c209a06941ef583b08b173dadfbe4571995bf9Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *inputs[2];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->cmd_input != NULL)
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->conn != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen inputs[0] = i_stream_create_dot(ctx->conn->input, FALSE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen inputs[0] = i_stream_create_fd(STDIN_FILENO, 1024*1024, FALSE);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_stream_set_name(inputs[0], "stdin");
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen inputs[1] = NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen ctx->cmd_input_fd = i_stream_get_fd(inputs[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->cmd_input = i_stream_create_seekable_path(inputs, 1024*256,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "/tmp/doveadm.");
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen i_stream_set_name(ctx->cmd_input, i_stream_get_name(inputs[0]));
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_stream_unref(&inputs[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_cmd_input_read(ctx);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainenstruct mailbox *
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainendoveadm_mailbox_find(struct mail_user *user, const char *mailbox)
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct mail_namespace *ns;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!uni_utf8_str_is_valid(mailbox)) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_fatal_status(EX_DATAERR,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen "Mailbox name not valid UTF-8: %s", mailbox);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_IGNORE_ACLS);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstruct mail_search_args *
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainendoveadm_mail_build_search_args(const char *const args[])
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct mail_search_parser *parser;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct mail_search_args *sargs;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen const char *error, *charset = "UTF-8";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser = mail_search_parser_init_cmdline(args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mail_search_build(mail_search_register_get_human(),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen parser, &charset, &sargs, &error) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_fatal("%s", error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_search_parser_deinit(&parser);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return sargs;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen}
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int cmd_force_resync_box(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mailbox_info *info)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox *box;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen box = mailbox_alloc(info->ns->list, info->vname,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox_open(box) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Opening mailbox %s failed: %s", info->vname,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_get_last_error(box, NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_failed_mailbox(ctx, box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = -1;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen } else if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen info->vname, mailbox_get_last_error(box, NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_failed_mailbox(ctx, box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mailbox_free(&box);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenstatic int cmd_force_resync_run(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_user *user)
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen{
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen MAILBOX_LIST_ITER_STAR_WITHIN_NS;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const enum mail_namespace_type ns_mask = MAIL_NAMESPACE_TYPE_MASK_ALL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mailbox_list_iterate_context *iter;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct mailbox_info *info;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iter = mailbox_list_iter_init_namespaces(user->namespaces, ctx->args,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ns_mask, iter_flags);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if ((info->flags & (MAILBOX_NOSELECT |
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen MAILBOX_NONEXISTENT)) == 0) T_BEGIN {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (cmd_force_resync_box(ctx, info) < 0)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen ret = -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } T_END;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mailbox_list_iter_deinit(&iter) < 0) {
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen i_error("Listing mailboxes failed: %s",
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen mailbox_list_get_last_error(user->namespaces->list, NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_failed_list(ctx, user->namespaces->list);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = -1;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenstatic void
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainencmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen const char *const args[])
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen if (args[0] == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_help_name("force-resync");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct doveadm_mail_cmd_context *ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.init = cmd_force_resync_init;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.run = cmd_force_resync_run;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ctx;
9aceb071780a949f4e8bf41d3cf80735d9ac7fdfTimo Sirainen}
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenstatic void
9aceb071780a949f4e8bf41d3cf80735d9ac7fdfTimo Sirainendoveadm_cctx_to_storage_service_input(const struct doveadm_cmd_context *cctx,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen struct mail_storage_service_input *input_r)
9aceb071780a949f4e8bf41d3cf80735d9ac7fdfTimo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen memset(input_r, 0, sizeof(*input_r));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->service = "doveadm";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->remote_ip = cctx->remote_ip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->remote_port = cctx->remote_port;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->local_ip = cctx->local_ip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->local_port = cctx->local_port;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen input_r->username = cctx->username;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic int
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct doveadm_cmd_context *cctx,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen const char **error_r)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen struct mail_storage_service_input input;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen const char *error, *ip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen ip = net_ip2addr(&cctx->remote_ip);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen if (ip[0] == '\0')
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen i_set_failure_prefix("doveadm(%s): ", cctx->username);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen else
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen i_set_failure_prefix("doveadm(%s,%s): ", ip, cctx->username);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen doveadm_cctx_to_storage_service_input(cctx, &input);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen /* see if we want to execute this command via (another)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm server */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = doveadm_mail_server_user(ctx, &input, error_r);
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen if (ret != 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, &input,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &ctx->cur_service_user, &error);
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen if (ret <= 0) {
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen if (ret < 0) {
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->v.prerun != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->v.prerun(ctx, ctx->cur_service_user, error_r) < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return -1;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = mail_storage_service_next(ctx->storage_service,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->cur_service_user,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &ctx->cur_mail_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret < 0) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen *error_r = "User init failed";
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen return ret;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (ctx->cmd_input != NULL)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen i_stream_seek(ctx->cmd_input, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ctx->v.run(ctx, ctx->cur_mail_user) < 0) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen i_assert(ctx->exit_code != 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_user_unref(&ctx->cur_mail_user);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen mail_storage_service_user_free(&ctx->cur_service_user);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen return 1;
263946a65b625fd4198619a8626db0f36bbafd66Timo Sirainen}
263946a65b625fd4198619a8626db0f36bbafd66Timo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen{
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen killed_signo = si->si_signo;
02a6291366caff79793db35d479e2a062bec2af4Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainenint doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen const struct doveadm_cmd_context *cctx,
573085b4b25b0bbae8d27969df2c91702eefa23eTimo Sirainen const char **error_r)
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen{
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen i_assert(cctx->username != NULL);
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen
0ee3fdb5e94ae6f34cb873ca3c9858342621e55fTimo Sirainen doveadm_cctx_to_storage_service_input(cctx, &ctx->storage_service_input);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->cur_client_ip = cctx->remote_ip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->cur_username = cctx->username;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk ctx->storage_service = mail_storage_service_init(master_service, NULL,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->service_flags);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.init(ctx, ctx->args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (hook_doveadm_mail_init != NULL)
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen hook_doveadm_mail_init(ctx);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen lib_signals_set_handler(SIGINT, 0, sig_die, NULL);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen lib_signals_set_handler(SIGTERM, 0, sig_die, NULL);
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return doveadm_mail_next_user(ctx, cctx, error_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct doveadm_cmd_context *cctx,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *wildcard_user)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen{
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen unsigned int user_idx;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen const char *ip, *user, *error;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen int ret;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen doveadm_cctx_to_storage_service_input(cctx, &ctx->storage_service_input);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen ctx->service_flags);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen lib_signals_set_handler(SIGINT, 0, sig_die, NULL);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen lib_signals_set_handler(SIGTERM, 0, sig_die, NULL);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen ctx->v.init(ctx, ctx->args);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen mail_storage_service_all_init_mask(ctx->storage_service,
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen wildcard_user != NULL ? wildcard_user : "");
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (hook_doveadm_mail_init != NULL)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen hook_doveadm_mail_init(ctx);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen user_idx = 0;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (wildcard_user != NULL) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen continue;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen cctx->username = user;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen ctx->cur_username = user;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen doveadm_print_sticky("username", user);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen T_BEGIN {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen ret = doveadm_mail_next_user(ctx, cctx, &error);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (ret < 0)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen i_error("%s", error);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen else if (ret == 0)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen i_info("User no longer exists, skipping");
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen } T_END;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (ret == -1)
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen break;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (doveadm_verbose) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (++user_idx % 100 == 0) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen printf("\r%d", user_idx);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen fflush(stdout);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen if (killed_signo != 0) {
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen i_warning("Killed with signal %d", killed_signo);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen ret = -1;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen break;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (doveadm_verbose)
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen printf("\n");
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen ip = net_ip2addr(&ctx->cur_client_ip);
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (ip[0] == '\0')
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen i_set_failure_prefix("doveadm: ");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen else
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_set_failure_prefix("doveadm(%s): ", ip);
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen if (ret < 0) {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen i_error("Failed to iterate through some users");
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen ctx->exit_code = EX_TEMPFAIL;
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic void
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen const char *const args[] ATTR_UNUSED)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen{
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic int
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen const char **username_r)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen{
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (ctx->users_list_input == NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen *username_r = i_stream_read_next_line(ctx->users_list_input);
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (ctx->users_list_input->stream_errno != 0) {
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_error("read(%s) failed: %s",
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_stream_get_name(ctx->users_list_input),
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen i_stream_get_error(ctx->users_list_input));
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return -1;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen }
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen return *username_r != NULL ? 1 : 0;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstatic void
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen{
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen}
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainenstruct doveadm_mail_cmd_context *
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainendoveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const struct doveadm_settings *set)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct doveadm_mail_cmd_context *ctx;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx = cmd->alloc();
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->set = set;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ctx->cmd = cmd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ctx->v.init == NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx->v.init = doveadm_mail_cmd_init_noop;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ctx->v.get_next_user == NULL)
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
c3a636e4c9ae776e0eed06b6d7ad1ccfb6003afdTimo Sirainen if (ctx->v.deinit == NULL)
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainen ctx->v.deinit = doveadm_mail_cmd_deinit_noop;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen p_array_init(&ctx->module_contexts, ctx->pool, 5);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return ctx;
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenstatic struct doveadm_mail_cmd_context *
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainendoveadm_mail_cmdline_init(const struct doveadm_mail_cmd *cmd)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen struct doveadm_mail_cmd_context *ctx;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx = doveadm_mail_cmd_init(cmd, doveadm_settings);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (doveadm_debug)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return ctx;
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen}
878a83a906e1be6354b563ead096955a22ad5fbeTimo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic void
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainendoveadm_mail_cmd_exec(struct doveadm_mail_cmd_context *ctx,
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen struct doveadm_cmd_context *cctx,
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen const char *wildcard_user)
b879ed8dd4b5850987e6b89a92f794d87c6be7d7Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int ret;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char *error;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen if (ctx->v.preinit != NULL)
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen ctx->v.preinit(ctx);
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen ctx->iterate_single_user =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen !ctx->iterate_all_users && wildcard_user == NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (doveadm_print_is_initialized() && !ctx->iterate_single_user) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_print_header("username", "Username",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_STICKY |
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen if (ctx->iterate_single_user) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ctx->cur_username == NULL)
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen i_fatal_status(EX_USAGE, "USER environment is missing and -u option not used");
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen if (!ctx->cli) {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* we may access multiple users */
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ret = doveadm_mail_single_user(ctx, cctx, &error);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (ret < 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* user lookup/init failed somehow */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_exit_code = EX_TEMPFAIL;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen i_error("%s", error);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen } else if (ret == 0) {
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainen doveadm_exit_code = EX_NOUSER;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen i_error("User doesn't exist");
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen } else {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen doveadm_mail_all_users(ctx, cctx, wildcard_user);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen }
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (ctx->search_args != NULL)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mail_search_args_unref(&ctx->search_args);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen doveadm_mail_server_flush();
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen ctx->v.deinit(ctx);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_print_flush();
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* service deinit unloads mail plugins, so do it late */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ctx->exit_code != 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_exit_code = ctx->exit_code;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainenstatic void doveadm_mail_cmd_free(struct doveadm_mail_cmd_context *ctx)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen if (ctx->users_list_input != NULL)
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen i_stream_unref(&ctx->users_list_input);
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen if (ctx->cmd_input != NULL)
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen i_stream_unref(&ctx->cmd_input);
faca2afa3576c50caf28e0f009555325d2a49e0bTimo Sirainen pool_unref(&ctx->pool);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
dbe06905918a415a34c5621b9fdf45be0b9c8e64Timo Sirainenstatic void
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainendoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
674f541b16689c0ed090dac32db94463c5af3977Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen struct doveadm_cmd_context cctx;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen struct doveadm_mail_cmd_context *ctx;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen const char *getopt_args, *wildcard_user;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen int c;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ctx = doveadm_mail_cmdline_init(cmd);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen ctx->full_args = (const void *)(argv + 1);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen ctx->cli = TRUE;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen ctx->cur_username = getenv("USER");
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen memset(&cctx, 0, sizeof(cctx));
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen getopt_args = "AF:S:u:";
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen /* keep context's getopt_args first in case it contains '+' */
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (ctx->getopt_args != NULL)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen getopt_args = t_strconcat(ctx->getopt_args, getopt_args, NULL);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_assert(master_getopt_str_is_valid(getopt_args));
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen wildcard_user = NULL;
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen while ((c = getopt(argc, argv, getopt_args)) > 0) {
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen switch (c) {
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen case 'A':
9b78c0d5e13141f4df6c6e483f854e5acb861288Timo Sirainen ctx->iterate_all_users = TRUE;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen break;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen case 'S':
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen doveadm_settings->doveadm_socket_path = optarg;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen if (doveadm_settings->doveadm_worker_count == 0)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen doveadm_settings->doveadm_worker_count = 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 'u':
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen ctx->service_flags |=
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen ctx->cur_username = optarg;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (strchr(ctx->cur_username, '*') != NULL ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen strchr(ctx->cur_username, '?') != NULL) {
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen wildcard_user = ctx->cur_username;
f934b271c69c7b3e5e3bca23ff9b3ab6187262c2Timo Sirainen ctx->cur_username = NULL;
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen }
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen break;
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen case 'F':
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen ctx->service_flags |=
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen wildcard_user = "*";
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen ctx->users_list_input =
c5a6a6565be93224fc26522eda855b0990f256e8Timo Sirainen i_stream_create_file(optarg, 1024);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen default:
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (ctx->v.parse_arg == NULL ||
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen !ctx->v.parse_arg(ctx, c))
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen doveadm_mail_help(cmd);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen }
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen }
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen argv += optind;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen if (argv[0] != NULL && cmd->usage_args == NULL) {
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen i_fatal_status(EX_USAGE, "doveadm %s: Unknown parameter: %s",
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen cmd->name, argv[0]);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen }
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen ctx->args = (const void *)argv;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen cctx.username = ctx->cur_username;
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen doveadm_mail_cmd_exec(ctx, &cctx, wildcard_user);
b7835adbfddd8c92b51d6653fb759f963302fa78Timo Sirainen doveadm_mail_cmd_free(ctx);
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen}
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainenstatic bool
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainendoveadm_mail_cmd_try_find_multi_word(const struct doveadm_mail_cmd *cmd,
72f2a851238e5661695c63bff0e9a9e800ba577aTimo Sirainen const char *cmdname, int *argc,
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen const char *const **argv)
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen{
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen unsigned int len;
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen if (*argc < 2)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen return FALSE;
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen *argc -= 1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen *argv += 1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen len = strlen((*argv)[0]);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (strncmp(cmdname, (*argv)[0], len) != 0)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return FALSE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (cmdname[len] == ' ') {
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen /* more args */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return doveadm_mail_cmd_try_find_multi_word(cmd, cmdname + len + 1,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen argc, argv);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (cmdname[len] != '\0')
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return FALSE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* match */
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen return TRUE;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen}
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainenconst struct doveadm_mail_cmd *
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainendoveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen const char *const **argv)
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen const struct doveadm_mail_cmd *cmd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen unsigned int cmd_name_len;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen const char *const *orig_argv;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen int orig_argc;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_assert(*argc > 0);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen cmd_name_len = strlen(cmd_name);
9ba7e76c20be775f368254e3059a6189fe789f16Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return cmd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* see if it matches a multi-word command */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen cmd->name[cmd_name_len] == ' ') {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen orig_argc = *argc;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen orig_argv = *argv;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (doveadm_mail_cmd_try_find_multi_word(cmd, subcmd,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen argc, argv))
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return cmd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen *argc = orig_argc;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *argv = orig_argv;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen return NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainenbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen{
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const struct doveadm_mail_cmd *cmd;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
abb9b8f14e83baca887cf12210bfe480f6cde7a6Timo Sirainen cmd = doveadm_mail_cmd_find_from_argv(cmd_name, &argc, (void *)&argv);
abb9b8f14e83baca887cf12210bfe480f6cde7a6Timo Sirainen if (cmd == NULL)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_mail_cmd(cmd, argc, argv);
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen return TRUE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* for now we'll just assume that cmd will be permanently in memory */
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen array_append(&doveadm_mail_cmds, cmd, 1);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenconst struct doveadm_mail_cmd *doveadm_mail_cmd_find(const char *cmd_name)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen const struct doveadm_mail_cmd *cmd;
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen return cmd;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen }
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen return NULL;
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen}
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainenvoid doveadm_mail_usage(string_t *out)
57ff998a443881c8959a8e65f6325cf19fefc1d0Timo Sirainen{
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen const struct doveadm_mail_cmd *cmd;
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen if (cmd->usage_args == &doveadm_mail_cmd_hide)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen continue;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen str_printfa(out, "%s\t"DOVEADM_CMD_MAIL_USAGE_PREFIX, cmd->name);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (cmd->usage_args != NULL)
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen str_append(out, cmd->usage_args);
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen str_append_c(out, '\n');
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen }
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen}
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainenvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen{
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen fprintf(stderr, "doveadm %s "DOVEADM_CMD_MAIL_USAGE_PREFIX" %s\n",
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen cmd->name, cmd->usage_args == NULL ? "" : cmd->usage_args);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen exit(EX_USAGE);
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen}
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainenvoid doveadm_mail_try_help_name(const char *cmd_name)
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen{
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen const struct doveadm_cmd_ver2 *cmd2;
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen const struct doveadm_mail_cmd *cmd;
fa2a11210f20fb8998ed656f75e163191c8047e6Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen cmd2 = doveadm_cmd_find_ver2(cmd_name);
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (cmd2 != NULL)
63fc74d46d781e87edb6388e51a5bf942c5f8eabTimo Sirainen help_ver2(cmd2);
63fc74d46d781e87edb6388e51a5bf942c5f8eabTimo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen cmd = doveadm_mail_cmd_find(cmd_name);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen if (cmd != NULL)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_mail_help(cmd);
705f6fbad395e6f014838e797b7dbcaceafd2f1dTimo Sirainen}
8f5b34c22e4c3bfb35ca13c4744867eb5ddbd3d6Timo Sirainen
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainenbool doveadm_mail_has_subcommands(const char *cmd_name)
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen{
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen const struct doveadm_mail_cmd *cmd;
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen unsigned int len = strlen(cmd_name);
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen if (strncmp(cmd->name, cmd_name, len) == 0 &&
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen cmd->name[len] == ' ')
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen return TRUE;
95d9395d15540b3a96f75c7f9fd73e6d8ad5e897Timo Sirainen }
95d9395d15540b3a96f75c7f9fd73e6d8ad5e897Timo Sirainen return FALSE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen}
1b04762685272a53643ac2179939537a44c7c044Timo Sirainen
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainenvoid doveadm_mail_help_name(const char *cmd_name)
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen{
48ada47cce07fb7195a3437224c7c25f542326b0Timo Sirainen doveadm_mail_try_help_name(cmd_name);
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen i_fatal("Missing help for command %s", cmd_name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct doveadm_cmd_ver2 doveadm_cmd_force_resync_ver2 = {
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen .name = "force-resync",
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen .mail_cmd = cmd_force_resync_alloc,
f38485358ffc04c3466b917770575e29deef24c3Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX "<mailbox mask>",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo SirainenDOVEADM_CMD_PARAMS_START
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo SirainenDOVEADM_CMD_MAIL_COMMON
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo SirainenDOVEADM_CMD_PARAM('\0', "mailbox-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo SirainenDOVEADM_CMD_PARAMS_END
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen};
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo Sirainenstatic struct doveadm_cmd_ver2 doveadm_cmd_purge_ver2 = {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen .name = "purge",
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen .mail_cmd = cmd_purge_alloc,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen .usage = DOVEADM_CMD_MAIL_USAGE_PREFIX,
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo SirainenDOVEADM_CMD_PARAMS_START
c07d7eb3ca9754367697c98f5e66a3982a45d142Timo SirainenDOVEADM_CMD_MAIL_COMMON
8d3278a82b964217d95c340ec6f82037cdc59d19Timo SirainenDOVEADM_CMD_PARAMS_END
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen};
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenstatic struct doveadm_mail_cmd *mail_commands[] = {
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen &cmd_batch,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen &cmd_dsync_backup,
367e28a16854ee9f7247b2518f36f5e9163fcc10Timo Sirainen &cmd_dsync_mirror,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen &cmd_dsync_server
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainenstatic struct doveadm_cmd_ver2 *mail_commands_ver2[] = {
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_metadata_set_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_metadata_unset_ver2,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen &doveadm_cmd_mailbox_metadata_get_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_metadata_list_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_status_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_list_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_create_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_delete_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_mailbox_rename_ver2,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen &doveadm_cmd_mailbox_subscribe_ver2,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen &doveadm_cmd_mailbox_unsubscribe_ver2,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen &doveadm_cmd_mailbox_update_ver2,
c06d6ea0766d0520af1a93e6000c0e73f350e0a2Timo Sirainen &doveadm_cmd_fetch_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_save_ver2,
62fc2fe221eccc834ac6b11b94b55335d5027cd1Timo Sirainen &doveadm_cmd_index_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_altmove_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_deduplicate_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_expunge_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_flags_add_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_flags_remove_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_flags_replace_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_import_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_force_resync_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_purge_ver2,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen &doveadm_cmd_search_ver2,
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen &doveadm_cmd_copy_ver2,
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen &doveadm_cmd_move_ver2
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen};
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainenvoid doveadm_mail_init(void)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen{
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen struct module_dir_load_settings mod_set;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen unsigned int i;
3b22894b8805b186c73d8b754001e8d7e944be85Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_array_init(&doveadm_mail_cmds, 32);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands); i++)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_mail_register_cmd(mail_commands[i]);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands_ver2); i++)
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen doveadm_cmd_register_ver2(mail_commands_ver2[i]);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen memset(&mod_set, 0, sizeof(mod_set));
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mod_set.abi_version = DOVECOT_ABI_VERSION;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mod_set.require_init_funcs = TRUE;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen mod_set.debug = doveadm_debug;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mod_set.binary_name = "doveadm";
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen /* load all configured mail plugins */
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen mail_storage_service_modules =
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen module_dir_load_missing(mail_storage_service_modules,
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen doveadm_settings->mail_plugin_dir,
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen doveadm_settings->mail_plugins,
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen &mod_set);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen}
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainenvoid doveadm_mail_deinit(void)
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen{
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen mail_storage_hooks_deinit();
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen array_free(&doveadm_mail_cmds);
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen}
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainenvoid
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainendoveadm_cmd_ver2_to_mail_cmd_wrapper(struct doveadm_cmd_context *cctx)
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen{
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen struct doveadm_mail_cmd_context *mctx;
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen const char *wildcard_user;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen const char *fieldstr;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen ARRAY_TYPE(const_string) pargv, full_args;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen int i;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen struct doveadm_mail_cmd mail_cmd = {
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen cctx->cmd->mail_cmd, cctx->cmd->name, cctx->cmd->usage
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen };
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen if (!cctx->cli) {
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen mctx = doveadm_mail_cmd_init(&mail_cmd, doveadm_settings);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen /* doveadm-server always does userdb lookups */
97180ea9c26c4de0807daaad21e03c80643b09fdTimo Sirainen mctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
88b315f36ba082708ab6f53ea1924c54d9be0aefTimo Sirainen } else {
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen mctx = doveadm_mail_cmdline_init(&mail_cmd);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen }
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen mctx->cur_username = cctx->username;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen mctx->iterate_all_users = FALSE;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen wildcard_user = NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen p_array_init(&full_args, mctx->pool, 8);
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen p_array_init(&pargv, mctx->pool, 8);
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen for(i=0;i<cctx->argc;i++) {
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen const struct doveadm_cmd_param *arg = &cctx->argv[i];
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen if (!arg->value_set)
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen continue;
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen if (strcmp(arg->name, "all-users") == 0) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mctx->iterate_all_users = arg->value.v_bool;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen fieldstr = "-A";
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen array_append(&full_args, &fieldstr, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (strcmp(arg->name, "socket-path") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen doveadm_settings->doveadm_socket_path = arg->value.v_string;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen if (doveadm_settings->doveadm_worker_count == 0)
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen doveadm_settings->doveadm_worker_count = 1;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen } else if (strcmp(arg->name, "user") == 0) {
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mctx->cur_username = arg->value.v_string;
fa2433aebcf3fccfa30ca9eed9b1a9166cf92ee2Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen fieldstr = "-u";
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen array_append(&full_args, &fieldstr, 1);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen array_append(&full_args, &arg->value.v_string, 1);
5d03d9f439e41c90215a3c938ffebe4c2a8ae257Timo Sirainen if (strchr(mctx->cur_username, '*') != NULL ||
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen strchr(mctx->cur_username, '?') != NULL) {
38f227941bcf673e0e523c1ac7267bca9cbcd2c4Timo Sirainen wildcard_user = mctx->cur_username;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen mctx->cur_username = NULL;
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen cctx->username = mctx->cur_username;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen } else if (strcmp(arg->name, "user-file") == 0) {
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen wildcard_user = "*";
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen mctx->users_list_input = arg->value.v_istream;
47e9fdee55c2074425cf0316f4f64fbbb790301cTimo Sirainen fieldstr = "-F";
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen array_append(&full_args, &fieldstr, 1);
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen fieldstr = ""; /* value doesn't really matter */
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen array_append(&full_args, &fieldstr, 1);
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen i_stream_ref(mctx->users_list_input);
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen } else if (strcmp(arg->name, "field") == 0 ||
7e95ba7f38b9b421287d36c6152f8a9e6b9f225bTimo Sirainen strcmp(arg->name, "flag") == 0) {
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen /* mailbox status, fetch, flags: convert an array into a
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen single space-separated parameter (alternative to
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen fieldstr) */
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen fieldstr = p_array_const_string_join(mctx->pool,
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen &arg->value.v_array, " ");
608bdb7f008cd5cd332d727018a9e8173abec998Timo Sirainen array_append(&pargv, &fieldstr, 1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (strcmp(arg->name, "file") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* input for doveadm_mail_get_input(),
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen used by e.g. save */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mctx->cmd_input != NULL) {
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen i_error("Only one file input allowed: %s", arg->name);
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen doveadm_mail_cmd_free(mctx);
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen doveadm_exit_code = EX_USAGE;
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen return;
2eb0402a28bd0422e0170160808c67d6c7274689Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen mctx->cmd_input = arg->value.v_istream;
i_stream_ref(mctx->cmd_input);
/* Keep all named special parameters above this line */
} else if (mctx->v.parse_arg != NULL && arg->short_opt != '\0') {
const char *short_opt_str = p_strdup_printf(
mctx->pool, "-%c", arg->short_opt);
optarg = (char*)arg->value.v_string;
mctx->v.parse_arg(mctx, arg->short_opt);
array_append(&full_args, &short_opt_str, 1);
if (arg->type == CMD_PARAM_STR)
array_append(&full_args, &arg->value.v_string, 1);
} else if ((arg->flags & CMD_PARAM_FLAG_POSITIONAL) != 0) {
/* feed this into pargv */
if (arg->type == CMD_PARAM_ARRAY)
array_append_array(&pargv, &arg->value.v_array);
else if (arg->type == CMD_PARAM_STR)
array_append(&pargv, &arg->value.v_string, 1);
} else {
doveadm_exit_code = EX_USAGE;
i_error("invalid parameter: %s", arg->name);
doveadm_mail_cmd_free(mctx);
return;
}
}
array_append_zero(&pargv);
/* All the -parameters need to be included in full_args so that
they're sent to doveadm-server. */
unsigned int args_pos = array_count(&full_args);
array_append_array(&full_args, &pargv);
mctx->args = array_idx(&full_args, args_pos);
mctx->full_args = array_idx(&full_args, 0);
mctx->cli = cctx->cli;
doveadm_mail_cmd_exec(mctx, cctx, wildcard_user);
doveadm_mail_cmd_free(mctx);
}