doveadm-cmd.c revision b0d00847d0e1ab20662efce5b24f8fee6897c6fe
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny/* Copyright (c) 2009-2r016 Dovecot authors, see the included COPYING file */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenystatic struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1Sumit Bosestatic const struct exit_code_str {
c03214d427ea43e7bf8255ccc79faa905c89f7f6Jakub Hrozek const char *str;
f26c954658dfd7461f290f0b5d924951a6db219aJan ZelenyARRAY_DEFINE_TYPE(getopt_option_array, struct option);
b56b06e199f15a8a840b36bc7cb8010e39ae761dSumit Bose for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
b9fbeb75e7a4f50f98d979a70a710f9221892483Lukas Slebodnik const struct exit_code_str *ptr = &exit_code_strings[i];
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny return "UNKNOWN";
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny for(size_t i = 0; i < N_ELEMENTS(exit_code_strings); i++) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const struct exit_code_str *ptr = &exit_code_strings[i];
4c08db0fb0dda3d27b1184248ca5c800d7ce23f0Michal Zidekvoid doveadm_register_cmd(const struct doveadm_cmd *cmd)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashovvoid doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov cmd->cmd = doveadm_cmd_ver2_to_cmd_wrapper;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenyconst struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name)
21d485184df986e1a123f70c689517386e51a5ceMichal Zidekdoveadm_cmd_find_with_args_ver2(const char *cmd_name, int *argc,
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek const char *const *argv[])
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek const char *cptr;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidek for(i=0;i<*argc;i++) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* cannot reuse i here because this needs be
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek done more than once */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov for (k=0; *cptr != '\0' && i+k < *argc; k++) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* make sure we don't overstep */
bfd59d1a2d0d45125e5164ef12c425690d519f61Jakub Hrozek /* did not match */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (strncmp(cptr, (*argv)[i+k], alen) != 0) break;
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher /* do not accept abbreviations */
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose if (cptr[alen] != ' ' && cptr[alen] != '\0') break;
75dd4b05e1dacc76dc9d5f16be31978f84a71dc5Sumit Bose /* name was fully consumed */
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagherdoveadm_cmd_find_multi_word(const char *cmdname, int *_argc,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov const char *const *_argv[])
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* more args */
c20a339d54b39120b4051f690ca759e6d079f177Stephen Gallagher if (!doveadm_cmd_find_multi_word(cmdname + len + 1,
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagherdoveadm_cmd_find_with_args(const char *cmd_name, int *argc,
58d02e0d3d6d48c97fccdb2ad7212e065671ad6dStephen Gallagher const char *const *argv[])
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov /* see if it matches a multi-word command */
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *subcmd_name = cmd->name + cmd_name_len + 1;
56e88cd5f3501566778b138e4934ee8e7f3fa674Lukas Slebodnik unsigned int i;
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
108db0e3b9e06e530364ef8228634f5e3f6bd3b5Jakub Hrozek doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenystatic const struct doveadm_cmd_param*
21d485184df986e1a123f70c689517386e51a5ceMichal Zidekdoveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *name)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (strcmp(cctx->argv[i].name, name) == 0 && cctx->argv[i].value_set)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenybool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
21d485184df986e1a123f70c689517386e51a5ceMichal Zidekbool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
e30d02c04efad31f97c35165a92105852c805d34Jakub Hrozek if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
6199bd6b41e8b280e65db4b4bb17a1c5c0444aa9Stephen Gallagherbool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenybool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny memcpy(value_r, ¶m->value.v_ip, sizeof(struct ip_addr));
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenybool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny *value_r = array_get(¶m->value.v_array, &count);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* doveadm_cmd_params_null_terminate_arrays() should have been
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny called, which guarantees that we're NULL-terminated */
64175969779e51c00a78397746d4fec7ce7033a4Jakub Hrozekbool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
c4eb21582937362e09aa34e6a18b7f33815d4940Jakub Hrozek if ((param = doveadm_cmd_param_get(cctx, name))==NULL) return FALSE;
88ab259f993956b6cd0b1a07d3d88d105e368a8cJakub Hrozekvoid doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashovvoid doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny array_delete(¶m->value.v_array, array_count(¶m->value.v_array)-1, 1);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenydoveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
88ab259f993956b6cd0b1a07d3d88d105e368a8cJakub Hrozek const char * const * cptr;
88ab259f993956b6cd0b1a07d3d88d105e368a8cJakub Hrozek for(i=0;i<pargc;i++) {
88ab259f993956b6cd0b1a07d3d88d105e368a8cJakub Hrozek if ((params[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0)
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* istreams are special */
2ce00e0d3896bb42db169d1e79553a81ca837a22Simo Sorce optarg = t_strdup_printf("-%c", params[i].short_opt);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* CMD_PARAM_BOOL is implicitly handled above */
9fcfe80902655f495b7258218fc8114aa5d2c023Stephen Gallagher array_append(target, ¶ms[i].value.v_string,1);
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher } else if (params[i].type == CMD_PARAM_INT64) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char *tmp = net_ip2addr(¶ms[i].value.v_ip);
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher } else if (params[i].type == CMD_PARAM_ARRAY) {
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher array_foreach(¶ms[i].value.v_array, cptr) {
c4eb21582937362e09aa34e6a18b7f33815d4940Jakub Hrozekdoveadm_cmd_ver2_to_cmd_wrapper(struct doveadm_cmd_context *cctx)
7ba70236daccb48432350147d0560b3302518ceeMichal Zidek unsigned int pargc;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny const char **pargv;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny doveadm_cmd_params_to_argv(cctx->cmd->name, cctx->argc, cctx->argv, &nargv);
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagherdoveadm_build_options(const struct doveadm_cmd_param par[],
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher ARRAY_TYPE(getopt_option_array) *longopts)
169fa5bd3edd34aa0db35681832bd7406e423c1bStephen Gallagher for(size_t i=0; par[i].name != NULL; i++) {
6b81b6ada1010e65b447fc74453e236fb8791813Jan Zelenystatic void doveadm_fill_param(struct doveadm_cmd_param *param,
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if (str_to_int64(value, ¶m->value.v_int64) != 0) {
c4eb21582937362e09aa34e6a18b7f33815d4940Jakub Hrozek if (net_addr2ip(value, ¶m->value.v_ip) != 0) {
7ba70236daccb48432350147d0560b3302518ceeMichal Zidek is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
3e39806177e1cd383743ff596cb96df44a6ce8c9Jakub Hrozek is = i_stream_create_file(value, IO_BLOCK_SIZE);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zelenybool doveadm_cmd_try_run_ver2(const char *cmd_name,
3e39806177e1cd383743ff596cb96df44a6ce8c9Jakub Hrozek cmd = doveadm_cmd_find_with_args_ver2(cmd_name, &argc, &argv);
3e39806177e1cd383743ff596cb96df44a6ce8c9Jakub Hrozek if (doveadm_cmd_run_ver2(argc, argv, cctx) < 0)
3e39806177e1cd383743ff596cb96df44a6ce8c9Jakub Hrozekint doveadm_cmd_run_ver2(int argc, const char *const argv[],
169fa5bd3edd34aa0db35681832bd7406e423c1bStephen Gallagher ARRAY_TYPE(doveadm_cmd_param_arr_t) pargv;
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher // build parameters
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher for(pargc=0;cctx->cmd->parameters[pargc].name != NULL;pargc++) {
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher memcpy(param, &(cctx->cmd->parameters[pargc]), sizeof(struct doveadm_cmd_param));
92ec40e6aa25f75903ffdb166a8ec56b67bfd77dPavel Březina i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher for(unsigned int i = 0; i < array_count(&pargv); i++) {
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher const struct option *opt = array_idx(&opts,li);
2f3ee3f49019f5b60adbe073070f31e6e2d7c7abStephen Gallagher // hunt the option
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny for(unsigned int i = 0; i < pargc; i++) {
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher const struct option *longopt = array_idx(&opts,i);
38e1ee5d65ade946f1322efa96f69c05e041c57fStephen Gallagher doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny /* process positional arguments */
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny doveadm_cmd_params_null_terminate_arrays(&pargv);