aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi/* Copyright (c) 2009-2r016 Dovecot authors, see the included COPYING file */
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen#include "lib.h"
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen#include "array.h"
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include "istream.h"
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include "str.h"
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi#include "net.h"
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include "doveadm.h"
d29c67900d3d104e24ed213ed4a10d204decdf18Aki Tuomi#include "doveadm-cmd.h"
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include <stdio.h>
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include <unistd.h>
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi#include <getopt.h>
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen &doveadm_cmd_mailbox_mutf7,
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen &doveadm_cmd_sis_deduplicate,
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen &doveadm_cmd_sis_find,
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen};
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
53309922d2ec3321e011966e8f2b210821ecd5e3Timo Sirainen &doveadm_cmd_service_stop_ver2,
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen &doveadm_cmd_service_status_ver2,
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen &doveadm_cmd_process_status_ver2,
68cc278710182485b6c09e9a9ff8db90a727f343Aki Tuomi &doveadm_cmd_stop_ver2,
676d5601a8e087b25eb4dd5509079ab832e66831Aki Tuomi &doveadm_cmd_reload_ver2,
285f3c4cf828ebe9ff345080aa1df3755613af29Timo Sirainen &doveadm_cmd_stats_dump_ver2,
6ef83bcdc4e40d6b387857e5f7d58cd86c71ec50Timo Sirainen &doveadm_cmd_oldstats_dump_ver2,
6ef83bcdc4e40d6b387857e5f7d58cd86c71ec50Timo Sirainen &doveadm_cmd_oldstats_reset_ver2,
99819adc9638200bc2ec1b68da9d2c68e8435740Aki Tuomi &doveadm_cmd_penalty_ver2,
6eb1a7a7ae2c1dfff6731956ade08f9a4a7c791aAki Tuomi &doveadm_cmd_kick_ver2,
99819adc9638200bc2ec1b68da9d2c68e8435740Aki Tuomi &doveadm_cmd_who_ver2
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi};
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomistatic const struct exit_code_str {
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi int code;
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi const char *str;
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi} exit_code_strings[] = {
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { DOVEADM_EX_UNKNOWN, "UNKNOWN" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_TEMPFAIL, "TEMPFAIL" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_USAGE, "USAGE" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_NOUSER, "NOUSER" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_NOPERM, "NOPERM" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_PROTOCOL, "PROTOCOL" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { EX_DATAERR, "DATAERR" },
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi { DOVEADM_EX_NOTFOUND, "NOTFOUND" }
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi};
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo SirainenARRAY_TYPE(doveadm_cmd) doveadm_cmds;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki TuomiARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki TuomiARRAY_DEFINE_TYPE(getopt_option_array, struct option);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomiconst char *doveadm_exit_code_to_str(int code)
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi{
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi const struct exit_code_str *ptr = &exit_code_strings[i];
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi if (ptr->code == code)
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi return ptr->str;
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi }
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi return "UNKNOWN";
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi}
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomiint doveadm_str_to_exit_code(const char *reason)
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi{
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi const struct exit_code_str *ptr = &exit_code_strings[i];
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi if (strcmp(ptr->str, reason) == 0)
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi return ptr->code;
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi }
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi return DOVEADM_EX_UNKNOWN;
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi}
c466bbccb4b8b0026aea13540ebdef3bddbd67ddAki Tuomi
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen{
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen array_append(&doveadm_cmds, cmd, 1);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen}
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomivoid doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (cmd->cmd == NULL) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (cmd->mail_cmd != NULL)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi cmd->cmd = doveadm_cmd_ver2_to_mail_cmd_wrapper;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi else if (cmd->old_cmd != NULL)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi cmd->cmd = doveadm_cmd_ver2_to_cmd_wrapper;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi else i_unreached();
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append(&doveadm_cmds_ver2, cmd, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomiconst struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name)
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi{
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi const struct doveadm_cmd_ver2 *cmd;
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi array_foreach(&doveadm_cmds_ver2, cmd) {
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi if (strcmp(cmd_name, cmd->name)==0)
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi return cmd;
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi }
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi return NULL;
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi}
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomi
7d500ecf27acc5b65615ee9e72d6da6bacf799d2Timo Sirainenconst struct doveadm_cmd_ver2 *
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainendoveadm_cmd_find_with_args_ver2(const char *cmd_name, int *argc,
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen const char *const *argv[])
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen int i, k;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const struct doveadm_cmd_ver2 *cmd;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const char *cptr;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen for(i=0;i<*argc;i++) {
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen if (strcmp((*argv)[i],cmd_name)==0) break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen i_assert(i != *argc);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_foreach(&doveadm_cmds_ver2, cmd) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi cptr = cmd->name;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* cannot reuse i here because this needs be
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi done more than once */
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen for (k=0; *cptr != '\0' && i+k < *argc; k++) {
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen size_t alen = strlen((*argv)[i+k]);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* make sure we don't overstep */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (strlen(cptr) < alen) break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* did not match */
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen if (strncmp(cptr, (*argv)[i+k], alen) != 0) break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* do not accept abbreviations */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (cptr[alen] != ' ' && cptr[alen] != '\0') break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi cptr += alen;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (*cptr != '\0') cptr++; /* consume space */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* name was fully consumed */
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen if (*cptr == '\0') {
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen if (k > 1) {
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen *argc -= k-1;
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen *argv += k-1;
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen }
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen return cmd;
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return NULL;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainenstatic bool
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainendoveadm_cmd_find_multi_word(const char *cmdname, int *_argc,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const *_argv[])
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen{
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen int argc = *_argc;
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const *argv = *_argv;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (argc < 2)
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen return FALSE;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen len = strlen(argv[1]);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (strncmp(cmdname, argv[1], len) != 0)
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen return FALSE;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen argc--; argv++;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (cmdname[len] == ' ') {
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen /* more args */
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen if (!doveadm_cmd_find_multi_word(cmdname + len + 1,
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen &argc, &argv))
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen return FALSE;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen } else {
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (cmdname[len] != '\0')
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen return FALSE;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen }
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen *_argc = argc;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen *_argv = argv;
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen return TRUE;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen}
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenconst struct doveadm_cmd *
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainendoveadm_cmd_find_with_args(const char *cmd_name, int *argc,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const *argv[])
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen{
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen const struct doveadm_cmd *cmd;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t cmd_name_len;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen i_assert(*argc > 0);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen cmd_name_len = strlen(cmd_name);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen array_foreach(&doveadm_cmds, cmd) {
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (strcmp(cmd->name, cmd_name) == 0)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen return cmd;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen /* see if it matches a multi-word command */
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen cmd->name[cmd_name_len] == ' ') {
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen const char *subcmd_name = cmd->name + cmd_name_len + 1;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen if (doveadm_cmd_find_multi_word(subcmd_name,
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen argc, argv))
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen return cmd;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen }
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen }
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen return NULL;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen}
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenvoid doveadm_cmds_init(void)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen{
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen unsigned int i;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen i_array_init(&doveadm_cmds, 32);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi i_array_init(&doveadm_cmds_ver2, 2);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_cmd(doveadm_commands[i]);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_director_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_instance_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_proxy_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_log_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_replicator_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_dict_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen doveadm_register_fs_commands();
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen}
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenvoid doveadm_cmds_deinit(void)
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen{
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen array_free(&doveadm_cmds);
368ec06f20b95d29d0bbd5655030048d060a2582Timo Sirainen array_free(&doveadm_cmds_ver2);
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainenstatic const struct doveadm_cmd_param*
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomidoveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi i_assert(cctx != NULL);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi i_assert(cctx->argv != NULL);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi for(int i = 0; i < cctx->argc; i++) {
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if (strcmp(cctx->argv[i].name, name) == 0 && cctx->argv[i].value_set)
c5e46dba179864f6f1adf196d46e7a0371b11914Josef 'Jeff' Sipek return &cctx->argv[i];
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return NULL;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name, bool *value_r)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const struct doveadm_cmd_param *param;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
05128fda80748e107bccdece0a3d23551e99e8f3Timo Sirainen if (param->type == CMD_PARAM_BOOL) {
db8b229230860a6c12daa0017a49396986368897Aki Tuomi *value_r = param->value.v_bool;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name, int64_t *value_r)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const struct doveadm_cmd_param *param;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (param->type == CMD_PARAM_INT64) {
db8b229230860a6c12daa0017a49396986368897Aki Tuomi *value_r = param->value.v_int64;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name, const char **value_r)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const struct doveadm_cmd_param *param;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (param->type == CMD_PARAM_STR) {
db8b229230860a6c12daa0017a49396986368897Aki Tuomi *value_r = param->value.v_string;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name, struct ip_addr *value_r)
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi{
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const struct doveadm_cmd_param *param;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi if (param->type == CMD_PARAM_IP) {
db8b229230860a6c12daa0017a49396986368897Aki Tuomi memcpy(value_r, &param->value.v_ip, sizeof(struct ip_addr));
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi return TRUE;
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi }
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi return FALSE;
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi}
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
4afc67eb96f8d6b7dc94d63d3c7fe4f556c4fceeTimo Sirainen const char *name, const char *const **value_r)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen const struct doveadm_cmd_param *param;
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen unsigned int count;
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
f169d423d8db89e36f764263aa4cfe46c62d5a2bAki Tuomi if (param->type == CMD_PARAM_ARRAY) {
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen *value_r = array_get(&param->value.v_array, &count);
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen /* doveadm_cmd_params_null_terminate_arrays() should have been
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen called, which guarantees that we're NULL-terminated */
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen i_assert((*value_r)[count] == NULL);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name, struct istream **value_r)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const struct doveadm_cmd_param *param;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (param->type == CMD_PARAM_ISTREAM) {
db8b229230860a6c12daa0017a49396986368897Aki Tuomi *value_r = param->value.v_istream;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainenvoid doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen{
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen struct doveadm_cmd_param *param;
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen array_foreach_modifiable(pargv, param) {
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen if (param->type == CMD_PARAM_ISTREAM &&
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen param->value.v_istream != NULL)
c5e46dba179864f6f1adf196d46e7a0371b11914Josef 'Jeff' Sipek i_stream_destroy(&param->value.v_istream);
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen }
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen array_clear(pargv);
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen}
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainenvoid doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen{
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen struct doveadm_cmd_param *param;
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen array_foreach_modifiable(pargv, param) {
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen if (param->type == CMD_PARAM_ARRAY &&
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen array_is_created(&param->value.v_array)) {
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen array_append_zero(&param->value.v_array);
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen array_delete(&param->value.v_array, array_count(&param->value.v_array)-1, 1);
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen }
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen }
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen}
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic void
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomidoveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi ARRAY_TYPE(const_string) *argv)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi bool array_add_opt;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi int i;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const char * const * cptr;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi i_assert(array_count(argv) == 0);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append(argv, &name, 1);
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi ARRAY_TYPE(const_string) pargv;
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi t_array_init(&pargv, 8);
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for(i=0;i<pargc;i++) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi const char *optarg = NULL;
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi ARRAY_TYPE(const_string) *target = argv;
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi if ((params[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0)
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi target = &pargv;
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi /* istreams are special */
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi i_assert(params[i].type != CMD_PARAM_ISTREAM);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi if (params[i].value_set) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi array_add_opt = FALSE;
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi if (params[i].short_opt != '\0') {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi if (params[i].type == CMD_PARAM_ARRAY) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi array_add_opt = TRUE;
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi } else {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi optarg = t_strdup_printf("-%c", params[i].short_opt);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi array_append(argv, &optarg, 1);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi }
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi }
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi /* CMD_PARAM_BOOL is implicitly handled above */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (params[i].type == CMD_PARAM_STR) {
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi array_append(target, &params[i].value.v_string,1);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi } else if (params[i].type == CMD_PARAM_INT64) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi const char *tmp = t_strdup_printf("%lld",
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi (long long)params[i].value.v_int64);
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi array_append(target, &tmp, 1);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi } else if (params[i].type == CMD_PARAM_IP) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi const char *tmp = net_ip2addr(&params[i].value.v_ip);
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi array_append(target, &tmp, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi } else if (params[i].type == CMD_PARAM_ARRAY) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_foreach(&params[i].value.v_array, cptr) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi if (array_add_opt)
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi array_append(argv, &optarg, 1);
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi array_append(target, cptr, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi if (array_count(&pargv) > 0) {
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi const char *dashdash = "--";
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi array_append(argv, &dashdash, 1);
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi array_append_array(argv, &pargv);
235ef8cd3865984cc27f88a18d14ea98adb53f09Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append_zero(argv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
cd75585e26420cef09cc699c6e02ab46e21937d1Aki Tuomivoid
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomidoveadm_cmd_ver2_to_cmd_wrapper(struct doveadm_cmd_context *cctx)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi unsigned int pargc;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const char **pargv;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi i_assert(cctx->cmd->old_cmd != NULL);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi ARRAY_TYPE(const_string) nargv;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi t_array_init(&nargv, 8);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi doveadm_cmd_params_to_argv(cctx->cmd->name, cctx->argc, cctx->argv, &nargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi pargv = array_get_modifiable(&nargv, &pargc);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi i_getopt_reset();
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi cctx->cmd->old_cmd(pargc-1, (char**)pargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic void
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomidoveadm_build_options(const struct doveadm_cmd_param par[],
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi string_t *shortopts,
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi ARRAY_TYPE(getopt_option_array) *longopts)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for(size_t i=0; par[i].name != NULL; i++) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi struct option longopt;
a18ba96c4ecebc9386b92385c546c868f1eae82eTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&longopt);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi longopt.name = par[i].name;
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen if (par[i].short_opt != '\0') {
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen longopt.val = par[i].short_opt;
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen str_append_c(shortopts, par[i].short_opt);
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen if (par[i].type != CMD_PARAM_BOOL)
14102a0c5db8828ca8c7751ec96587fadc97a0bcTimo Sirainen str_append_c(shortopts, ':');
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
a18ba96c4ecebc9386b92385c546c868f1eae82eTimo Sirainen if (par[i].type != CMD_PARAM_BOOL)
a18ba96c4ecebc9386b92385c546c868f1eae82eTimo Sirainen longopt.has_arg = 1;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append(longopts, &longopt, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append_zero(longopts);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic void doveadm_fill_param(struct doveadm_cmd_param *param,
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const char *value, pool_t pool)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param->value_set = TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi switch(param->type) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case CMD_PARAM_BOOL:
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param->value.v_bool = TRUE; break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case CMD_PARAM_INT64:
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (str_to_int64(value, &param->value.v_int64) != 0) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param->value_set = FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi break;
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi case CMD_PARAM_IP:
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi if (net_addr2ip(value, &param->value.v_ip) != 0) {
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi param->value_set = FALSE;
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi }
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case CMD_PARAM_STR:
3d27e1102558215203b73c58a2cba84dccf0dd1aTimo Sirainen param->value.v_string = p_strdup(pool, value);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case CMD_PARAM_ARRAY:
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (!array_is_created(&param->value.v_array))
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi p_array_init(&param->value.v_array, pool, 8);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const char *val = p_strdup(pool, value);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_append(&param->value.v_array, &val, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case CMD_PARAM_ISTREAM: {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi struct istream *is;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (strcmp(value,"-") == 0) {
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi } else {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi is = i_stream_create_file(value, IO_BLOCK_SIZE);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param->value.v_istream = is;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
79bbb900ffba886779474dfb04c41408f0ba0602Timo Sirainenbool doveadm_cmd_try_run_ver2(const char *cmd_name,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen int argc, const char *const argv[],
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi struct doveadm_cmd_context *cctx)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const struct doveadm_cmd_ver2 *cmd;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen cmd = doveadm_cmd_find_with_args_ver2(cmd_name, &argc, &argv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (cmd == NULL)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi cctx->cmd = cmd;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if (doveadm_cmd_run_ver2(argc, argv, cctx) < 0)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi doveadm_exit_code = EX_USAGE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainenint doveadm_cmd_run_ver2(int argc, const char *const argv[],
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi struct doveadm_cmd_context *cctx)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi{
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi struct doveadm_cmd_param *param;
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen ARRAY_TYPE(doveadm_cmd_param_arr_t) pargv;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi ARRAY_TYPE(getopt_option_array) opts;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi unsigned int pargc;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi int c,li;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi pool_t pool = pool_datastack_create();
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi string_t *optbuf = str_new(pool, 64);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi p_array_init(&opts, pool, 4);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi // build parameters
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi p_array_init(&pargv, pool, 20);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi for(pargc=0;cctx->cmd->parameters[pargc].name != NULL;pargc++) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param = array_append_space(&pargv);
c5e46dba179864f6f1adf196d46e7a0371b11914Josef 'Jeff' Sipek memcpy(param, &cctx->cmd->parameters[pargc], sizeof(struct doveadm_cmd_param));
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi param->value_set = FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi switch(c) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case 0:
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi for(unsigned int i = 0; i < array_count(&pargv); i++) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi const struct option *opt = array_idx(&opts,li);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi param = array_idx_modifiable(&pargv,i);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi if (opt->name == param->name)
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi doveadm_fill_param(param, optarg, pool);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case '?':
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi case ':':
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen doveadm_cmd_params_clean(&pargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return -1;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi default:
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi // hunt the option
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for(unsigned int i = 0; i < pargc; i++) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi const struct option *longopt = array_idx(&opts,i);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (longopt->val == c)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* process positional arguments */
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi for(;optind<argc;optind++) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi struct doveadm_cmd_param *ptr;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi bool found = FALSE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi array_foreach_modifiable(&pargv, ptr) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi doveadm_fill_param(ptr, argv[optind], pool);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi found = TRUE;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi break;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (!found) {
b0d00847d0e1ab20662efce5b24f8fee6897c6feTimo Sirainen i_error("Extraneous arguments found: %s",
b0d00847d0e1ab20662efce5b24f8fee6897c6feTimo Sirainen t_strarray_join(argv+optind, " "));
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen doveadm_cmd_params_clean(&pargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return -1;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi }
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen doveadm_cmd_params_null_terminate_arrays(&pargv);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi cctx->argv = array_get_modifiable(&pargv, &pargc);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi cctx->argc = pargc;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi cctx->cmd->cmd(cctx);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainen doveadm_cmd_params_clean(&pargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi return 0;
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi}