doveadm.c revision 78ab753927acf4466f38e4a50694be3f4c4cc9ab
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2009-2010 Dovecot authors, see the included COPYING file */
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "lib.h"
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen#include "array.h"
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen#include "str.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "module-dir.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "master-service.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "master-service-settings.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "doveadm-mail.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "doveadm-settings.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "doveadm.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include <stdio.h>
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include <stdlib.h>
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include <unistd.h>
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen#include <time.h>
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainenbool doveadm_verbose = FALSE, doveadm_debug = FALSE;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainenstatic struct module *modules = NULL;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenstatic ARRAY_DEFINE(doveadm_cmds, struct doveadm_cmd);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen array_append(&doveadm_cmds, cmd, 1);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainenvoid usage(void)
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen const struct doveadm_cmd *cmd;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
04a2d9680d1c5b647204ed8a8888f40c1cdb09deTimo Sirainen fprintf(stderr, "usage: doveadm [-Dv] <command> [<args>]\n");
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen array_foreach(&doveadm_cmds, cmd) {
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen fprintf(stderr, USAGE_CMDNAME_FMT" %s\n",
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen cmd->name, cmd->short_usage);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen }
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen doveadm_mail_usage();
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen exit(1);
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen}
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenvoid help(const struct doveadm_cmd *cmd)
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen fprintf(stderr, "doveadm %s %s\n", cmd->name, cmd->short_usage);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen if (cmd->long_usage != NULL)
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen fprintf(stderr, "%s", cmd->long_usage);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen exit(0);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainenconst char *unixdate2str(time_t timestamp)
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen{
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen static char buf[64];
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen struct tm *tm;
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen tm = localtime(&timestamp);
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen return buf;
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen}
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainenstatic void cmd_help(int argc, char *argv[])
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen const struct doveadm_cmd *cmd;
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen string_t *name;
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen int i;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen if (argv[1] == NULL)
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen usage();
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen name = t_str_new(100);
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen for (i = 1; i < argc; i++) {
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen str_append(name, argv[i]);
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen array_foreach(&doveadm_cmds, cmd) {
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen if (strcmp(cmd->name, str_c(name)) == 0)
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen help(cmd);
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen }
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen doveadm_mail_try_help_name(str_c(name));
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen str_append_c(name, ' ');
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen }
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen usage();
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
0f9a8663b0ff6fe30389d02284a2b002c40914ebTimo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenstatic struct doveadm_cmd doveadm_cmd_help = {
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen cmd_help, "help", "<cmd>", NULL
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen};
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainenstatic bool
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainendoveadm_try_run_multi_word(const struct doveadm_cmd *cmd,
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen const char *cmdname, int argc, char *argv[])
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen{
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen unsigned int len;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
78ab753927acf4466f38e4a50694be3f4c4cc9abTimo Sirainen if (argc < 2)
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return FALSE;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen len = strlen(argv[1]);
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (strncmp(cmdname, argv[1], len) != 0)
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return FALSE;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (cmdname[len] == ' ') {
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen /* more args */
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return doveadm_try_run_multi_word(cmd, cmdname + len + 1,
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen argc - 1, argv + 1);
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen }
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (cmdname[len] != '\0')
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return FALSE;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen /* match */
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen cmd->cmd(argc - 1, argv + 1);
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return TRUE;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen}
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenstatic bool doveadm_try_run(const char *cmd_name, int argc, char *argv[])
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen const struct doveadm_cmd *cmd;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen unsigned int cmd_name_len;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen i_assert(argc > 0);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen cmd_name_len = strlen(cmd_name);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen array_foreach(&doveadm_cmds, cmd) {
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (strcmp(cmd->name, cmd_name) == 0) {
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen cmd->cmd(argc, argv);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen return TRUE;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen }
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen /* see if it matches a multi-word command */
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen cmd->name[cmd_name_len] == ' ') {
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen const char *subcmd = cmd->name + cmd_name_len + 1;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen if (doveadm_try_run_multi_word(cmd, subcmd,
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen argc, argv))
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen return TRUE;
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen }
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen }
542a32ee5f4ca72626ec93b6313f909811c01534Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen return FALSE;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainenstatic void doveadm_load_modules(void)
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen{
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen struct module_dir_load_settings mod_set;
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen /* some doveadm plugins have dependencies to mail plugins. we can load
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen only those whose dependencies have been loaded earlier, the rest are
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen ignored. */
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen memset(&mod_set, 0, sizeof(mod_set));
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen mod_set.version = master_service_get_version_string(master_service);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen mod_set.require_init_funcs = TRUE;
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen mod_set.debug = doveadm_debug;
78ab753927acf4466f38e4a50694be3f4c4cc9abTimo Sirainen mod_set.ignore_dlopen_errors = !doveadm_debug;
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen modules = module_dir_load_missing(modules, DOVEADM_MODULEDIR,
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen NULL, &mod_set);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen module_dir_init(modules);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen}
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_help,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_auth,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_user,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_dump,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_pw,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_who,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_penalty,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_kick,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_mailbox_convert
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen};
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainenint main(int argc, char *argv[])
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen{
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen const struct setting_parser_info *set_roots[] = {
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen &doveadm_setting_parser_info,
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen NULL
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen };
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen enum master_service_flags service_flags =
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen MASTER_SERVICE_FLAG_STANDALONE |
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen const char *cmd_name, *error;
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen unsigned int i;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen int c;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen /* "+" is GNU extension to stop at the first non-option.
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen others just accept -+ option. */
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen master_service = master_service_init("doveadm", service_flags,
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen &argc, &argv, "+Dv");
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen while ((c = master_getopt(master_service)) > 0) {
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen switch (c) {
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen case 'D':
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen doveadm_debug = TRUE;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen doveadm_verbose = TRUE;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen break;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen case 'v':
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen doveadm_verbose = TRUE;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen break;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen default:
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen return FATAL_DEFAULT;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen }
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen }
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen if (master_service_settings_read_simple(master_service, set_roots,
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen &error) < 0)
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen i_fatal("Error reading configuration: %s", error);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen doveadm_settings = master_service_settings_get_others(master_service)[0];
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen i_array_init(&doveadm_cmds, 32);
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen doveadm_register_cmd(doveadm_commands[i]);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen doveadm_mail_init();
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen doveadm_load_modules();
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen if (optind == argc)
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen usage();
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen cmd_name = argv[optind];
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen argc -= optind;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen argv += optind;
dbcc7e1e5eaaad8a8cac6ee74076772c42a2649aTimo Sirainen optind = 1;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_init_finish(master_service);
aee3e2f7ab2b27572a90b9e7fd8fe60f13c6637eTimo Sirainen if (!doveadm_debug) {
aee3e2f7ab2b27572a90b9e7fd8fe60f13c6637eTimo Sirainen /* disable debugging unless -D is given */
aee3e2f7ab2b27572a90b9e7fd8fe60f13c6637eTimo Sirainen i_set_debug_file("/dev/null");
aee3e2f7ab2b27572a90b9e7fd8fe60f13c6637eTimo Sirainen }
aee3e2f7ab2b27572a90b9e7fd8fe60f13c6637eTimo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen if (!doveadm_try_run(cmd_name, argc, argv) &&
f50ea0370137dd93d9953d91ea73486ca0784de9Timo Sirainen !doveadm_mail_try_run(cmd_name, argc, argv))
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen usage();
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen doveadm_mail_deinit();
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen module_dir_unload(&modules);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen array_free(&doveadm_cmds);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen master_service_deinit(&master_service);
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen return 0;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen}