0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2009-2r016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstatic struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
bb10ebcf076c959c752f583746d83805d7686df8Timo SirainenARRAY_DEFINE_TYPE(getopt_option_array, struct option);
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];
ee246b46953e4b94b2f22e093373674fa9155500Timo Sirainen return "UNKNOWN";
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenint doveadm_str_to_exit_code(const char *reason)
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];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenvoid doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen cmd->cmd = doveadm_cmd_ver2_to_mail_cmd_wrapper;
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenconst struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name)
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainendoveadm_cmd_find_with_args_ver2(const char *cmd_name, int *argc,
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen const char *const *argv[])
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for(i=0;i<*argc;i++) {
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++) {
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen /* make sure we don't overstep */
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 if (*cptr != '\0') cptr++; /* consume space */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* name was fully consumed */
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainendoveadm_cmd_find_multi_word(const char *cmdname, int *_argc,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const *_argv[])
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen /* more args */
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen if (!doveadm_cmd_find_multi_word(cmdname + len + 1,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainendoveadm_cmd_find_with_args(const char *cmd_name, int *argc,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen const char *const *argv[])
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen /* see if it matches a multi-word command */
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen const char *subcmd_name = cmd->name + cmd_name_len + 1;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen unsigned int i;
003079baf8056c81c25162a176a89f9169cc374fTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic const struct doveadm_cmd_param*
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainendoveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (strcmp(cctx->argv[i].name, name) == 0 && cctx->argv[i].value_set)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainenbool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainenbool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenbool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenbool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen memcpy(value_r, ¶m->value.v_ip, sizeof(struct ip_addr));
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenbool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen const char *name, const char *const **value_r)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen *value_r = array_get(¶m->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 */
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenbool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenvoid doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainenvoid doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
b79ec51bdeef6ef950eb5e890e65cc0491cf5fe9Timo Sirainen array_delete(¶m->value.v_array, array_count(¶m->value.v_array)-1, 1);
64541374b58e4c702b1926e87df421d180ffa006Timo Sirainendoveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen for(i=0;i<pargc;i++) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if ((params[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* istreams are special */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen i_assert(params[i].type != CMD_PARAM_ISTREAM);
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen optarg = t_strdup_printf("-%c", params[i].short_opt);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* CMD_PARAM_BOOL is implicitly handled above */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_append(target, ¶ms[i].value.v_string,1);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (params[i].type == CMD_PARAM_INT64) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen const char *tmp = net_ip2addr(¶ms[i].value.v_ip);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if (params[i].type == CMD_PARAM_ARRAY) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen array_foreach(¶ms[i].value.v_array, cptr) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainendoveadm_cmd_ver2_to_cmd_wrapper(struct doveadm_cmd_context *cctx)
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainen doveadm_cmd_params_to_argv(cctx->cmd->name, cctx->argc, cctx->argv, &nargv);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainendoveadm_build_options(const struct doveadm_cmd_param par[],
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void doveadm_fill_param(struct doveadm_cmd_param *param,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (str_to_int64(value, ¶m->value.v_int64) != 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (net_addr2ip(value, ¶m->value.v_ip) != 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen param->value.v_string = p_strdup(pool, value);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen is = i_stream_create_file(value, IO_BLOCK_SIZE);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenbool doveadm_cmd_try_run_ver2(const char *cmd_name,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen cmd = doveadm_cmd_find_with_args_ver2(cmd_name, &argc, &argv);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (doveadm_cmd_run_ver2(argc, argv, cctx) < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenint doveadm_cmd_run_ver2(int argc, const char *const argv[],
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen // build parameters
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for(pargc=0;cctx->cmd->parameters[pargc].name != NULL;pargc++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(param, &cctx->cmd->parameters[pargc], sizeof(struct doveadm_cmd_param));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
8830fab191cab8440281eb641dfdd93974b2933bTimo Sirainen for(unsigned int i = 0; i < array_count(&pargv); i++) {
b2105c78f0fd58281317e6d777ded860f33153a3Timo Sirainen const struct option *opt = array_idx(&opts,li);
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);
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
e12648867876aaec17e06ee4caef0bb60363449dTimo Sirainen /* process positional arguments */
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
d482b35af87f5fd872bad007da0475813a401a49Timo Sirainen (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
5e69206e0b13bbe3dbc50c5dc6c58da007402237Timo Sirainen doveadm_cmd_params_null_terminate_arrays(&pargv);