doveadm-mail.c revision 97437f768d1a3e6134fed1971202803fd250eef2
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "lib-signals.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ioloop.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "str.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "module-dir.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "wildcard-match.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "master-service.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "imap-utf7.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-user.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-namespace.h"
66ae183b6e895216037bd921367670f4b0665911Timo Sirainen#include "mail-storage.h"
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include "mail-storage-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-storage-service.h"
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen#include "mail-search-build.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-search-parser.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "doveadm-mail.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include <stdio.h>
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen#include <stdlib.h>
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo SirainenARRAY_TYPE(doveadm_mail_cmd) doveadm_mail_cmds;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid (*hook_doveadm_mail_init)(struct doveadm_mail_cmd_context *ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct doveadm_mail_cmd_module_register
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_mail_cmd_module_register = { 0 };
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int killed_signo = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct doveadm_mail_cmd_context *
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainendoveadm_mail_cmd_alloc_size(size_t size)
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen{
8fa41238067c854435884c459963fde6f8c6436bTimo Sirainen struct doveadm_mail_cmd_context *ctx;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen pool_t pool;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen i_assert(size >= sizeof(struct doveadm_mail_cmd_context));
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen pool = pool_alloconly_create("doveadm mail cmd", 1024);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx = p_malloc(pool, size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->pool = pool;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->dm_printf_last_lf = TRUE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return ctx;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainenstatic void
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainencmd_purge_run(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct mail_user *user)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_namespace *ns;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ns->type != NAMESPACE_PRIVATE || ns->alias_for != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (mail_storage_purge(ns->storage) < 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen i_error("Purging namespace '%s' failed: %s", ns->prefix,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mail_storage_get_last_error(ns->storage, NULL));
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
ba00293b85c7fb4e7a2d100991c716e17b9daaaeTimo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_purge_alloc(void)
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen{
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen struct doveadm_mail_cmd_context *ctx;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen ctx->v.run = cmd_purge_run;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return ctx;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mailbox **box_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_namespace *ns;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen struct mailbox *box;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen string_t *str;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen const char *orig_mailbox = mailbox;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen str = t_str_new(128);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (imap_utf8_to_utf7(mailbox, str) < 0)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mailbox = str_c(str);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (ns == NULL)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen i_fatal("Can't find namespace for mailbox %s", mailbox);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen MAILBOX_FLAG_IGNORE_ACLS);
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen if (mailbox_open(box) < 0) {
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen i_error("Opening mailbox %s failed: %s", orig_mailbox,
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen mail_storage_get_last_error(mailbox_get_storage(box),
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen NULL));
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen mailbox_free(&box);
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen return -1;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen }
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen *box_r = box;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return 0;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen}
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenint doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct mailbox **box_r)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mailbox_find_and_open(user, mailbox, box_r) < 0)
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return -1;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen i_error("Syncing mailbox %s failed: %s", mailbox,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen mail_storage_get_last_error(mailbox_get_storage(*box_r),
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen NULL));
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return -1;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen }
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen return 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen}
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainenstruct mail_search_args *
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainendoveadm_mail_build_search_args(const char *const args[])
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen{
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen struct mail_search_parser *parser;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen struct mail_search_args *sargs;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen const char *error;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen parser = mail_search_parser_init_cmdline(args);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (mail_search_build(mail_search_register_get_human(),
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen parser, "UTF-8", &sargs, &error) < 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_fatal("%s", error);
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen mail_search_parser_deinit(&parser);
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen return sargs;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen}
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainenstruct force_resync_cmd_context {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct doveadm_mail_cmd_context ctx;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen const char *mailbox;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen};
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainenstatic void cmd_force_resync_run(struct doveadm_mail_cmd_context *_ctx,
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen struct mail_user *user)
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct force_resync_cmd_context *ctx =
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen (struct force_resync_cmd_context *)_ctx;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct mail_storage *storage;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct mailbox *box;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen _ctx->failed = TRUE;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return;
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen storage = mailbox_get_storage(box);
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FORCE_RESYNC |
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen MAILBOX_SYNC_FLAG_FIX_INCONSISTENT) < 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("Forcing a resync on mailbox %s failed: %s",
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->mailbox,
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_storage_get_last_error(storage, NULL));
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen _ctx->failed = TRUE;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen mailbox_free(&box);
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenstatic void cmd_force_resync_init(struct doveadm_mail_cmd_context *_ctx,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const args[])
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct force_resync_cmd_context *ctx =
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen (struct force_resync_cmd_context *)_ctx;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const char *mailbox = args[0];
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (mailbox == NULL || args[1] != NULL)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen doveadm_mail_help_name("force-resync");
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx->mailbox = p_strdup(ctx->ctx.pool, mailbox);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen}
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_force_resync_alloc(void)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen struct force_resync_cmd_context *ctx;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct force_resync_cmd_context);
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen ctx->ctx.v.init = cmd_force_resync_init;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen ctx->ctx.v.run = cmd_force_resync_run;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return &ctx->ctx;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainenstatic int
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainendoveadm_mail_next_user(struct doveadm_mail_cmd_context *ctx,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const struct mail_storage_service_input *input,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char **error_r)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen struct mail_storage_service_user *service_user;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *error;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen int ret;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen i_set_failure_prefix(t_strdup_printf("doveadm(%s): ", input->username));
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen ret = mail_storage_service_lookup(ctx->storage_service, input,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen &service_user, &error);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (ret <= 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (ret < 0) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *error_r = t_strdup_printf("User lookup failed: %s",
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen error);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ret = mail_storage_service_next(ctx->storage_service, service_user,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen &ctx->cur_mail_user);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if (ret < 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen *error_r = "User init failed";
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_storage_service_user_free(&service_user);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainen ctx->v.run(ctx, ctx->cur_mail_user);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen mail_user_unref(&ctx->cur_mail_user);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen mail_storage_service_user_free(&service_user);
6825360d446542046757b06064282301c4c6b27cTimo Sirainen return 1;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen}
6825360d446542046757b06064282301c4c6b27cTimo Sirainen
6825360d446542046757b06064282301c4c6b27cTimo Sirainenstatic void
6825360d446542046757b06064282301c4c6b27cTimo Sirainendoveadm_mail_single_user(struct doveadm_mail_cmd_context *ctx,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *username,
6825360d446542046757b06064282301c4c6b27cTimo Sirainen enum mail_storage_service_flags service_flags)
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen{
c8d093d149253fe8faec267c5057f45fe626f84cTimo Sirainen struct mail_storage_service_input input;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen const char *error;
6825360d446542046757b06064282301c4c6b27cTimo Sirainen int ret;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (username == NULL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_fatal("USER environment is missing and -u option not used");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen memset(&input, 0, sizeof(input));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen input.username = username;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen service_flags);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (hook_doveadm_mail_init != NULL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hook_doveadm_mail_init(ctx);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (ret < 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_fatal("%s", error);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen else if (ret == 0)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen i_fatal("User no longer exists");
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen mail_storage_service_deinit(&ctx->storage_service);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainenstatic void sig_die(const siginfo_t *si, void *context ATTR_UNUSED)
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen{
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen killed_signo = si->si_signo;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen}
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenstatic void
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainendoveadm_mail_all_users(struct doveadm_mail_cmd_context *ctx,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const char *wildcard_user,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen enum mail_storage_service_flags service_flags)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen struct mail_storage_service_input input;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen unsigned int user_idx, user_count, interval, n;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen const char *user, *error;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen int ret;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen memset(&input, 0, sizeof(input));
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen input.service = "doveadm";
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ctx->storage_service = mail_storage_service_init(master_service, NULL,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen service_flags);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen lib_signals_set_handler(SIGINT, FALSE, sig_die, NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen lib_signals_set_handler(SIGTERM, FALSE, sig_die, NULL);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (hook_doveadm_mail_init != NULL)
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen hook_doveadm_mail_init(ctx);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen user_count = mail_storage_service_all_init(ctx->storage_service);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen n = user_count / 10000;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen for (interval = 10; n > 0 && interval < 1000; interval *= 10)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen n /= 10;
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen user_idx = 0;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen while ((ret = ctx->v.get_next_user(ctx, &user)) > 0) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (wildcard_user != NULL) {
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen if (!wildcard_match_icase(user, wildcard_user))
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen continue;
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen }
e3689d0f073341e844638f34e1e4d0b7bb053cc8Timo Sirainen input.username = user;
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen T_BEGIN {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen ret = doveadm_mail_next_user(ctx, &input, &error);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (ret < 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_error("%s", error);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (ret == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_info("User no longer exists, skipping");
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret == -1)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (doveadm_verbose) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (++user_idx % interval == 0) {
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen printf("\r%d / %d", user_idx, user_count);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fflush(stdout);
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (killed_signo != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_warning("Killed with signal %d", killed_signo);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (doveadm_verbose)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen printf("\n");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_set_failure_prefix("doveadm: ");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Failed to iterate through some users");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_storage_service_deinit(&ctx->storage_service);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen}
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_mail_cmd_init_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *const args[] ATTR_UNUSED)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainendoveadm_mail_cmd_get_next_user(struct doveadm_mail_cmd_context *ctx,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen const char **username_r)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen{
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen return mail_storage_service_all_next(ctx->storage_service, username_r);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen}
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic void
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainendoveadm_mail_cmd_deinit_noop(struct doveadm_mail_cmd_context *ctx ATTR_UNUSED)
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen{
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen}
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainenstatic void
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainendoveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen enum mail_storage_service_flags service_flags =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen struct doveadm_mail_cmd_context *ctx;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *getopt_args, *username, *wildcard_user;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen int c;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (doveadm_debug)
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen ctx = cmd->alloc();
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen if (ctx->v.init == NULL)
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen ctx->v.init = doveadm_mail_cmd_init_noop;
0b49cfeae91a4020a404714b11c99e8e955fb631Timo Sirainen if (ctx->v.get_next_user == NULL)
af1e2b2ab5d1c5ca5afe482ef8c8161c17acc190Timo Sirainen ctx->v.get_next_user = doveadm_mail_cmd_get_next_user;
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (ctx->v.deinit == NULL)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen ctx->v.deinit = doveadm_mail_cmd_deinit_noop;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen p_array_init(&ctx->module_contexts, ctx->pool, 5);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen getopt_args = t_strconcat("Au:", ctx->getopt_args, NULL);
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen username = getenv("USER");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen wildcard_user = NULL;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen while ((c = getopt(argc, argv, getopt_args)) > 0) {
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen switch (c) {
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen case 'A':
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen ctx->iterate_all_users = TRUE;
f239eb76f77afcbc0bfc97c9b52b4407d1bc3fe6Timo Sirainen break;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen case 'u':
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen service_flags |=
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen username = optarg;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (strchr(username, '*') != NULL ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen strchr(username, '?') != NULL)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen wildcard_user = username;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen default:
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen if (ctx->v.parse_arg == NULL ||
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen !ctx->v.parse_arg(ctx, c))
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen doveadm_mail_help(cmd);
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen }
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen argv += optind;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
99e8698f598d2b83da7c581584a538c0713fd11dTimo Sirainen if (argv[0] != NULL && cmd->usage_args == NULL) {
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen i_fatal("doveadm %s: Unknown parameter: %s",
0c27b881989bc2b391281650ee89a8cc4d89f5e7Timo Sirainen cmd->name, argv[0]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen ctx->v.init(ctx, (const void *)argv);
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen if (!ctx->iterate_all_users && wildcard_user == NULL) {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen doveadm_mail_single_user(ctx, username, service_flags);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen } else {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen service_flags |= MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen doveadm_mail_all_users(ctx, wildcard_user, service_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen ctx->v.deinit(ctx);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (ctx->failed)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen exit(FATAL_DEFAULT);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen}
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainenvoid dm_printf(struct doveadm_mail_cmd_context *ctx, const char *format, ...)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen{
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen va_list args;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen va_start(args, format);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (!ctx->iterate_all_users)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen vprintf(format, args);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen else T_BEGIN {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen const char *str = t_strdup_vprintf(format, args);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen bool prev_lf = ctx->dm_printf_last_lf;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen for (; *str != '\0'; str++) {
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen if (prev_lf)
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen printf("%s: ", ctx->cur_mail_user->username);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen putchar(*str);
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen prev_lf = *str == '\n';
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->dm_printf_last_lf = prev_lf;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen } T_END;
1fd0d511885c30028aba388588151acf4ee85e75Timo Sirainen va_end(args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
c2feb7d13482d0f60691cd71d06d42a80df99397Timo Sirainenstatic bool
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainendoveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen const char *cmdname, int argc, char *argv[])
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen unsigned int len;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (argc < 2)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen len = strlen(argv[1]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strncmp(cmdname, argv[1], len) != 0)
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen return FALSE;
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (cmdname[len] == ' ') {
e670e1783fe4541dc3fc6109a181d45b0a9c2635Timo Sirainen /* more args */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen argc - 1, argv + 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (cmdname[len] != '\0')
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen return FALSE;
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen /* match */
90c5979b3c530707744beab6413f9d1e446335d1Timo Sirainen doveadm_mail_cmd(cmd, argc - 1, argv + 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenbool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen const struct doveadm_mail_cmd *cmd;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int cmd_name_len;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen i_assert(argc > 0);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen cmd_name_len = strlen(cmd_name);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen doveadm_mail_cmd(cmd, argc, argv);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen /* see if it matches a multi-word command */
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen cmd->name[cmd_name_len] == ' ') {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if (doveadm_mail_try_run_multi_word(cmd, subcmd,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen argc, argv))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
eb77c0a041648af50abc027811f6b7951c3a80cdTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen return FALSE;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen}
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen
51b979b6414b940f04677a7e2d064be119345954Timo Sirainenvoid doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
6143fece58262865ce89b5012b73ef08f2ad6abcTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* for now we'll just assume that cmd will be permanently in memory */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append(&doveadm_mail_cmds, cmd, 1);
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenvoid doveadm_mail_usage(string_t *out)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct doveadm_mail_cmd *cmd;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen str_printfa(out, "%s\t[-u <user>|-A]", cmd->name);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (cmd->usage_args != NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen str_printfa(out, " %s", cmd->usage_args);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen str_append_c(out, '\n');
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenvoid doveadm_mail_help(const struct doveadm_mail_cmd *cmd)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen fprintf(stderr, "doveadm %s [-u <user>|-A] %s\n", cmd->name,
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen cmd->usage_args == NULL ? "" : cmd->usage_args);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen exit(0);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen}
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid doveadm_mail_try_help_name(const char *cmd_name)
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen{
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen const struct doveadm_mail_cmd *cmd;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen doveadm_mail_help(cmd);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen }
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen}
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainenbool doveadm_mail_has_subcommands(const char *cmd_name)
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct doveadm_mail_cmd *cmd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int len = strlen(cmd_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach(&doveadm_mail_cmds, cmd) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strncmp(cmd->name, cmd_name, len) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd->name[len] == ' ')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid doveadm_mail_help_name(const char *cmd_name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_mail_try_help_name(cmd_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Missing help for command %s", cmd_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_mail_cmd cmd_force_resync = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_force_resync_alloc, "force-resync", "<mailbox>"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_mail_cmd cmd_purge = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_purge_alloc, "purge", NULL
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainenstatic struct doveadm_mail_cmd *mail_commands[] = {
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen &cmd_force_resync,
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen &cmd_purge,
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen &cmd_expunge,
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen &cmd_search,
2469ed8e17534f6cb5f41493df8c7e6f3b2c9b61Timo Sirainen &cmd_fetch,
c61d52810496376a2ea60b8f4e27bbcaa8754f3fTimo Sirainen &cmd_altmove,
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen &cmd_mailbox_list,
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen &cmd_mailbox_create,
f4e0148e539c6dd4e12b8305ab0dd5e63c46ba67Timo Sirainen &cmd_mailbox_delete,
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen &cmd_mailbox_rename,
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen &cmd_mailbox_subscribe,
2bd96c58be42146cb84076331604cadb2994fce5Timo Sirainen &cmd_mailbox_unsubscribe,
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen &cmd_mailbox_status
27db4ce5fe399c981e09dcf9e885a1546afd34f4Timo Sirainen};
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainenvoid doveadm_mail_init(void)
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen{
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen struct module_dir_load_settings mod_set;
5cc772dc8b507be0bc1996b5717943ba13432e08Timo Sirainen unsigned int i;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen i_array_init(&doveadm_mail_cmds, 32);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < N_ELEMENTS(mail_commands); i++)
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen doveadm_mail_register_cmd(mail_commands[i]);
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen memset(&mod_set, 0, sizeof(mod_set));
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen mod_set.version = master_service_get_version_string(master_service);
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen mod_set.require_init_funcs = TRUE;
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen mod_set.debug = doveadm_debug;
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen
ae14dfd895881f9d1c6899b0c09f1a8b51447d61Timo Sirainen /* load all configured mail plugins */
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen mail_storage_service_modules =
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen module_dir_load_missing(mail_storage_service_modules,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen doveadm_settings->mail_plugin_dir,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen doveadm_settings->mail_plugins,
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen &mod_set);
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen}
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainenvoid doveadm_mail_deinit(void)
31189eeac1ccaaf1201c60427f8c1087b0f5dfceTimo Sirainen{
902222fb0928d1701f20a384b73f327b1d9a15ddTimo Sirainen array_free(&doveadm_mail_cmds);
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen}
0d0451206a91e9f96e522075dce28a89adc2325dTimo Sirainen