aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi/* Copyright (c) 2009-2r016 Dovecot authors, see the included COPYING file */
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenstatic struct doveadm_cmd *doveadm_commands[] = {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki TuomiARRAY_DEFINE_TYPE(getopt_option_array, struct option);
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 return "UNKNOWN";
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];
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainenvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomivoid doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
7a8ef11587fd50d5888223fc3d91911775a21ba5Aki Tuomiconst struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name)
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainendoveadm_cmd_find_with_args_ver2(const char *cmd_name, int *argc,
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen const char *const *argv[])
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen for(i=0;i<*argc;i++) {
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++) {
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* make sure we don't overstep */
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 /* name was fully consumed */
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainendoveadm_cmd_find_multi_word(const char *cmdname, int *_argc,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const *_argv[])
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen /* more args */
3b759465ad5088a8d491b49c9ebb0dc9d3f66f7eTimo Sirainen if (!doveadm_cmd_find_multi_word(cmdname + len + 1,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainendoveadm_cmd_find_with_args(const char *cmd_name, int *argc,
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainen const char *const *argv[])
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen /* see if it matches a multi-word command */
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen const char *subcmd_name = cmd->name + cmd_name_len + 1;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen unsigned int i;
55accf49e32ff93bfdd92961cb54ccc8c329147cTimo Sirainen for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainenstatic const struct doveadm_cmd_param*
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomidoveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
db8b229230860a6c12daa0017a49396986368897Aki Tuomi const char *name)
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if (strcmp(cctx->argv[i].name, name) == 0 && cctx->argv[i].value_set)
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
db8b229230860a6c12daa0017a49396986368897Aki Tuomi memcpy(value_r, ¶m->value.v_ip, sizeof(struct ip_addr));
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
4afc67eb96f8d6b7dc94d63d3c7fe4f556c4fceeTimo Sirainen const char *name, const char *const **value_r)
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen *value_r = array_get(¶m->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 */
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomibool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
1e8a6a8708b612eee65f83ef6874aab94b15eb50Timo Sirainenvoid doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
c5e46dba179864f6f1adf196d46e7a0371b11914Josef 'Jeff' Sipek i_stream_destroy(¶m->value.v_istream);
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainenvoid doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen array_delete(¶m->value.v_array, array_count(¶m->value.v_array)-1, 1);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomidoveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi for(i=0;i<pargc;i++) {
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi if ((params[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0)
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi /* istreams are special */
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi optarg = t_strdup_printf("-%c", params[i].short_opt);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi /* CMD_PARAM_BOOL is implicitly handled above */
98800cb9f53b7cc7b5dbfc78f2803707b9b0d324Aki Tuomi array_append(target, ¶ms[i].value.v_string,1);
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi const char *tmp = net_ip2addr(¶ms[i].value.v_ip);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomidoveadm_cmd_ver2_to_cmd_wrapper(struct doveadm_cmd_context *cctx)
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi doveadm_cmd_params_to_argv(cctx->cmd->name, cctx->argc, cctx->argv, &nargv);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomidoveadm_build_options(const struct doveadm_cmd_param par[],
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomistatic void doveadm_fill_param(struct doveadm_cmd_param *param,
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if (str_to_int64(value, ¶m->value.v_int64) != 0) {
79ec87ea6861e2dd447f69ab44a7cc4e4fce3fddAki Tuomi if (net_addr2ip(value, ¶m->value.v_ip) != 0) {
3d27e1102558215203b73c58a2cba84dccf0dd1aTimo Sirainen param->value.v_string = p_strdup(pool, value);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
79bbb900ffba886779474dfb04c41408f0ba0602Timo Sirainenbool doveadm_cmd_try_run_ver2(const char *cmd_name,
6a8c95b0693c93601e948e06bfe1f89abdd43307Timo Sirainen cmd = doveadm_cmd_find_with_args_ver2(cmd_name, &argc, &argv);
36a052b7bd94ccb47abbb6b15c1380f03780ba20Timo Sirainenint doveadm_cmd_run_ver2(int argc, const char *const argv[],
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi // build parameters
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi for(pargc=0;cctx->cmd->parameters[pargc].name != NULL;pargc++) {
c5e46dba179864f6f1adf196d46e7a0371b11914Josef 'Jeff' Sipek memcpy(param, &cctx->cmd->parameters[pargc], sizeof(struct doveadm_cmd_param));
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
aaa1b6bb4cd2d7f8f4e7977d61176ea1c8f7e32bAki Tuomi while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
0746d8c498e2bb336399c37715d4fef9d64560c7Aki Tuomi for(unsigned int i = 0; i < array_count(&pargv); i++) {
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 doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi /* process positional arguments */
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
14af7be4aa26d55c341cd6efe32bb2add2c39830Aki Tuomi (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
2029c2cb37d7308e74329c9a15b6cf07a3468314Timo Sirainen doveadm_cmd_params_null_terminate_arrays(&pargv);