doveadm.c revision 29666594233e23edd98f8ee0fb5763dd2b094b09
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"
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen#include "env-util.h"
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen#include "execv-const.h"
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen#include "network.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "module-dir.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "master-service.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "master-service-settings.h"
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen#include "doveadm-print.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>
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen#include <dirent.h>
068357123aba2906c17a4e3bbe57417570be1958Timo Sirainen#include <time.h>
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen#include <sys/stat.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
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainenstatic void
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainendoveadm_usage_compress_lines(FILE *out, const char *str, const char *prefix)
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen{
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen const char *cmd, *args, *p, *short_name, *prev_name = "";
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen char **lines;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen unsigned int i, count, prefix_len = strlen(prefix);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen /* split lines */
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen lines = p_strsplit(pool_datastack_create(), str, "\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen for (count = 0; lines[count] != NULL; count++) ;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen /* sort lines */
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen qsort(lines, count, sizeof(*lines), i_strcmp_p);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen /* print lines, compress subcommands into a single line */
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen for (i = 0; i < count; i++) {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen args = strchr(lines[i], '\t');
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (args == NULL) {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen cmd = lines[i];
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen args = "";
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen } else {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen cmd = t_strdup_until(lines[i], args);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen args++;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (*prefix != '\0') {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (strncmp(cmd, prefix, prefix_len) != 0 ||
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen cmd[prefix_len] != ' ')
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen continue;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen cmd += prefix_len + 1;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen p = strchr(cmd, ' ');
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (p == NULL) {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (*prev_name != '\0') {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen prev_name = "";
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, USAGE_CMDNAME_FMT" %s\n", cmd, args);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen } else {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen short_name = t_strdup_until(cmd, p);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (strcmp(prev_name, short_name) != 0) {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (*prev_name != '\0')
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, USAGE_CMDNAME_FMT" %s",
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen short_name, t_strcut(p + 1, ' '));
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen prev_name = short_name;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen } else {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "|%s", t_strcut(p + 1, ' '));
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (*prev_name != '\0')
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen}
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
767431e5084a037c4dbefdf30ebfa03c84b1f449Timo Sirainenstatic void ATTR_NORETURN
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainenusage_to(FILE *out, const char *prefix)
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen{
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen const struct doveadm_cmd *cmd;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen string_t *str = t_str_new(1024);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
72c47a26f4ded49d4827dc64818b34bbc9606fc4Timo Sirainen fprintf(out, "usage: doveadm [-Dv] [-f <formatter>] ");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (*prefix != '\0')
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "%s ", prefix);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen fprintf(out, "<command> [<args>]\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen array_foreach(&doveadm_cmds, cmd)
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen str_printfa(str, "%s\t%s\n", cmd->name, cmd->short_usage);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen doveadm_mail_usage(str);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen doveadm_usage_compress_lines(out, str_c(str), prefix);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen exit(1);
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen}
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
767431e5084a037c4dbefdf30ebfa03c84b1f449Timo Sirainenvoid usage(void)
767431e5084a037c4dbefdf30ebfa03c84b1f449Timo Sirainen{
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen usage_to(stderr, "");
767431e5084a037c4dbefdf30ebfa03c84b1f449Timo Sirainen}
767431e5084a037c4dbefdf30ebfa03c84b1f449Timo Sirainen
9ce62fcb795a4bb57f1c003fc8cbd63bff6e5463Timo Sirainenstatic void ATTR_NORETURN
9ce62fcb795a4bb57f1c003fc8cbd63bff6e5463Timo Sirainenhelp_to(const struct doveadm_cmd *cmd, FILE *out)
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen fprintf(out, "doveadm %s %s\n", cmd->name, cmd->short_usage);
29666594233e23edd98f8ee0fb5763dd2b094b09Timo Sirainen exit(1);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainenvoid help(const struct doveadm_cmd *cmd)
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen{
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen help_to(cmd, stdout);
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen}
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo 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
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainenconst char *doveadm_plugin_getenv(const char *name)
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen{
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen const char *const *envs;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen unsigned int i, count;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen if (!array_is_created(&doveadm_settings->plugin_envs))
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen return NULL;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen envs = array_get(&doveadm_settings->plugin_envs, &count);
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen for (i = 0; i < count; i += 2) {
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen if (strcmp(envs[i], name) == 0)
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen return envs[i+1];
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen }
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen return NULL;
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen}
1db62753d9e3b5d71018889c8ef0a3722a307455Timo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainenstatic bool
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainenparse_hostport(const char *str, const char **host_r, unsigned int *port_r)
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen{
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen const char *p;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen /* host:port */
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen p = strrchr(str, ':');
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (p == NULL || str_to_uint(p+1, port_r) < 0)
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen return FALSE;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen *host_r = t_strdup_until(str, p);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen /* there is any '/' character (unlikely to be found from host names),
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen assume ':' is part of a file path */
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (strchr(str, '/') != NULL)
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen return FALSE;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen return TRUE;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen}
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainenint doveadm_connect(const char *path)
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen{
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen struct stat st;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen const char *host;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen struct ip_addr *ips;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen unsigned int port, ips_count;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen int fd, ret;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (parse_hostport(path, &host, &port) && stat(path, &st) < 0) {
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen /* it's a host:port, connect via TCP */
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen ret = net_gethostbyname(host, &ips, &ips_count);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (ret != 0) {
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen i_fatal("Lookup of host %s failed: %s",
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen host, net_gethosterror(ret));
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen }
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen fd = net_connect_ip_blocking(&ips[0], port, NULL);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (fd == -1) {
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen i_fatal("connect(%s:%u) failed: %m",
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen net_ip2addr(&ips[0]), port);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen }
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen } else {
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen fd = net_connect_unix(path);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen if (fd == -1)
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen i_fatal("net_connect_unix(%s) failed: %m", path);
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen }
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen return fd;
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen}
91770f85d9b2ac3e91b7aa74f57149412ae33c4cTimo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainenstatic bool doveadm_has_subcommands(const char *cmd_name)
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen{
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen const struct doveadm_cmd *cmd;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen unsigned int len = strlen(cmd_name);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen array_foreach(&doveadm_cmds, cmd) {
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen if (strncmp(cmd->name, cmd_name, len) == 0 &&
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen cmd->name[len] == ' ')
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen return TRUE;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen return doveadm_mail_has_subcommands(cmd_name);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen}
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainenstatic bool doveadm_has_unloaded_plugin(const char *name)
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen{
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen struct module *module;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen DIR *dir;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen struct dirent *d;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen const char *plugin_name;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen unsigned int name_len = strlen(name);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen bool found = FALSE;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen /* first check that it's not actually loaded */
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen for (module = modules; module != NULL; module = module->next) {
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (strcmp(module_get_plugin_name(module), name) == 0)
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen return FALSE;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen }
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen dir = opendir(DOVEADM_MODULEDIR);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (dir == NULL)
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen return FALSE;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen while ((d = readdir(dir)) != NULL) {
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen plugin_name = module_file_get_name(d->d_name);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (strncmp(plugin_name, "doveadm_", 8) == 0)
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen plugin_name += 8;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (strncmp(plugin_name, name, name_len) == 0 &&
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen (plugin_name[name_len] == '\0' ||
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen strcmp(plugin_name + name_len, "_plugin") == 0)) {
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen found = TRUE;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen break;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen }
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen }
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen (void)closedir(dir);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen return found;
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen}
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainenstatic void cmd_help(int argc ATTR_UNUSED, char *argv[])
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen{
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen const char *man_argv[3];
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen if (argv[1] == NULL)
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen usage_to(stdout, "");
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen env_put("MANPATH="MANDIR);
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen man_argv[0] = "man";
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen man_argv[1] = t_strconcat("doveadm-", argv[1], NULL);
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen man_argv[2] = NULL;
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen execvp_const(man_argv[0], man_argv);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
0f9a8663b0ff6fe30389d02284a2b002c40914ebTimo Sirainen
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainenstatic struct doveadm_cmd doveadm_cmd_help = {
bde78a7bf5f9000f1ae4dc7ce6cabd012e1f8b79Pascal Volk cmd_help, "help", "<cmd>"
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen};
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainenstatic void cmd_config(int argc ATTR_UNUSED, char *argv[])
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen{
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen argv[0] = BINDIR"/doveconf";
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen (void)execv(argv[0], argv);
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen i_fatal("execv(%s) failed: %m", argv[0]);
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen}
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainenstatic struct doveadm_cmd doveadm_cmd_config = {
bde78a7bf5f9000f1ae4dc7ce6cabd012e1f8b79Pascal Volk cmd_config, "config", "[doveconf parameters]"
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen};
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo 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
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainenstatic void doveadm_read_settings(void)
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen{
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen static const struct setting_parser_info *set_roots[] = {
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen &doveadm_setting_parser_info,
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen NULL
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen };
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen struct master_service_settings_input input;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen struct master_service_settings_output output;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen const char *error;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen memset(&input, 0, sizeof(input));
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen input.roots = set_roots;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen input.module = "doveadm";
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen input.preserve_home = TRUE;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen if (master_service_settings_read(master_service, &input,
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen &output, &error) < 0)
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen i_fatal("Error reading configuration: %s", error);
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen doveadm_settings = master_service_settings_get_others(master_service)[0];
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen}
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_help,
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen &doveadm_cmd_config,
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen &doveadm_cmd_stop,
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen &doveadm_cmd_reload,
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,
846dd75b809a28a7defc915fc4d61badce509d61Timo Sirainen &doveadm_cmd_mailbox_mutf7
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen};
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainenint main(int argc, char *argv[])
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen{
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen enum master_service_flags service_flags =
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen MASTER_SERVICE_FLAG_STANDALONE |
a672f99363d5f37060c1331d00d2ee3c4626310fTimo Sirainen MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen const char *cmd_name;
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen unsigned int i;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen bool quick_init = FALSE;
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,
72c47a26f4ded49d4827dc64818b34bbc9606fc4Timo Sirainen &argc, &argv, "+Df:v");
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;
72c47a26f4ded49d4827dc64818b34bbc9606fc4Timo Sirainen case 'f':
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_init(optarg);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo 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 }
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen cmd_name = argv[optind];
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
4a26584a87ee0e986d23a224b3b3e85c44254d7fTimo Sirainen if (cmd_name != NULL && strcmp(cmd_name, "help") == 0 &&
4a26584a87ee0e986d23a224b3b3e85c44254d7fTimo Sirainen argv[optind+1] != NULL) {
4a26584a87ee0e986d23a224b3b3e85c44254d7fTimo Sirainen /* "help cmd" doesn't need any configuration */
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen quick_init = TRUE;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen } else {
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen doveadm_read_settings();
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen }
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
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen if (cmd_name != NULL && (quick_init ||
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen strcmp(cmd_name, "stop") == 0 ||
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen strcmp(cmd_name, "reload") == 0)) {
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen /* special case commands: even if there is something wrong
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen with the config (e.g. mail_plugins), don't fail these
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen commands */
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen quick_init = TRUE;
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen } else {
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen quick_init = FALSE;
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_register_director_commands();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_register_log_commands();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_mail_init();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_load_modules();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen if (cmd_name == NULL) {
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen /* show usage after registering all plugins */
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen usage_to(stdout, "");
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen }
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen }
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen argc -= optind;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen argv += optind;
1d5dbb87f3485544db62896e2d56c663cb728c17Timo Sirainen#ifdef __GLIBC__
1d5dbb87f3485544db62896e2d56c663cb728c17Timo Sirainen /* for subcommands allow -options anywhere in command line */
1d5dbb87f3485544db62896e2d56c663cb728c17Timo Sirainen optind = 0;
1d5dbb87f3485544db62896e2d56c663cb728c17Timo Sirainen#else
dbcc7e1e5eaaad8a8cac6ee74076772c42a2649aTimo Sirainen optind = 1;
1d5dbb87f3485544db62896e2d56c663cb728c17Timo Sirainen#endif
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) &&
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen !doveadm_mail_try_run(cmd_name, argc, argv)) {
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (doveadm_has_subcommands(cmd_name))
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen usage_to(stdout, cmd_name);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen if (doveadm_has_unloaded_plugin(cmd_name)) {
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen i_fatal("Unknown command '%s', but plugin %s exists. "
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen "Try to set mail_plugins=%s",
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen cmd_name, cmd_name, cmd_name);
10515cb90514b169ab6c3693c72c4bf1017476dbTimo Sirainen }
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen usage();
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen }
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen if (!quick_init) {
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_mail_deinit();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen module_dir_unload(&modules);
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_deinit();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen }
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen array_free(&doveadm_cmds);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen master_service_deinit(&master_service);
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen return 0;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen}