]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Add infrastructure for doveadm_cmd_ver2
authorAki Tuomi <aki.tuomi@dovecot.fi>
Mon, 15 Feb 2016 12:02:19 +0000 (14:02 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 19 Feb 2016 13:31:41 +0000 (15:31 +0200)
Version 2 commands have named parameters, which also have types. This is
especially useful for reading input from HTTP/JSON API. This also simplifies
the parameter parsing for command line input.

For v2.3 the plan is to replace all the old doveadm_cmds with this new
version and get rid of the _ver2 suffixes. But for now we'll have two
versions of commands.

For backwards compatibility with old commands we have also implemented
wrappers so that v2 structs can be defined and there's a function to convert
the named parameters to old v1 style args[] string, so the old command
handlers can still be run. This will also be removed in v2.3.

This change also adds requirement for getopt_long(). It's already available
in all the Linuxes and BSDs, so this shouldn't be too big of a requirement.
Other systems can install it from an external library.

src/doveadm/doveadm-cmd.c
src/doveadm/doveadm-cmd.h
src/doveadm/doveadm-mail.c
src/doveadm/doveadm-mail.h
src/doveadm/doveadm.c
src/doveadm/doveadm.h

index 4ec56b8ace6076a3c1fe7e3abbaff4d8ccd0446b..11d05fbb5b0cd485762613c27f57d00293dd3c5b 100644 (file)
@@ -2,7 +2,14 @@
 
 #include "lib.h"
 #include "array.h"
+#include "istream.h"
+#include "str.h"
 #include "doveadm-cmd.h"
+#include "doveadm.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
 
 static struct doveadm_cmd *doveadm_commands[] = {
        &doveadm_cmd_stop,
@@ -16,13 +23,65 @@ static struct doveadm_cmd *doveadm_commands[] = {
        &doveadm_cmd_stats_dump
 };
 
+static struct doveadm_cmd_ver2 *doveadm_commands_ver2[] = {
+};
+
 ARRAY_TYPE(doveadm_cmd) doveadm_cmds;
+ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
+ARRAY_DEFINE_TYPE(getopt_option_array, struct option);
 
 void doveadm_register_cmd(const struct doveadm_cmd *cmd)
 {
        array_append(&doveadm_cmds, cmd, 1);
 }
 
+void doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
+{
+       if (cmd->cmd == NULL) {
+               if (cmd->mail_cmd != NULL)
+                       cmd->cmd = doveadm_cmd_ver2_to_mail_cmd_wrapper;
+               else if (cmd->old_cmd != NULL)
+                       cmd->cmd = doveadm_cmd_ver2_to_cmd_wrapper;
+               else i_unreached();
+       }
+       array_append(&doveadm_cmds_ver2, cmd, 1);
+}
+
+const struct doveadm_cmd_ver2* doveadm_cmd_find_ver2(const char *cmd_name,
+       int argc, const char *argv[])
+{
+       int i;
+       const struct doveadm_cmd_ver2 *cmd;
+       const char *cptr;
+
+       for(i=0;i<argc;i++) {
+               if (strcmp(argv[i],cmd_name)==0) break;
+       }
+
+       i_assert(i != argc);
+
+       array_foreach(&doveadm_cmds_ver2, cmd) {
+               cptr = cmd->name;
+               /* cannot reuse i here because this needs be
+                  done more than once */
+               for(int k=0; cptr != NULL && i+k < argc; k++) {
+                       size_t alen = strlen(argv[i+k]);
+                       /* make sure we don't overstep */
+                       if (strlen(cptr) < alen) break;
+                       /* did not match */
+                       if (strncmp(cptr, argv[i+k], alen) != 0) break;
+                       /* do not accept abbreviations */
+                       if (cptr[alen] != ' ' && cptr[alen] != '\0') break;
+                       cptr += alen;
+                       if (*cptr != '\0') cptr++; /* consume space */
+               }
+               /* name was fully consumed */
+               if (*cptr == '\0') return cmd;
+       }
+
+       return NULL;
+}
+
 static const struct doveadm_cmd *
 doveadm_cmd_find_multi_word(const struct doveadm_cmd *cmd,
                            const char *cmdname, int *_argc, char **_argv[])
@@ -88,9 +147,14 @@ void doveadm_cmds_init(void)
        unsigned int i;
 
        i_array_init(&doveadm_cmds, 32);
+       i_array_init(&doveadm_cmds_ver2, 2);
+
        for (i = 0; i < N_ELEMENTS(doveadm_commands); i++)
                doveadm_register_cmd(doveadm_commands[i]);
 
+       for (i = 0; i < N_ELEMENTS(doveadm_commands_ver2); i++)
+               doveadm_cmd_register_ver2(doveadm_commands_ver2[i]);
+
        doveadm_register_auth_commands();
        doveadm_register_director_commands();
        doveadm_register_instance_commands();
@@ -106,3 +170,287 @@ void doveadm_cmds_deinit(void)
 {
        array_free(&doveadm_cmds);
 }
+
+static const struct doveadm_cmd_param*
+doveadm_cmd_param_get(int argc, const struct doveadm_cmd_param* params, const char *name)
+{
+       i_assert(params != NULL);
+       for(int i = 0; i < argc; i++) {
+               if (strcmp(params[i].name, name) == 0 && params[i].value_set)
+                       return &(params[i]);
+       }
+       return NULL;
+}
+
+bool doveadm_cmd_param_bool(int argc, const struct doveadm_cmd_param* params, const char *name, bool* value)
+{
+       const struct doveadm_cmd_param* param;
+       if ((param = doveadm_cmd_param_get(argc, params, name))==NULL) return FALSE;
+
+       if (param->type == CMD_PARAM_NONE || param->type == CMD_PARAM_BOOL) {
+               *value = param->value.v_bool;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool doveadm_cmd_param_int64(int argc, const struct doveadm_cmd_param* params, const char *name, int64_t* value)
+{
+       const struct doveadm_cmd_param* param;
+       if ((param = doveadm_cmd_param_get(argc, params, name))==NULL) return FALSE;
+
+       if (param->type == CMD_PARAM_INT64) {
+               *value = param->value.v_int64;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool doveadm_cmd_param_str(int argc, const struct doveadm_cmd_param* params, const char *name, const char** value)
+{
+       const struct doveadm_cmd_param* param;
+       if ((param = doveadm_cmd_param_get(argc, params, name))==NULL) return FALSE;
+
+       if (param->type == CMD_PARAM_STR) {
+               *value = param->value.v_string;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool doveadm_cmd_param_array(int argc, struct doveadm_cmd_param* params, const char *name, ARRAY_TYPE(const_string)** value)
+{
+       const struct doveadm_cmd_param* param;
+       if ((param = doveadm_cmd_param_get(argc, params, name))==NULL) return FALSE;
+       if (param->type == CMD_PARAM_STR) {
+               *value = (ARRAY_TYPE(const_string)*)&(param->value.v_array);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool doveadm_cmd_param_istream(int argc, struct doveadm_cmd_param* params, const char *name, struct istream** value)
+{
+       const struct doveadm_cmd_param* param;
+       if ((param = doveadm_cmd_param_get(argc, params, name))==NULL) return FALSE;
+
+       if (param->type == CMD_PARAM_ISTREAM) {
+               *value = param->value.v_istream;
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static void
+doveadm_cmd_params_to_argv(const char *name, int pargc, const struct doveadm_cmd_param* params,
+       ARRAY_TYPE(const_string) *argv)
+{
+       int i;
+       const char * const * cptr;
+       i_assert(array_count(argv) == 0);
+       array_append(argv, &name, 1);
+       for(i=0;i<pargc;i++) {
+               if (params[i].value_set && params[i].opt != NULL &&
+                       *(params[i].opt) != ':' && *(params[i].opt) != '?') {
+                       const char *optarg = t_strdup_printf("-%c", params[i].opt[0]);
+                       if (params[i].type == CMD_PARAM_STR) {
+                               array_append(argv, &optarg, 1);
+                               array_append(argv, &params[i].value.v_string,1);
+                       } else if (params[i].type == CMD_PARAM_ARRAY) {
+                               array_foreach(&params[i].value.v_array, cptr) {
+                                       array_append(argv, &optarg, 1);
+                                       array_append(argv, cptr, 1);
+                               }
+                       }
+               } else if (params[i].value_set) {
+                       if (params[i].type == CMD_PARAM_ARRAY) {
+                               array_append_array(argv, &params[i].value.v_array);
+                       } else {
+                               array_append(argv, &params[i].value.v_string,1);
+                       }
+               }
+       }
+       array_append_zero(argv);
+}
+
+int
+doveadm_cmd_ver2_to_cmd_wrapper(const struct doveadm_cmd_ver2* cmd,
+       int argc, const struct doveadm_cmd_param* param)
+{
+       unsigned int pargc;
+       const char **pargv;
+
+       i_assert(cmd->old_cmd != NULL);
+
+       ARRAY_TYPE(const_string) nargv;
+       t_array_init(&nargv, 8);
+       doveadm_cmd_params_to_argv(cmd->name, argc, param, &nargv);
+       pargv = array_get_modifiable(&nargv, &pargc);
+       i_getopt_reset();
+       cmd->old_cmd(pargc-1, (char**)pargv);
+
+       return 0;
+}
+
+static void
+doveadm_build_options(const struct doveadm_cmd_param par[],
+               string_t *shortopts,
+               ARRAY_TYPE(getopt_option_array) *longopts)
+{
+       const char *optp;
+       for(size_t i=0; par[i].name != NULL; i++) {
+               struct option longopt;
+               if ((par[i].flags & CMD_PARAM_FLAG_DO_NOT_EXPOSE) != 0) continue;
+               longopt.name = par[i].name;
+               longopt.flag = 0;
+               longopt.val = 0;
+               if (par[i].opt) {
+                       optp = par[i].opt;
+                       if (*optp != ':' && *optp != '?') {
+                               longopt.val = *optp;
+                               str_append_c(shortopts, *optp);
+                               optp++;
+                               if (optp[0] != '\0')
+                                       str_append_c(shortopts, *optp);
+                       }
+                       switch(*optp) {
+                       case ':': longopt.has_arg = 1; break;
+                       case '?': longopt.has_arg = 2; break;
+                       default:
+                               longopt.has_arg = 0;
+                       }
+               } else {
+                       longopt.has_arg = 0;
+               }
+               array_append(longopts, &longopt, 1);
+       }
+       array_append_zero(longopts);
+}
+
+static void doveadm_fill_param(struct doveadm_cmd_param *param,
+       const char *value, pool_t pool)
+{
+       param->value_set = TRUE;
+       switch(param->type) {
+       case CMD_PARAM_NONE:
+       case CMD_PARAM_BOOL:
+               param->value.v_bool = TRUE; break;
+       case CMD_PARAM_INT64:
+               if (str_to_int64(value, &param->value.v_int64) != 0) {
+                       param->value_set = FALSE;
+               }
+               break;
+       case CMD_PARAM_STR:
+               if (value != NULL) {
+                       param->value.v_string = p_strdup(pool, value);
+               } else {
+                       param->value.v_string = NULL;
+               }
+               break;
+       case CMD_PARAM_ARRAY:
+               if (!array_is_created(&param->value.v_array))
+                       p_array_init(&param->value.v_array, pool, 8);
+               const char *val = p_strdup(pool, value);
+               array_append(&param->value.v_array, &val, 1);
+               break;
+       case CMD_PARAM_ISTREAM: {
+               struct istream *is;
+               if (strcmp(value,"-") == 0) {
+                       is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE, FALSE);
+               } else {
+                       is = i_stream_create_file(value, IO_BLOCK_SIZE);
+               }
+               param->value.v_istream = is;
+       }
+       }
+}
+
+bool doveadm_cmd_try_run_ver2(const char *cmd_name, int argc, const char *argv[])
+{
+       const struct doveadm_cmd_ver2 *cmd;
+
+       cmd = doveadm_cmd_find_ver2(cmd_name, argc, argv);
+       if (cmd == NULL)
+               return FALSE;
+
+       if (doveadm_cmd_run_ver2(cmd, argc, argv) < 0)
+               doveadm_exit_code = EX_USAGE;
+       return TRUE;
+}
+
+int doveadm_cmd_run_ver2(const struct doveadm_cmd_ver2 *cmd, int argc, const char *argv[])
+{
+       struct doveadm_cmd_param *param;
+       ARRAY(struct doveadm_cmd_param) pargv;
+       ARRAY_TYPE(getopt_option_array) opts;
+       const char *cptr;
+       unsigned int pargc;
+       int c,li;
+       pool_t pool = pool_datastack_create();
+       string_t *optbuf = str_new(pool, 64);
+
+       p_array_init(&opts, pool, 4);
+
+       // build parameters
+       doveadm_build_options(cmd->parameters, optbuf, &opts);
+
+       p_array_init(&pargv, pool, 20);
+
+       for(pargc=0;cmd->parameters[pargc].name != NULL;pargc++) {
+               param = array_append_space(&pargv);
+               memcpy(param, &(cmd->parameters[pargc]), sizeof(struct doveadm_cmd_param));
+               param->value_set = FALSE;
+       }
+       i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
+
+       while((c = getopt_long(argc, (char*const*)argv, str_c(optbuf), array_idx(&opts, 0), &li)) > -1) {
+               switch(c) {
+               case 0:
+                       doveadm_fill_param(array_idx_modifiable(&pargv,li), optarg, pool);
+                       break;
+               case '?':
+               case ':':
+                       return -1;
+               default:
+                       // hunt the option
+                       for(unsigned int i = 0; i < pargc; i++) {
+                               const struct option *longopt = array_idx(&opts,i);
+                               if (longopt->val == c)
+                                       doveadm_fill_param(array_idx_modifiable(&pargv,i), optarg, pool);
+                       }
+               }
+       }
+
+       cptr = cmd->name;
+       while((cptr = strchr(cptr+1, ' ')) != NULL) optind++;
+
+       /* process positional arguments */
+       for(;optind<argc;optind++) {
+               struct doveadm_cmd_param *ptr;
+               bool found = FALSE;
+               array_foreach_modifiable(&pargv, ptr) {
+                       if ((ptr->flags & CMD_PARAM_FLAG_POSITIONAL) != 0 &&
+                           (ptr->value_set == FALSE || ptr->type == CMD_PARAM_ARRAY)) {
+                               doveadm_fill_param(ptr, argv[optind], pool);
+                               found = TRUE;
+                               break;
+                       }
+               }
+               if (!found) {
+                       i_error("Extraneous arguments found");
+                       return -1;
+               }
+       }
+
+       param = array_get_modifiable(&pargv, &pargc);
+
+       // FIXME: Unsure what do to with return value
+       cmd->cmd(cmd, pargc, param);
+
+       // unref istreams
+       array_foreach_modifiable(&pargv, param) {
+               if (param->type == CMD_PARAM_ISTREAM && param->value.v_istream != NULL)
+                       i_stream_unref(&param->value.v_istream);
+       }
+       return 0;
+}
index 596313d48931390141e54533e9533fa913ed2b22..372873c81a53cb474eeefc961ea22c7e6b4e5d4a 100644 (file)
@@ -1,18 +1,71 @@
 #ifndef DOVEADM_CMD_H
 #define DOVEADM_CMD_H
 
+#define DOVEADM_CMD_PARAMS_START .parameters = (const struct doveadm_cmd_param[]){
+#define DOVEADM_CMD_PARAM(optP, nameP, typeP, flagP ) { .opt = optP, .name = nameP, .type = typeP, .flags = flagP },
+#define DOVEADM_CMD_PARAMS_END { .opt = NULL, .name = NULL, .type = CMD_PARAM_NONE, .flags = CMD_PARAM_FLAG_NONE } }
+
+struct doveadm_cmd_ver2;
+struct doveadm_mail_cmd_context;
+
 typedef void doveadm_command_t(int argc, char *argv[]);
 
+typedef enum {
+       CMD_PARAM_NONE,    /* same as below, used for empty */
+       CMD_PARAM_BOOL,    /* value will contain 1 (not pointer) */
+       CMD_PARAM_INT64,    /* ditto but contains number (not pointer) */
+       CMD_PARAM_STR,     /* value contains const char* */
+       CMD_PARAM_ARRAY,   /* value contains const char*[] */
+       CMD_PARAM_ISTREAM  /* value contains struct istream* */
+} doveadm_cmd_param_t;
+
+typedef enum {
+       CMD_PARAM_FLAG_NONE             = 0x0,
+       CMD_PARAM_FLAG_POSITIONAL       = 0x1,
+       CMD_PARAM_FLAG_DO_NOT_EXPOSE    = 0x2,
+} doveadm_cmd_param_flag_t;
+
+struct doveadm_cmd_param {
+       const char *opt;
+       const char *name;
+       doveadm_cmd_param_t type;
+       bool value_set;
+       struct {
+               bool v_bool;
+               int64_t v_int64;
+               const char* v_string;
+               ARRAY_TYPE(const_string) v_array;
+               struct istream* v_istream;
+       } value;
+       doveadm_cmd_param_flag_t flags;
+};
+
+typedef int doveadm_command_ver2_t(const struct doveadm_cmd_ver2* cmd,
+       int argc, const struct doveadm_cmd_param[]);
+
 struct doveadm_cmd {
        doveadm_command_t *cmd;
        const char *name;
        const char *short_usage;
 };
+
+struct doveadm_cmd_ver2 {
+       doveadm_command_ver2_t *cmd;
+       doveadm_command_t *old_cmd;
+       struct doveadm_mail_cmd_context *(*mail_cmd)(void);
+       const char *name;
+       const char *usage;
+       const struct doveadm_cmd_param *parameters;
+};
+
 ARRAY_DEFINE_TYPE(doveadm_cmd, struct doveadm_cmd);
 extern ARRAY_TYPE(doveadm_cmd) doveadm_cmds;
 
 extern struct doveadm_cmd doveadm_cmd_stop;
 extern struct doveadm_cmd doveadm_cmd_reload;
+ARRAY_DEFINE_TYPE(doveadm_cmd_ver2, struct doveadm_cmd_ver2);
+extern ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
+
 extern struct doveadm_cmd doveadm_cmd_dump;
 extern struct doveadm_cmd doveadm_cmd_pw;
 extern struct doveadm_cmd doveadm_cmd_who;
@@ -44,4 +97,25 @@ void doveadm_register_fs_commands(void);
 void doveadm_cmds_init(void);
 void doveadm_cmds_deinit(void);
 
+int doveadm_cmd_ver2_to_cmd_wrapper(const struct doveadm_cmd_ver2* cmd,
+       int argc, const struct doveadm_cmd_param[]);
+int doveadm_cmd_ver2_to_mail_cmd_wrapper(const struct doveadm_cmd_ver2* cmd,
+       int argc, const struct doveadm_cmd_param argv[]);
+
+void doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd);
+const struct doveadm_cmd_ver2 *doveadm_cmd_find_ver2(const char *cmd_name,
+       int argc, const char *argv[]);
+/* Returns FALSE if cmd_name doesn't exist, TRUE if it exists. */
+bool doveadm_cmd_try_run_ver2(const char *cmd_name, int argc,
+       const char *argv[]);
+/* Returns 0 if success, -1 if parameters were invalid. */
+int doveadm_cmd_run_ver2(const struct doveadm_cmd_ver2 *cmd,
+       int argc, const char *argv[]);
+
+bool doveadm_cmd_param_bool(int argc, const struct doveadm_cmd_param* params, const char *name, bool* value);
+bool doveadm_cmd_param_int64(int argc, const struct doveadm_cmd_param* params, const char *name, int64_t* value);
+bool doveadm_cmd_param_str(int argc, const struct doveadm_cmd_param* params, const char *name, const char** value);
+bool doveadm_cmd_param_array(int argc, struct doveadm_cmd_param* params, const char *name, ARRAY_TYPE(const_string)** value);
+bool doveadm_cmd_param_istream(int argc, struct doveadm_cmd_param* params, const char *name, struct istream** value);
+
 #endif
index 4b98e876c7d601282813f78cd32821fd77049eaf..dac6c034de78112636bf15145df3db67f9127f10 100644 (file)
@@ -534,6 +534,19 @@ doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd,
        return ctx;
 }
 
+static struct doveadm_mail_cmd_context *
+doveadm_mail_cmdline_init(const struct doveadm_mail_cmd *cmd)
+{
+       struct doveadm_mail_cmd_context *ctx;
+
+       ctx = doveadm_mail_cmd_init(cmd, doveadm_settings);
+       ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
+       if (doveadm_debug)
+               ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
+       ctx->cur_username = getenv("USER");
+       return ctx;
+}
+
 static void
 doveadm_mail_cmd_exec(struct doveadm_mail_cmd_context *ctx,
                      const char *wildcard_user)
@@ -599,20 +612,15 @@ doveadm_mail_cmd(const struct doveadm_mail_cmd *cmd, int argc, char *argv[])
        const char *getopt_args, *wildcard_user;
        int c;
 
-       ctx = doveadm_mail_cmd_init(cmd, doveadm_settings);
+       ctx = doveadm_mail_cmdline_init(cmd);
        ctx->full_args = (const void *)(argv + 1);
 
-       ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
-       if (doveadm_debug)
-               ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_DEBUG;
-
        getopt_args = "AF:S:u:";
        /* keep context's getopt_args first in case it contains '+' */
        if (ctx->getopt_args != NULL)
                getopt_args = t_strconcat(ctx->getopt_args, getopt_args, NULL);
        i_assert(master_getopt_str_is_valid(getopt_args));
 
-       ctx->cur_username = getenv("USER");
        wildcard_user = NULL;
        while ((c = getopt(argc, argv, getopt_args)) > 0) {
                switch (c) {
@@ -836,6 +844,9 @@ static struct doveadm_mail_cmd *mail_commands[] = {
        &cmd_dsync_server
 };
 
+static struct doveadm_cmd_ver2 *mail_commands_ver2[] = {
+};
+
 void doveadm_mail_init(void)
 {
        struct module_dir_load_settings mod_set;
@@ -845,6 +856,9 @@ void doveadm_mail_init(void)
        for (i = 0; i < N_ELEMENTS(mail_commands); i++)
                doveadm_mail_register_cmd(mail_commands[i]);
 
+       for (i = 0; i < N_ELEMENTS(mail_commands_ver2); i++)
+               doveadm_cmd_register_ver2(mail_commands_ver2[i]);
+
        memset(&mod_set, 0, sizeof(mod_set));
        mod_set.abi_version = DOVECOT_ABI_VERSION;
        mod_set.require_init_funcs = TRUE;
@@ -864,3 +878,68 @@ void doveadm_mail_deinit(void)
        mail_storage_hooks_deinit();
        array_free(&doveadm_mail_cmds);
 }
+
+int
+doveadm_cmd_ver2_to_mail_cmd_wrapper(const struct doveadm_cmd_ver2* cmd,
+       int argc, const struct doveadm_cmd_param argv[])
+{
+       struct doveadm_mail_cmd_context *ctx;
+       const char *wildcard_user;
+       ARRAY_TYPE(const_string) pargv;
+       int i;
+       struct doveadm_mail_cmd mail_cmd = {
+               .alloc = cmd->mail_cmd
+       };
+
+       ctx = doveadm_mail_cmdline_init(&mail_cmd);
+
+       ctx->iterate_all_users = FALSE;
+       wildcard_user = NULL;
+       t_array_init(&pargv, 8);
+
+       for(i=0;i<argc;i++) {
+               if (!argv[i].value_set)
+                       continue;
+
+               if (strcmp(argv[i].name, "all_users") == 0) {
+                       ctx->iterate_all_users = argv[i].value.v_bool;
+               } else if (strcmp(argv[i].name, "socket_path") == 0) {
+                       doveadm_settings->doveadm_socket_path = argv[i].value.v_string;
+                       if (doveadm_settings->doveadm_worker_count == 0)
+                               doveadm_settings->doveadm_worker_count = 1;
+               } else if (strcmp(argv[i].name, "user") == 0) {
+                       ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+                       ctx->cur_username = argv[i].value.v_string;
+                       if (strchr(ctx->cur_username, '*') != NULL ||
+                           strchr(ctx->cur_username, '?') != NULL) {
+                               wildcard_user = ctx->cur_username;
+                               ctx->cur_username = NULL;
+                       }
+               } else if (strcmp(argv[i].name, "user_list") == 0) {
+                       ctx->service_flags |= MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+                       wildcard_user = "*";
+                       ctx->users_list_input = argv[i].value.v_istream;
+               } else if (ctx->v.parse_arg != NULL && argv[i].opt != NULL &&
+                          *(argv[i]).opt != '?' && *(argv[i]).opt != ':') {
+                       optarg = (char*)argv[i].value.v_string;
+                       ctx->v.parse_arg(ctx, *(argv[i].opt));
+               } else if ((argv[i].flags & CMD_PARAM_FLAG_POSITIONAL) != 0) {
+                       /* feed this into pargv */
+                       if (argv[i].type == CMD_PARAM_ARRAY)
+                               array_append_array(&pargv, &argv[i].value.v_array);
+                       else if (argv[i].type == CMD_PARAM_STR)
+                               array_append(&pargv, &argv[i].value.v_string, 1);
+               } else {
+                       doveadm_exit_code = EX_USAGE;
+                       i_error("invalid parameter: %s", argv[i].name);
+                       return -1;
+               }
+       }
+
+       array_append_zero(&pargv);
+       ctx->args = array_idx(&pargv, 0);
+       ctx->full_args = ctx->args;
+
+       doveadm_mail_cmd_exec(ctx, wildcard_user);
+       return 0;
+}
index 63cbba9f3d65228be34138512b7063d868308090..969a8bc74b0acdb4ed89a360869f0dfdea82f7c5 100644 (file)
@@ -195,4 +195,10 @@ extern struct doveadm_mail_cmd cmd_mailbox_metadata_get;
 extern struct doveadm_mail_cmd cmd_mailbox_metadata_list;
 extern struct doveadm_mail_cmd cmd_batch;
 
+#define DOVEADM_CMD_MAIL_COMMON \
+DOVEADM_CMD_PARAM("A", "all-users", CMD_PARAM_BOOL, 0) \
+DOVEADM_CMD_PARAM("S:", "socket-path", CMD_PARAM_STR, 0) \
+DOVEADM_CMD_PARAM("u:", "user", CMD_PARAM_STR, 0) \
+DOVEADM_CMD_PARAM("F:", "user-file", CMD_PARAM_ISTREAM, 0)
+
 #endif
index 67a595be67af90d3617cd1a24f069c4a912e3fdd..0b7d991a59775deb97ceb56ecf7a7e698e8452c6 100644 (file)
@@ -144,6 +144,18 @@ void help(const struct doveadm_cmd *cmd)
        help_to(cmd, stdout);
 }
 
+static void ATTR_NORETURN
+help_to_ver2(const struct doveadm_cmd_ver2 *cmd, FILE *out)
+{
+       fprintf(out, "doveadm %s %s\n", cmd->name, cmd->usage);
+       exit(EX_USAGE);
+}
+
+void help_ver2(const struct doveadm_cmd_ver2 *cmd)
+{
+       help_to_ver2(cmd, stdout);
+}
+
 static void cmd_help(int argc ATTR_UNUSED, char *argv[])
 {
        const char *man_argv[3];
@@ -341,7 +353,8 @@ int main(int argc, char *argv[])
                i_set_debug_file("/dev/null");
        }
 
-       if (!doveadm_try_run(cmd_name, argc, argv) &&
+       if (!doveadm_cmd_try_run_ver2(cmd_name, argc, (const char**)argv) &&
+           !doveadm_try_run(cmd_name, argc, argv) &&
            !doveadm_mail_try_run(cmd_name, argc, argv)) {
                if (doveadm_has_subcommands(cmd_name))
                        usage_to(stdout, cmd_name);
index 6bfd34fea40daff9f6c85868e472171e117cc534..12e6315305909e0eabeccd47cb6179676e907d79 100644 (file)
@@ -15,6 +15,7 @@ extern int doveadm_exit_code;
 
 void usage(void) ATTR_NORETURN;
 void help(const struct doveadm_cmd *cmd) ATTR_NORETURN;
+void help_ver2(const struct doveadm_cmd_ver2 *cmd) ATTR_NORETURN;
 void doveadm_master_send_signal(int signo);
 
 #endif