doveadm-mail.c revision 844929a7bd6e9d21f0a8cdb3a19f4620a17cdeca
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "lib.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "array.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "lib-signals.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "ioloop.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "istream.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "istream-dot.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "istream-seekable.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "str.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "unichar.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "module-dir.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "wildcard-match.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "master-service.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-user.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-namespace.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-storage.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-storage-settings.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-storage-service.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-storage-hooks.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-search-build.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mail-search-parser.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "mailbox-list-iter.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "client-connection.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "doveadm.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "doveadm-settings.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "doveadm-print.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "doveadm-dsync.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include "doveadm-mail.h"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#include <stdio.h>
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch#define DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS (5*60*1000)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan BoschARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct doveadm_mail_cmd_module_register
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_module_register = { 0 };
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschchar doveadm_mail_cmd_hide = '\0';
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int killed_signo = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool doveadm_is_killed(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return killed_signo != 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschint doveadm_killed_signo(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return killed_signo;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_failed_error(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum mail_error error)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int exit_code = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch switch (error) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_NONE:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_unreached();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_TEMP:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = EX_TEMPFAIL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_NOTPOSSIBLE:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_EXISTS:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_CONVERSION:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_INVALIDDATA:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = DOVEADM_EX_NOTPOSSIBLE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_PARAMS:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = EX_USAGE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_PERM:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = EX_NOPERM;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_NOQUOTA:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = EX_CANTCREAT;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_NOTFOUND:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = DOVEADM_EX_NOTFOUND;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_EXPUNGED:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case MAIL_ERROR_INUSE:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit_code = EX_TEMPFAIL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* tempfail overrides all other exit codes, otherwise use whatever
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch error happened first */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->exit_code == 0 || exit_code == EX_TEMPFAIL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->exit_code = exit_code;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_failed_storage(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_storage *storage)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum mail_error error;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_get_last_error(storage, &error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_error(ctx, error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_failed_mailbox(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mailbox *box)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_storage(ctx, mailbox_get_storage(box));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_failed_list(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mailbox_list *list)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch enum mail_error error;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mailbox_list_get_last_error(list, &error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_error(ctx, error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct doveadm_mail_cmd_context *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_alloc_size(size_t size)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch pool_t pool;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch pool = pool_alloconly_create("doveadm mail cmd", 1024);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = p_malloc(pool, size);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->pool = pool;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschcmd_purge_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_namespace *ns;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_storage *storage;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (ns = user->namespaces; ns != NULL; ns = ns->next) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE ||
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ns->alias_for != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch continue;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch storage = mail_namespace_get_default_storage(ns);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (mail_storage_purge(storage) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Purging namespace '%s' failed: %s", ns->prefix,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_get_last_error(storage, NULL));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_storage(ctx, storage);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.run = cmd_purge_run;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void doveadm_mail_cmd_input_input(struct doveadm_mail_cmd_context *ctx)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while (i_stream_read(ctx->cmd_input) > 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_skip(ctx->cmd_input, i_stream_get_data_size(ctx->cmd_input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!ctx->cmd_input->eof)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cmd_input->stream_errno != 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("read(%s) failed: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_get_name(ctx->cmd_input),
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_get_error(ctx->cmd_input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_loop_stop(current_ioloop);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void doveadm_mail_cmd_input_timeout(struct doveadm_mail_cmd_context *ctx)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch input = i_stream_create_error_str(ETIMEDOUT, "Timed out in %u secs",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS/1000);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_set_name(input, i_stream_get_name(ctx->cmd_input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_destroy(&ctx->cmd_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cmd_input = input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_loop_stop(current_ioloop);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void doveadm_mail_cmd_input_read(struct doveadm_mail_cmd_context *ctx)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct ioloop *ioloop;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct io *io;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct timeout *to;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ioloop = io_loop_create();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io = io_add(ctx->cmd_input_fd, IO_READ,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_input_input, ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch to = timeout_add(DOVEADM_MAIL_CMD_INPUT_TIMEOUT_MSECS,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_input_timeout, ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* read the pending input from stream. */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_loop_set_running(ioloop);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_input_input(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (io_loop_is_running(ioloop))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_loop_run(ioloop);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_remove(&io);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch timeout_remove(&to);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch io_loop_destroy(&ioloop);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(ctx->cmd_input->eof);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_seek(ctx->cmd_input, 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_get_input(struct doveadm_mail_cmd_context *ctx)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct istream *inputs[2];
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cmd_input != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->conn != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch inputs[0] = i_stream_create_dot(ctx->conn->input, FALSE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch inputs[0] = i_stream_create_fd(STDIN_FILENO, 1024*1024, FALSE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_set_name(inputs[0], "stdin");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch inputs[1] = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cmd_input_fd = i_stream_get_fd(inputs[0]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cmd_input = i_stream_create_seekable_path(inputs, 1024*256,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch "/tmp/doveadm.");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_set_name(ctx->cmd_input, i_stream_get_name(inputs[0]));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_unref(&inputs[0]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_input_read(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct mailbox *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mailbox_find(struct mail_user *user, const char *mailbox)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_namespace *ns;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!uni_utf8_str_is_valid(mailbox)) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_fatal_status(EX_DATAERR,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch "Mailbox name not valid UTF-8: %s", mailbox);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ns = mail_namespace_find(user->namespaces, mailbox);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_IGNORE_ACLS);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct mail_search_args *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_build_search_args(const char *const args[])
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_search_parser *parser;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_search_args *sargs;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *error, *charset = "UTF-8";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch parser = mail_search_parser_init_cmdline(args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (mail_search_build(mail_search_register_get_human(),
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch parser, &charset, &sargs, &error) < 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_fatal("%s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_search_parser_deinit(&parser);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return sargs;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int cmd_force_resync_box(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct mailbox_info *info)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mailbox *box;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch box = mailbox_alloc(info->ns->list, info->vname,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAILBOX_FLAG_IGNORE_ACLS);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (mailbox_open(box) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Opening mailbox %s failed: %s", info->vname,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mailbox_get_last_error(box, NULL));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_mailbox(ctx, box);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Forcing a resync on mailbox %s failed: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch info->vname, mailbox_get_last_error(box, NULL));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_mailbox(ctx, box);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mailbox_free(&box);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int cmd_force_resync_run(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_user *user)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const enum mailbox_list_iter_flags iter_flags =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAILBOX_LIST_ITER_STAR_WITHIN_NS;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const enum mail_namespace_type ns_mask = MAIL_NAMESPACE_TYPE_MASK_ALL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mailbox_list_iterate_context *iter;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct mailbox_info *info;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch iter = mailbox_list_iter_init_namespaces(user->namespaces, ctx->args,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ns_mask, iter_flags);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while ((info = mailbox_list_iter_next(iter)) != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if ((info->flags & (MAILBOX_NOSELECT |
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAILBOX_NONEXISTENT)) == 0) T_BEGIN {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd_force_resync_box(ctx, info) < 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } T_END;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (mailbox_list_iter_deinit(&iter) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Listing mailboxes failed: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mailbox_list_get_last_error(user->namespaces->list, NULL));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_failed_list(ctx, user->namespaces->list);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschcmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const args[])
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (args[0] == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_help_name("force-resync");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.init = cmd_force_resync_init;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.run = cmd_force_resync_run;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct mail_storage_service_input *input,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char **error_r)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *error, *ip;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ip = net_ip2addr(&input->remote_ip);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ip[0] == '\0')
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_set_failure_prefix("doveadm(%s): ", input->username);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_set_failure_prefix("doveadm(%s,%s): ", ip, input->username);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* see if we want to execute this command via (another)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm server */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = doveadm_mail_server_user(ctx, input, error_r);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret != 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = mail_storage_service_lookup(ctx->storage_service, input,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &ctx->cur_service_user, &error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret <= 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *error_r = t_strdup_printf("User lookup failed: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.prerun != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.prerun(ctx, ctx->cur_service_user, error_r) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_user_free(&ctx->cur_service_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = mail_storage_service_next(ctx->storage_service,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_service_user,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &ctx->cur_mail_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *error_r = "User init failed";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_user_free(&ctx->cur_service_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cmd_input != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_seek(ctx->cmd_input, 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.run(ctx, ctx->cur_mail_user) < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(ctx->exit_code != 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_user_unref(&ctx->cur_mail_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_user_free(&ctx->cur_service_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch killed_signo = si->si_signo;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschint doveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct mail_storage_service_input *input,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char **error_r)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(input->username != NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_client_ip = input->remote_ip;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = input->username;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->storage_service_input = *input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->storage_service = mail_storage_service_init(master_service, NULL,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.init(ctx, ctx->args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (hook_doveadm_mail_init != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch hook_doveadm_mail_init(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch lib_signals_set_handler(SIGINT, 0, sig_die, NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch lib_signals_set_handler(SIGTERM, 0, sig_die, NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return doveadm_mail_next_user(ctx, input, error_r);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *wildcard_user)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_storage_service_input input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int user_idx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *ip, *user, *error;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch memset(&input, 0, sizeof(input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch input.service = "doveadm";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->storage_service_input = input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->storage_service = mail_storage_service_init(master_service, NULL,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch lib_signals_set_handler(SIGINT, 0, sig_die, NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch lib_signals_set_handler(SIGTERM, 0, sig_die, NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.init(ctx, ctx->args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_all_init(ctx->storage_service);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (hook_doveadm_mail_init != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch hook_doveadm_mail_init(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch user_idx = 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (wildcard_user != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!wildcard_match_icase(user, wildcard_user))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch continue;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch input.username = user;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = user;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_print_sticky("username", user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch T_BEGIN {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = doveadm_mail_next_user(ctx, &input, &error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret < 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("%s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (ret == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_info("User no longer exists, skipping");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } T_END;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret == -1)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_verbose) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (++user_idx % 100 == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch printf("\r%d", user_idx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch fflush(stdout);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (killed_signo != 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_warning("Killed with signal %d", killed_signo);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_verbose)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch printf("\n");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ip = net_ip2addr(&ctx->cur_client_ip);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ip[0] == '\0')
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_set_failure_prefix("doveadm: ");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_set_failure_prefix("doveadm(%s): ", ip);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Failed to iterate through some users");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->exit_code = EX_TEMPFAIL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const args[] ATTR_UNUSED)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic int
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char **username_r)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->users_list_input == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return mail_storage_service_all_next(ctx->storage_service, username_r);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *username_r = i_stream_read_next_line(ctx->users_list_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->users_list_input->stream_errno != 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("read(%s) failed: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_get_name(ctx->users_list_input),
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_get_error(ctx->users_list_input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return -1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return *username_r != NULL ? 1 : 0;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstruct doveadm_mail_cmd_context *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_settings *set)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = cmd->alloc();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->set = set;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cmd = cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.init == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.init = doveadm_mail_cmd_init_noop;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.get_next_user == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.deinit == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.deinit = doveadm_mail_cmd_deinit_noop;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch p_array_init(&ctx->module_contexts, ctx->pool, 5);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd_context *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmdline_init(const struct doveadm_mail_cmd *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = doveadm_mail_cmd_init(cmd, doveadm_settings);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_debug)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = getenv("USER");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_exec(struct doveadm_mail_cmd_context *ctx,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *wildcard_user)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int ret;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *error;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.preinit != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.preinit(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->iterate_single_user =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch !ctx->iterate_all_users && wildcard_user == NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_print_is_initialized() && !ctx->iterate_single_user) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_print_header("username", "Username",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch DOVEADM_PRINT_HEADER_FLAG_STICKY |
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->iterate_single_user) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct mail_storage_service_input input;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cur_username == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_fatal_status(EX_USAGE, "USER environment is missing and -u option not used");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch memset(&input, 0, sizeof(input));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch input.service = "doveadm";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch input.username = ctx->cur_username;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ret = doveadm_mail_single_user(ctx, &input, &error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ret < 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* user lookup/init failed somehow */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_exit_code = EX_TEMPFAIL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("%s", error);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (ret == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_exit_code = EX_NOUSER;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("User doesn't exist");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_all_users(ctx, wildcard_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->search_args != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_search_args_unref(&ctx->search_args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_server_flush();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.deinit(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_print_flush();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* service deinit unloads mail plugins, so do it late */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_deinit(&ctx->storage_service);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->exit_code != 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_exit_code = ctx->exit_code;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void doveadm_mail_cmd_free(struct doveadm_mail_cmd_context *ctx)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->users_list_input != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_unref(&ctx->users_list_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cmd_input != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_unref(&ctx->cmd_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch pool_unref(&ctx->pool);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic void
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *getopt_args, *wildcard_user;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int c;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = doveadm_mail_cmdline_init(cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->full_args = (const void *)(argv + 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch getopt_args = "AF:S:u:";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* keep context's getopt_args first in case it contains '+' */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->getopt_args != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch getopt_args = t_strconcat(ctx->getopt_args, getopt_args, NULL);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(master_getopt_str_is_valid(getopt_args));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch while ((c = getopt(argc, argv, getopt_args)) > 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch switch (c) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case 'A':
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->iterate_all_users = TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case 'S':
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->doveadm_socket_path = optarg;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_settings->doveadm_worker_count == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->doveadm_worker_count = 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case 'u':
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |=
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = optarg;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strchr(ctx->cur_username, '*') != NULL ||
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch strchr(ctx->cur_username, '?') != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = ctx->cur_username;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch case 'F':
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |=
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = "*";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->users_list_input =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_create_file(optarg, 1024);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch break;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch default:
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->v.parse_arg == NULL ||
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch !ctx->v.parse_arg(ctx, c))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_help(cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch argv += optind;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (argv[0] != NULL && cmd->usage_args == NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_fatal_status(EX_USAGE, "doveadm %s: Unknown parameter: %s",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd->name, argv[0]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->args = (const void *)argv;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_exec(ctx, wildcard_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_free(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic bool
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_try_find_multi_word(const struct doveadm_mail_cmd *cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *cmdname, int *argc,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const **argv)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int len;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (*argc < 2)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *argc -= 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *argv += 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch len = strlen((*argv)[0]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strncmp(cmdname, (*argv)[0], len) != 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmdname[len] == ' ') {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* more args */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return doveadm_mail_cmd_try_find_multi_word(cmd, cmdname + len + 1,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch argc, argv);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmdname[len] != '\0')
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* match */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst struct doveadm_mail_cmd *
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const **argv)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int cmd_name_len;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *const *orig_argv;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int orig_argc;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_assert(*argc > 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd_name_len = strlen(cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_foreach(&doveadm_mail_cmds, cmd) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strcmp(cmd->name, cmd_name) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* see if it matches a multi-word command */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd->name[cmd_name_len] == ' ') {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *subcmd = cmd->name + cmd_name_len + 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch orig_argc = *argc;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch orig_argv = *argv;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_mail_cmd_try_find_multi_word(cmd, subcmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch argc, argv))
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *argc = orig_argc;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch *argv = orig_argv;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd = doveadm_mail_cmd_find_from_argv(cmd_name, &argc, (void *)&argv);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd == NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd(cmd, argc, argv);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* for now we'll just assume that cmd will be permanently in memory */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_append(&doveadm_mail_cmds, cmd, 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschconst struct doveadm_mail_cmd *doveadm_mail_cmd_find(const char *cmd_name)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_foreach(&doveadm_mail_cmds, cmd) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strcmp(cmd->name, cmd_name) == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_usage(string_t *out)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_foreach(&doveadm_mail_cmds, cmd) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd->usage_args == &doveadm_mail_cmd_hide)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch continue;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_printfa(out, "%s\t"DOVEADM_CMD_MAIL_USAGE_PREFIX, cmd->name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd->usage_args != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append(out, cmd->usage_args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch str_append_c(out, '\n');
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch fprintf(stderr, "doveadm %s "DOVEADM_CMD_MAIL_USAGE_PREFIX" %s\n",
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd->name, cmd->usage_args == NULL ? "" : cmd->usage_args);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch exit(EX_USAGE);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_try_help_name(const char *cmd_name)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_cmd_ver2 *cmd2;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd2 = doveadm_cmd_find_ver2(cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd2 != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch help_ver2(cmd2);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd = doveadm_mail_cmd_find(cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (cmd != NULL)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_help(cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschbool doveadm_mail_has_subcommands(const char *cmd_name)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const struct doveadm_mail_cmd *cmd;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int len = strlen(cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_foreach(&doveadm_mail_cmds, cmd) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strncmp(cmd->name, cmd_name, len) == 0 &&
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd->name[len] == ' ')
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_help_name(const char *cmd_name)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_try_help_name(cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_fatal("Missing help for command %s", cmd_name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd cmd_force_resync = {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd_force_resync_alloc, "force-resync", "<mailbox mask>"
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd cmd_purge = {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch cmd_purge_alloc, "purge", NULL
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_mail_cmd *mail_commands[] = {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_force_resync,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_purge,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_expunge,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_search,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_flags_add,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_flags_remove,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_flags_replace,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_import,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_copy,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_deduplicate,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_move,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_batch,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_dsync_backup,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_dsync_mirror,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &cmd_dsync_server
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschstatic struct doveadm_cmd_ver2 *mail_commands_ver2[] = {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_metadata_set_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_metadata_unset_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_metadata_get_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_metadata_list_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_status_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_list_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_create_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_delete_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_rename_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_subscribe_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_mailbox_unsubscribe_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_fetch_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_save_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_index_ver2,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &doveadm_cmd_altmove_ver2
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch};
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_init(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct module_dir_load_settings mod_set;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch unsigned int i;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_array_init(&doveadm_mail_cmds, 32);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (i = 0; i < N_ELEMENTS(mail_commands); i++)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_register_cmd(mail_commands[i]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for (i = 0; i < N_ELEMENTS(mail_commands_ver2); i++)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_cmd_register_ver2(mail_commands_ver2[i]);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch memset(&mod_set, 0, sizeof(mod_set));
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mod_set.abi_version = DOVECOT_ABI_VERSION;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mod_set.require_init_funcs = TRUE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mod_set.debug = doveadm_debug;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mod_set.binary_name = "doveadm";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* load all configured mail plugins */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_service_modules =
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch module_dir_load_missing(mail_storage_service_modules,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->mail_plugin_dir,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->mail_plugins,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &mod_set);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid doveadm_mail_deinit(void)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch mail_storage_hooks_deinit();
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_free(&doveadm_mail_cmds);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschvoid
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Boschdoveadm_cmd_ver2_to_mail_cmd_wrapper(const struct doveadm_cmd_ver2* cmd,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int argc, const struct doveadm_cmd_param argv[])
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch{
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd_context *ctx;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *wildcard_user;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch const char *fieldstr;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ARRAY_TYPE(const_string) pargv;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch int i;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch struct doveadm_mail_cmd mail_cmd = {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch .alloc = cmd->mail_cmd
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch };
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx = doveadm_mail_cmdline_init(&mail_cmd);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->iterate_all_users = FALSE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch p_array_init(&pargv, ctx->pool, 8);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch for(i=0;i<argc;i++) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (!argv[i].value_set)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch continue;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strcmp(argv[i].name, "all-users") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->iterate_all_users = argv[i].value.v_bool;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (strcmp(argv[i].name, "socket-path") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->doveadm_socket_path = argv[i].value.v_string;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (doveadm_settings->doveadm_worker_count == 0)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_settings->doveadm_worker_count = 1;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (strcmp(argv[i].name, "user") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = argv[i].value.v_string;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (strchr(ctx->cur_username, '*') != NULL ||
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch strchr(ctx->cur_username, '?') != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = ctx->cur_username;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cur_username = NULL;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (strcmp(argv[i].name, "user-file") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch wildcard_user = "*";
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->users_list_input = argv[i].value.v_istream;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_ref(ctx->users_list_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (ctx->v.parse_arg != NULL && argv[i].short_opt != '\0') {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch optarg = (char*)argv[i].value.v_string;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->v.parse_arg(ctx, argv[i].short_opt);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (strcmp(argv[i].name, "field") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* mailbox status, fetch: convert an array into a
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch single space-separated parameter (alternative to
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch fieldstr) */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch fieldstr = p_array_const_string_join(ctx->pool,
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch &argv[i].value.v_array, " ");
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_append(&pargv, &fieldstr, 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if (strcmp(argv[i].name, "file") == 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* input for doveadm_mail_get_input(),
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch used by e.g. save */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (ctx->cmd_input != NULL) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("Only one file input allowed: %s", argv[i].name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_free(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_exit_code = EX_USAGE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->cmd_input = argv[i].value.v_istream;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_stream_ref(ctx->cmd_input);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else if ((argv[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0) {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch /* feed this into pargv */
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch if (argv[i].type == CMD_PARAM_ARRAY)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_append_array(&pargv, &argv[i].value.v_array);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch else if (argv[i].type == CMD_PARAM_STR)
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_append(&pargv, &argv[i].value.v_string, 1);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch } else {
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_exit_code = EX_USAGE;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch i_error("invalid parameter: %s", argv[i].name);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_free(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch return;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch }
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch array_append_zero(&pargv);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->args = array_idx(&pargv, 0);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch ctx->full_args = ctx->args;
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_exec(ctx, wildcard_user);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch doveadm_mail_cmd_free(ctx);
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch}
56dd928c164ec5c0d1158a1760154b58c5f1f6e7Stephan Bosch