0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2009-2r016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "net.h"
89b548af722113acb5d63dfffb44423cb60f91e4Timo Sirainen#include "doveadm.h"
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen#include "doveadm-cmd.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdio.h>
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <getopt.h>
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_mailbox_mutf7,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_sis_deduplicate,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_sis_find,
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen};
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen &doveadm_cmd_service_stop_ver2,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen &doveadm_cmd_service_status_ver2,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen &doveadm_cmd_process_status_ver2,
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainen &doveadm_cmd_stop_ver2,
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen &doveadm_cmd_reload_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_stats_dump_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_oldstats_dump_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_oldstats_reset_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_penalty_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_kick_ver2,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen &doveadm_cmd_who_ver2
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen};
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainenstatic const struct exit_code_str {
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen int code;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen const char *str;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen} exit_code_strings[] = {
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen { DOVEADM_EX_UNKNOWN, "UNKNOWN" },
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainen { EX_TEMPFAIL, "TEMPFAIL" },
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen { EX_USAGE, "USAGE" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { EX_NOUSER, "NOUSER" },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { EX_NOPERM, "NOPERM" },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { EX_PROTOCOL, "PROTOCOL" },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { EX_DATAERR, "DATAERR" },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { DOVEADM_EX_NOTFOUND, "NOTFOUND" }
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen};
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenARRAY_TYPE(doveadm_cmd) doveadm_cmds;
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenARRAY_DEFINE_TYPE(getopt_option_array, struct option);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *doveadm_exit_code_to_str(int code)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct exit_code_str *ptr = &exit_code_strings[i];
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (ptr->code == code)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return ptr->str;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen return "UNKNOWN";
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenint doveadm_str_to_exit_code(const char *reason)
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen{
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const struct exit_code_str *ptr = &exit_code_strings[i];
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (strcmp(ptr->str, reason) == 0)
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen return ptr->code;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return DOVEADM_EX_UNKNOWN;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&doveadm_cmds, cmd, 1);
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen}
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenvoid doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen{
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (cmd->cmd == NULL) {
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen if (cmd->mail_cmd != NULL)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen cmd->cmd = doveadm_cmd_ver2_to_mail_cmd_wrapper;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen else if (cmd->old_cmd != NULL)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen cmd->cmd = doveadm_cmd_ver2_to_cmd_wrapper;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen else i_unreached();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen array_append(&doveadm_cmds_ver2, cmd, 1);
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen}
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenconst struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name)
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen{
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const struct doveadm_cmd_ver2 *cmd;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen array_foreach(&doveadm_cmds_ver2, cmd) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (strcmp(cmd_name, cmd->name)==0)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return cmd;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen return NULL;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen}
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainenconst struct doveadm_cmd_ver2 *
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainendoveadm_cmd_find_with_args_ver2(const char *cmd_name, int *argc,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const char *const *argv[])
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen int i, k;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct doveadm_cmd_ver2 *cmd;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const char *cptr;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for(i=0;i<*argc;i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (strcmp((*argv)[i],cmd_name)==0) break;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen i_assert(i != *argc);
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen array_foreach(&doveadm_cmds_ver2, cmd) {
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen cptr = cmd->name;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* cannot reuse i here because this needs be
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen done more than once */
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen for (k=0; *cptr != '\0' && i+k < *argc; k++) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen size_t alen = strlen((*argv)[i+k]);
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen /* make sure we don't overstep */
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen if (strlen(cptr) < alen) break;
da985034a708db2f61394b30d117050ae6829ee5Timo Sirainen /* did not match */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (strncmp(cptr, (*argv)[i+k], alen) != 0) break;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* do not accept abbreviations */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (cptr[alen] != ' ' && cptr[alen] != '\0') break;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen cptr += alen;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (*cptr != '\0') cptr++; /* consume space */
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* name was fully consumed */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (*cptr == '\0') {
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen if (k > 1) {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *argc -= k-1;
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen *argv += k-1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return cmd;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return NULL;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen}
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic bool
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainendoveadm_cmd_find_multi_word(const char *cmdname, int *_argc,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const *_argv[])
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen{
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen int argc = *_argc;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen const char *const *argv = *_argv;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen size_t len;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (argc < 2)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return FALSE;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen len = strlen(argv[1]);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen if (strncmp(cmdname, argv[1], len) != 0)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen return FALSE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen argc--; argv++;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen if (cmdname[len] == ' ') {
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* more args */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (!doveadm_cmd_find_multi_word(cmdname + len + 1,
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen &argc, &argv))
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return FALSE;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen } else {
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (cmdname[len] != '\0')
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen return FALSE;
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen }
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *_argc = argc;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen *_argv = argv;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen return TRUE;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen}
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenconst struct doveadm_cmd *
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainendoveadm_cmd_find_with_args(const char *cmd_name, int *argc,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const *argv[])
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen{
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const struct doveadm_cmd *cmd;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen size_t cmd_name_len;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen i_assert(*argc > 0);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen cmd_name_len = strlen(cmd_name);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen array_foreach(&doveadm_cmds, cmd) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
367c05967091a2cbfce59b7f274f55b1a0f9e8c9Timo Sirainen return cmd;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen /* see if it matches a multi-word command */
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen cmd->name[cmd_name_len] == ' ') {
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen const char *subcmd_name = cmd->name + cmd_name_len + 1;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (doveadm_cmd_find_multi_word(subcmd_name,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen argc, argv))
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen return cmd;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenvoid doveadm_cmds_init(void)
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen{
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen unsigned int i;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen i_array_init(&doveadm_cmds, 32);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen i_array_init(&doveadm_cmds_ver2, 2);
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen doveadm_register_cmd(doveadm_commands[i]);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen doveadm_register_director_commands();
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen doveadm_register_instance_commands();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen doveadm_register_proxy_commands();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen doveadm_register_log_commands();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen doveadm_register_replicator_commands();
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen doveadm_register_dict_commands();
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen doveadm_register_fs_commands();
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenvoid doveadm_cmds_deinit(void)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen array_free(&doveadm_cmds);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen array_free(&doveadm_cmds_ver2);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic const struct doveadm_cmd_param*
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainendoveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *name)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(cctx != NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(cctx->argv != NULL);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for(int i = 0; i < cctx->argc; i++) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(cctx->argv[i].name, name) == 0 && cctx->argv[i].value_set)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return &cctx->argv[i];
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return NULL;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenbool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen const char *name, bool *value_r)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct doveadm_cmd_param *param;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
1175f27441385a7011629f295f42708f9a3a4ffcTimo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen if (param->type == CMD_PARAM_BOOL) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen *value_r = param->value.v_bool;
053843989f13d9013b265fb401a4bde7e0e6568eTimo Sirainen return TRUE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen return FALSE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenbool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *name, int64_t *value_r)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct doveadm_cmd_param *param;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
ab286a8b58306eb8d22fc18342b6c199fd428e1eTimo Sirainen if (param->type == CMD_PARAM_INT64) {
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen *value_r = param->value.v_int64;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen return TRUE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen }
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenbool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *name, const char **value_r)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const struct doveadm_cmd_param *param;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (param->type == CMD_PARAM_STR) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen *value_r = param->value.v_string;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenbool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char *name, struct ip_addr *value_r)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen const struct doveadm_cmd_param *param;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (param->type == CMD_PARAM_IP) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen memcpy(value_r, &param->value.v_ip, sizeof(struct ip_addr));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen return TRUE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenbool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen const char *name, const char *const **value_r)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const struct doveadm_cmd_param *param;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen unsigned int count;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if (param->type == CMD_PARAM_ARRAY) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen *value_r = array_get(&param->value.v_array, &count);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen /* doveadm_cmd_params_null_terminate_arrays() should have been
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen called, which guarantees that we're NULL-terminated */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen i_assert((*value_r)[count] == NULL);
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen return TRUE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return FALSE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenbool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen const char *name, struct istream **value_r)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen const struct doveadm_cmd_param *param;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if (param->type == CMD_PARAM_ISTREAM) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *value_r = param->value.v_istream;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return TRUE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenvoid doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen{
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen struct doveadm_cmd_param *param;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_foreach_modifiable(pargv, param) {
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (param->type == CMD_PARAM_ISTREAM &&
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen param->value.v_istream != NULL)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_stream_destroy(&param->value.v_istream);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen array_clear(pargv);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen}
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainenvoid doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen{
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen struct doveadm_cmd_param *param;
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_foreach_modifiable(pargv, param) {
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen if (param->type == CMD_PARAM_ARRAY &&
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_is_created(&param->value.v_array)) {
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_append_zero(&param->value.v_array);
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_delete(&param->value.v_array, array_count(&param->value.v_array)-1, 1);
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen }
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen }
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen}
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainenstatic void
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainendoveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen ARRAY_TYPE(const_string) *argv)
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen{
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainen bool array_add_opt;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen int i;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen const char * const * cptr;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen i_assert(array_count(argv) == 0);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen array_append(argv, &name, 1);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ARRAY_TYPE(const_string) pargv;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen t_array_init(&pargv, 8);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for(i=0;i<pargc;i++) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *optarg = NULL;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen ARRAY_TYPE(const_string) *target = argv;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if ((params[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen target = &pargv;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* istreams are special */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen i_assert(params[i].type != CMD_PARAM_ISTREAM);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (params[i].value_set) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_add_opt = FALSE;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (params[i].short_opt != '\0') {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (params[i].type == CMD_PARAM_ARRAY) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_add_opt = TRUE;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen } else {
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen optarg = t_strdup_printf("-%c", params[i].short_opt);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen array_append(argv, &optarg, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* CMD_PARAM_BOOL is implicitly handled above */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (params[i].type == CMD_PARAM_STR) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(target, &params[i].value.v_string,1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (params[i].type == CMD_PARAM_INT64) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *tmp = t_strdup_printf("%lld",
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen (long long)params[i].value.v_int64);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(target, &tmp, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (params[i].type == CMD_PARAM_IP) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *tmp = net_ip2addr(&params[i].value.v_ip);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(target, &tmp, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (params[i].type == CMD_PARAM_ARRAY) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_foreach(&params[i].value.v_array, cptr) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (array_add_opt)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(argv, &optarg, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(target, cptr, 1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (array_count(&pargv) > 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *dashdash = "--";
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(argv, &dashdash, 1);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen array_append_array(argv, &pargv);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen array_append_zero(argv);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenvoid
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainendoveadm_cmd_ver2_to_cmd_wrapper(struct doveadm_cmd_context *cctx)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int pargc;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char **pargv;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_assert(cctx->cmd->old_cmd != NULL);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ARRAY_TYPE(const_string) nargv;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen t_array_init(&nargv, 8);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen doveadm_cmd_params_to_argv(cctx->cmd->name, cctx->argc, cctx->argv, &nargv);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen pargv = array_get_modifiable(&nargv, &pargc);
b4931fc08faa0079f32f29286f4c3abd0d8788bcTimo Sirainen i_getopt_reset();
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen cctx->cmd->old_cmd(pargc-1, (char**)pargv);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainendoveadm_build_options(const struct doveadm_cmd_param par[],
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen string_t *shortopts,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ARRAY_TYPE(getopt_option_array) *longopts)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen for(size_t i=0; par[i].name != NULL; i++) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct option longopt;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_zero(&longopt);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen longopt.name = par[i].name;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (par[i].short_opt != '\0') {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen longopt.val = par[i].short_opt;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append_c(shortopts, par[i].short_opt);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (par[i].type != CMD_PARAM_BOOL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen str_append_c(shortopts, ':');
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (par[i].type != CMD_PARAM_BOOL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen longopt.has_arg = 1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(longopts, &longopt, 1);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen array_append_zero(longopts);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void doveadm_fill_param(struct doveadm_cmd_param *param,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *value, pool_t pool)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen param->value_set = TRUE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen switch(param->type) {
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen case CMD_PARAM_BOOL:
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen param->value.v_bool = TRUE; break;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen case CMD_PARAM_INT64:
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (str_to_int64(value, &param->value.v_int64) != 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen param->value_set = FALSE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen break;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen case CMD_PARAM_IP:
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (net_addr2ip(value, &param->value.v_ip) != 0) {
871c7b8969e8627dc4c8b3e56fd126f948e6bce6Timo Sirainen param->value_set = FALSE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen break;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen case CMD_PARAM_STR:
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen param->value.v_string = p_strdup(pool, value);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen case CMD_PARAM_ARRAY:
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen if (!array_is_created(&param->value.v_array))
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen p_array_init(&param->value.v_array, pool, 8);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *val = p_strdup(pool, value);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen array_append(&param->value.v_array, &val, 1);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen case CMD_PARAM_ISTREAM: {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct istream *is;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (strcmp(value,"-") == 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen is = i_stream_create_file(value, IO_BLOCK_SIZE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen param->value.v_istream = is;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenbool doveadm_cmd_try_run_ver2(const char *cmd_name,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen int argc, const char *const argv[],
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct doveadm_cmd_context *cctx)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const struct doveadm_cmd_ver2 *cmd;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen cmd = doveadm_cmd_find_with_args_ver2(cmd_name, &argc, &argv);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (cmd == NULL)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return FALSE;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen cctx->cmd = cmd;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (doveadm_cmd_run_ver2(argc, argv, cctx) < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen doveadm_exit_code = EX_USAGE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return TRUE;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen}
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenint doveadm_cmd_run_ver2(int argc, const char *const argv[],
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen struct doveadm_cmd_context *cctx)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen{
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen struct doveadm_cmd_param *param;
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen ARRAY_TYPE(doveadm_cmd_param_arr_t) pargv;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ARRAY_TYPE(getopt_option_array) opts;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int pargc;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen int c,li;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_t pool = pool_datastack_create();
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen string_t *optbuf = str_new(pool, 64);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen p_array_init(&opts, pool, 4);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen // build parameters
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_array_init(&pargv, pool, 20);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for(pargc=0;cctx->cmd->parameters[pargc].name != NULL;pargc++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen param = array_append_space(&pargv);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(param, &cctx->cmd->parameters[pargc], sizeof(struct doveadm_cmd_param));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen param->value_set = FALSE;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch(c) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen case 0:
8830fab191cab8440281eb641dfdd93974b2933bTimo Sirainen for(unsigned int i = 0; i < array_count(&pargv); i++) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen const struct option *opt = array_idx(&opts,li);
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen param = array_idx_modifiable(&pargv,i);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (opt->name == param->name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_fill_param(param, optarg, pool);
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen case '?':
92888ef30960c30ccc9e030fe7eab5d4d04a7d1cTimo Sirainen case ':':
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_cmd_params_clean(&pargv);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen default:
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen // hunt the option
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen for(unsigned int i = 0; i < pargc; i++) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen const struct option *longopt = array_idx(&opts,i);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (longopt->val == c)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen }
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen /* process positional arguments */
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen for(;optind<argc;optind++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct doveadm_cmd_param *ptr;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool found = FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach_modifiable(&pargv, ptr) {
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_fill_param(ptr, argv[optind], pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen found = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!found) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Extraneous arguments found: %s",
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen t_strarray_join(argv+optind, " "));
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen doveadm_cmd_params_clean(&pargv);
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen return -1;
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen }
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen }
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen doveadm_cmd_params_null_terminate_arrays(&pargv);
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen cctx->argv = array_get_modifiable(&pargv, &pargc);
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen cctx->argc = pargc;
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cctx->cmd->cmd(cctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen doveadm_cmd_params_clean(&pargv);
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen