bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "lib.h"
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen#include "array.h"
fab850a6aee4aaef4f4795bd7946807a3ba45041Timo Sirainen#include "str.h"
6e2856a5beeeb0edf5d852dde63d99fb9af11151Martti Rannanjärvi#include "sort.h"
57591c5ea045b6829ebcfed9b145d719d63f935aTimo Sirainen#include "ostream.h"
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen#include "env-util.h"
28b8434ca4cba2e310d13ffc55e895d658725f43Timo Sirainen#include "execv-const.h"
eee37857404ee76763762483a3e6e83618e16e62Timo Sirainen#include "dict.h"
06af65f82453bb976cf8aa6fe2507e3a6253a04fTimo Sirainen#include "master-service-private.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "master-service-settings.h"
e5d7056b6ef069e228f8ad3c9467662955cab3c6Timo Sirainen#include "settings-parser.h"
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen#include "doveadm-print-private.h"
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include "doveadm-dump.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "doveadm-mail.h"
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen#include "doveadm-settings.h"
54f559f2e69ea1498e3ccfa7b65d16d9a622c391Timo Sirainen#include "doveadm-dsync.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include "doveadm.h"
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen#include <unistd.h>
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainenconst struct doveadm_print_vfuncs *doveadm_print_vfuncs_all[] = {
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen &doveadm_print_flow_vfuncs,
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen &doveadm_print_tab_vfuncs,
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen &doveadm_print_table_vfuncs,
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen &doveadm_print_pager_vfuncs,
3cd674e541f2f930d2ae5dbdc6fe2f4d29d8dc04Aki Tuomi &doveadm_print_json_vfuncs,
21e4a561c2983f7ff02c0503c9bad8e4f45cee8aAki Tuomi &doveadm_print_formatted_vfuncs,
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen NULL
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen};
8aa6fe58b1832da498b49de4383f9f1ef458945dTimo Sirainen
6c40413c6e64fde2d977cd6076afa97fa57b67fcTimo Sirainenbool doveadm_verbose_proctitle;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenint doveadm_exit_code = 0;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainenstatic void failure_exit_callback(int *status)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen{
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen enum fatal_exit_status fatal_status = *status;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen switch (fatal_status) {
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_LOGWRITE:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_LOGERROR:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_LOGOPEN:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_OUTOFMEM:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_EXEC:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen case FATAL_DEFAULT:
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen *status = EX_TEMPFAIL;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen break;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen }
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen}
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainenstatic void
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainendoveadm_usage_compress_lines(FILE *out, const char *str, const char *prefix)
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen{
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen const char *cmd, *args, *p, *short_name, *sub_name;
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen const char *prev_name = "", *prev_sub_name = "";
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen const char **lines;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int i, count;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t prefix_len = strlen(prefix);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen /* split lines */
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen lines = (void *)p_strsplit(pool_datastack_create(), str, "\n");
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen for (count = 0; lines[count] != NULL; count++) ;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen /* sort lines */
27a44fcfd8d19bffe0f267f20a2b5d3fe7600fddTimo Sirainen i_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;
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen prev_sub_name = "";
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen } else {
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen sub_name = t_strcut(p + 1, ' ');
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen if (strcmp(prev_sub_name, sub_name) != 0) {
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen fprintf(out, "|%s", sub_name);
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen prev_sub_name = sub_name;
bb1a7da5a76625640a5a207b19ed3abdb70c9617Timo Sirainen }
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{
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen const struct doveadm_cmd_ver2 *cmd2;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen const struct doveadm_cmd *cmd;
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen string_t *str = t_str_new(1024);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
10635b60b6f7776cd4c1f364ae8dc94c3b9254ecPascal Volk 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);
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen array_foreach(&doveadm_cmds_ver2, cmd2)
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen str_printfa(str, "%s\t%s\n", cmd2->name, cmd2->usage);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen doveadm_mail_usage(str);
bd417d416988d11a6b555b9aa57779e7ed976951Timo Sirainen doveadm_usage_compress_lines(out, str_c(str), prefix);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen exit(EX_USAGE);
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);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen exit(EX_USAGE);
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainenvoid help(const struct doveadm_cmd *cmd)
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen{
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen help_to(cmd, stdout);
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen}
9f3bb0e10835efb0c9b1eb9e09e16b614ec41b97Timo Sirainen
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic void ATTR_NORETURN
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomihelp_to_ver2(const struct doveadm_cmd_ver2 *cmd, FILE *out)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi fprintf(out, "doveadm %s %s\n", cmd->name, cmd->usage);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi exit(EX_USAGE);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomivoid help_ver2(const struct doveadm_cmd_ver2 *cmd)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi help_to_ver2(cmd, stdout);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
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{
06af65f82453bb976cf8aa6fe2507e3a6253a04fTimo Sirainen env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
06af65f82453bb976cf8aa6fe2507e3a6253a04fTimo Sirainen master_service_get_config_path(master_service), NULL));
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
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainenstatic void cmd_exec(int argc ATTR_UNUSED, char *argv[]);
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainenstatic struct doveadm_cmd doveadm_cmd_exec = {
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen cmd_exec, "exec", "<binary> [binary parameters]"
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen};
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainenstatic void cmd_exec(int argc ATTR_UNUSED, char *argv[])
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen{
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen const char *path, *binary = argv[1];
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen if (binary == NULL)
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen help(&doveadm_cmd_exec);
cc52f19439f17c03e37fd65c6299a77d5c5e638aTimo Sirainen
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen path = t_strdup_printf("%s/%s", doveadm_settings->libexec_dir, binary);
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen argv++;
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen argv[0] = t_strdup_noconst(path);
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen (void)execv(argv[0], argv);
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen i_fatal("execv(%s) failed: %m", argv[0]);
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen}
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainenstatic bool doveadm_try_run(const char *cmd_name, int argc,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const argv[])
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen{
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen const struct doveadm_cmd *cmd;
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen
7d500ecf27acc5b65615ee9e72d6da6bacf799d2Timo Sirainen cmd = doveadm_cmd_find_with_args(cmd_name, &argc, &argv);
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen if (cmd == NULL)
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen return FALSE;
79bbb900ffba886779474dfb04c41408f0ba0602Timo Sirainen cmd->cmd(argc, (char **)argv);
e16cdc182bf122c37e252b49809db688e874b2a3Timo Sirainen return TRUE;
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen}
acc039dfc0b0f4588cf2feec04727b61e1c672a1Timo Sirainen
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainenstatic bool doveadm_has_subcommands(const char *cmd_name)
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen{
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen const struct doveadm_cmd_ver2 *cmd2;
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen const struct doveadm_cmd *cmd;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len = strlen(cmd_name);
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen array_foreach(&doveadm_cmds, cmd) {
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen if (strncmp(cmd->name, cmd_name, len) == 0 &&
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen cmd->name[len] == ' ')
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen return TRUE;
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen }
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen array_foreach(&doveadm_cmds_ver2, cmd2) {
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen if (strncmp(cmd2->name, cmd_name, len) == 0 &&
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen cmd2->name[len] == ' ')
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen return TRUE;
bef3447d29acf374bbae54bc7d6bba2583c6d5eaTimo Sirainen }
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen return doveadm_mail_has_subcommands(cmd_name);
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen}
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo 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;
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo Sirainen const struct doveadm_settings *set;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen const char *error;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&input);
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen input.roots = set_roots;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen input.module = "doveadm";
c1fc5a97a15332f1253ee13a9cab65a7b4b6cd5fTimo Sirainen input.service = "doveadm";
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen input.preserve_user = TRUE;
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);
e5d7056b6ef069e228f8ad3c9467662955cab3c6Timo Sirainen
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen service_set = master_service_settings_get(master_service);
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen service_set = settings_dup(&master_service_setting_parser_info,
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen service_set, pool_datastack_create());
6c40413c6e64fde2d977cd6076afa97fa57b67fcTimo Sirainen doveadm_verbose_proctitle = service_set->verbose_proctitle;
2e533fb1283b5f06a4063b519e47f1861c910386Timo Sirainen
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo Sirainen set = master_service_settings_get_others(master_service)[0];
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo Sirainen doveadm_settings = settings_dup(&doveadm_setting_parser_info, set,
e5d7056b6ef069e228f8ad3c9467662955cab3c6Timo Sirainen pool_datastack_create());
afd6d387ea65843b59fb6051fb567719d2a5279cAki Tuomi
afd6d387ea65843b59fb6051fb567719d2a5279cAki Tuomi doveadm_settings->parsed_features = set->parsed_features; /* copy this value by hand */
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen}
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenstatic struct doveadm_cmd *doveadm_cmdline_commands[] = {
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_help,
a3a55999bcfe2e57941cb64343f4ea80beabdab7Timo Sirainen &doveadm_cmd_config,
f2a1955d993f67982bc40ad7bbae9a036dabfd64Timo Sirainen &doveadm_cmd_exec,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_dump,
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen &doveadm_cmd_pw,
4605cab1123700c52c515a433a2802fcbc827c62Timo Sirainen &doveadm_cmd_zlibconnect
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 |
f36c4185474823594a78b3f252e79d8923522c36Timo Sirainen MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN |
f36c4185474823594a78b3f252e79d8923522c36Timo Sirainen MASTER_SERVICE_FLAG_NO_INIT_DATASTACK_FRAME;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi struct doveadm_cmd_context cctx;
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo Sirainen const char *cmd_name;
ff3337516aad9843599905aeeb29812ea67c09d1Timo Sirainen unsigned int i;
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen bool quick_init = FALSE;
5296198635718c9bf5b2f972c9d5be52092d3d58Timo Sirainen int c;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&cctx);
6fc40674e5a33787ae7fcd47a77a77ea20977994Aki Tuomi cctx.conn_type = DOVEADM_CONNECTION_TYPE_CLI;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen i_set_failure_exit_callback(failure_exit_callback);
885a3c2287ae3e5827aa580ea06b231de38abb47Timo Sirainen doveadm_dsync_main(&argc, &argv);
885a3c2287ae3e5827aa580ea06b231de38abb47Timo 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,
ce9619645e0ec302c208690e9f9bc65037c05196Timo Sirainen &argc, &argv, "+Df:hv");
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;
ce9619645e0ec302c208690e9f9bc65037c05196Timo Sirainen case 'h':
ce9619645e0ec302c208690e9f9bc65037c05196Timo Sirainen doveadm_print_hide_titles = TRUE;
ce9619645e0ec302c208690e9f9bc65037c05196Timo 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 {
d5ef38077adbff5b3e4d0b3c94a2057581dc78b6Timo Sirainen doveadm_read_settings();
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen }
851404049fe55a02fb69d7c2b4d851d2d0fd4b8dTimo Sirainen master_service_init_log(master_service, "doveadm: ");
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_cmds_init();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_cmdline_commands); i++)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_cmd(doveadm_cmdline_commands[i]);
a13b1245bee0b6524b4aeb3c8fd9e34af648b746Aki Tuomi doveadm_register_auth_commands();
6ef83bcdc4e40d6b387857e5f7d58cd86c71ec50Timo Sirainen doveadm_cmd_register_ver2(&doveadm_cmd_oldstats_top_ver2);
676d5601a8e087b25eb4dd5509079ab832e66831Aki Tuomi
968b2f633b7405bc2cf0596d04762994ceb279d0Timo Sirainen if (cmd_name != NULL && (quick_init ||
2f896df28bbb7751c6d77219cb6675fa091d3c7aTimo Sirainen strcmp(cmd_name, "config") == 0 ||
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;
d3c2ca49bbac9f5eea8038a9016aaf68679ba0c5Timo Sirainen master_service_init_stats_client(master_service, TRUE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi doveadm_print_ostream = o_stream_create_fd(STDOUT_FILENO, 0);
57591c5ea045b6829ebcfed9b145d719d63f935aTimo Sirainen o_stream_set_no_error_handling(doveadm_print_ostream, TRUE);
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen doveadm_dump_init();
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen doveadm_mail_init();
eee37857404ee76763762483a3e6e83618e16e62Timo Sirainen dict_drivers_register_builtin();
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;
975c2cdc1b09131553c3849b96d30b2e89dd0e24Timo Sirainen i_getopt_reset();
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
619994941f9d9e8e2d108eb3f9f9821a35f60caeAki Tuomi /* this has to be done here because proctitle hack can break
619994941f9d9e8e2d108eb3f9f9821a35f60caeAki Tuomi the env pointer */
619994941f9d9e8e2d108eb3f9f9821a35f60caeAki Tuomi cctx.username = getenv("USER");
619994941f9d9e8e2d108eb3f9f9821a35f60caeAki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if (!doveadm_cmd_try_run_ver2(cmd_name, argc, (const char**)argv, &cctx) &&
79bbb900ffba886779474dfb04c41408f0ba0602Timo Sirainen !doveadm_try_run(cmd_name, argc, (const char **)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();
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen doveadm_dump_deinit();
1c633f71ec2060e5bfa500a97f34cd881a958ecdTimo Sirainen doveadm_unload_modules();
eee37857404ee76763762483a3e6e83618e16e62Timo Sirainen dict_drivers_unregister_builtin();
7ed711d973b319320da100d3e905ef7b99ed69d6Timo Sirainen doveadm_print_deinit();
57591c5ea045b6829ebcfed9b145d719d63f935aTimo Sirainen o_stream_unref(&doveadm_print_ostream);
a2857829c642e2671779576b00c37b7d04693731Timo Sirainen }
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_cmds_deinit();
4909421ac41e143fe07a235c0d11e9f0452d716bTimo Sirainen master_service_deinit(&master_service);
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return doveadm_exit_code;
a6ab8f00351265e35b79f3a22b1f5a4978ae5c35Timo Sirainen}