$(doveadm_common_mail_cmds) \
$(doveadm_common_dump_cmds) \
doveadm-cmd.c \
+ doveadm-cmd-parse.c \
doveadm-print.c \
doveadm-settings.c \
doveadm-util.c \
pkginc_lib_HEADERS = \
doveadm.h \
doveadm-cmd.h \
+ doveadm-cmd-parse.h \
doveadm-dsync.h \
doveadm-dump.h \
doveadm-mail.h \
--- /dev/null
+/* Copyright (c) 2009-2016 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "istream.h"
+#include "str.h"
+#include "net.h"
+#include "doveadm.h"
+#include "doveadm-cmd-parse.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+
+ARRAY_DEFINE_TYPE(getopt_option_array, struct option);
+
+static const struct doveadm_cmd_param *
+doveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
+ const char *name)
+{
+ i_assert(cctx != NULL);
+ i_assert(cctx->argv != NULL);
+ for(int i = 0; i < cctx->argc; i++) {
+ if (strcmp(cctx->argv[i].name, name) == 0 &&
+ cctx->argv[i].value_set)
+ return &cctx->argv[i];
+ }
+ return NULL;
+}
+
+bool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
+ const char *name, bool *value_r)
+{
+ const struct doveadm_cmd_param *param;
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+
+ if (param->type == CMD_PARAM_BOOL) {
+ *value_r = param->value.v_bool;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
+ const char *name, int64_t *value_r)
+{
+ const struct doveadm_cmd_param *param;
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+
+ if (param->type == CMD_PARAM_INT64) {
+ *value_r = param->value.v_int64;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
+ const char *name, const char **value_r)
+{
+ const struct doveadm_cmd_param *param;
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+
+ if (param->type == CMD_PARAM_STR) {
+ *value_r = param->value.v_string;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
+ const char *name, struct ip_addr *value_r)
+{
+ const struct doveadm_cmd_param *param;
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+
+ if (param->type == CMD_PARAM_IP) {
+ memcpy(value_r, ¶m->value.v_ip, sizeof(struct ip_addr));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
+ const char *name, const char *const **value_r)
+{
+ const struct doveadm_cmd_param *param;
+ unsigned int count;
+
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+ if (param->type == CMD_PARAM_ARRAY) {
+ *value_r = array_get(¶m->value.v_array, &count);
+ /* doveadm_cmd_params_null_terminate_arrays() should have been
+ called, which guarantees that we're NULL-terminated */
+ i_assert((*value_r)[count] == NULL);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
+ const char *name, struct istream **value_r)
+{
+ const struct doveadm_cmd_param *param;
+ if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
+ return FALSE;
+
+ if (param->type == CMD_PARAM_ISTREAM) {
+ *value_r = param->value.v_istream;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
+{
+ struct doveadm_cmd_param *param;
+
+ array_foreach_modifiable(pargv, param) {
+ if (param->type == CMD_PARAM_ISTREAM &&
+ param->value.v_istream != NULL)
+ i_stream_destroy(¶m->value.v_istream);
+ }
+ array_clear(pargv);
+}
+
+void doveadm_cmd_params_null_terminate_arrays(
+ ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
+{
+ struct doveadm_cmd_param *param;
+
+ array_foreach_modifiable(pargv, param) {
+ if (param->type == CMD_PARAM_ARRAY &&
+ array_is_created(¶m->value.v_array)) {
+ array_append_zero(¶m->value.v_array);
+ array_pop_back(¶m->value.v_array);
+ }
+ }
+}
+
+static void
+doveadm_build_options(const struct doveadm_cmd_param par[],
+ string_t *shortopts,
+ ARRAY_TYPE(getopt_option_array) *longopts)
+{
+ for (size_t i = 0; par[i].name != NULL; i++) {
+ struct option longopt;
+
+ i_zero(&longopt);
+ longopt.name = par[i].name;
+ if (par[i].short_opt != '\0') {
+ longopt.val = par[i].short_opt;
+ str_append_c(shortopts, par[i].short_opt);
+ if (par[i].type != CMD_PARAM_BOOL)
+ str_append_c(shortopts, ':');
+ }
+ if (par[i].type != CMD_PARAM_BOOL)
+ longopt.has_arg = 1;
+ array_push_back(longopts, &longopt);
+ }
+ 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_BOOL:
+ param->value.v_bool = TRUE;
+ break;
+ case CMD_PARAM_INT64:
+ if (str_to_int64(value, ¶m->value.v_int64) != 0)
+ param->value_set = FALSE;
+ break;
+ case CMD_PARAM_IP:
+ if (net_addr2ip(value, ¶m->value.v_ip) != 0)
+ param->value_set = FALSE;
+ break;
+ case CMD_PARAM_STR:
+ param->value.v_string = p_strdup(pool, value);
+ break;
+ case CMD_PARAM_ARRAY:
+ if (!array_is_created(¶m->value.v_array))
+ p_array_init(¶m->value.v_array, pool, 8);
+ const char *val = p_strdup(pool, value);
+ array_push_back(¶m->value.v_array, &val);
+ break;
+ case CMD_PARAM_ISTREAM: {
+ struct istream *is;
+ if (strcmp(value,"-") == 0)
+ is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
+ else
+ is = i_stream_create_file(value, IO_BLOCK_SIZE);
+ param->value.v_istream = is;
+ break;
+ }
+ }
+}
+
+static int
+doveadm_cmd_process_options(int argc, const char *const argv[],
+ struct doveadm_cmd_context *cctx, pool_t pool,
+ ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
+{
+ struct doveadm_cmd_param *param;
+ ARRAY_TYPE(getopt_option_array) opts;
+ string_t *optbuf = str_new(pool, 64);
+
+ p_array_init(&opts, pool, 4);
+
+ // build parameters
+ if ((cctx->cmd->flags & CMD_FLAG_NO_UNORDERED_OPTIONS) != 0)
+ str_append_c(optbuf, '+');
+ doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
+
+ unsigned int pargc;
+ for (pargc = 0; cctx->cmd->parameters[pargc].name != NULL; pargc++) {
+ param = array_append_space(pargv);
+ memcpy(param, &cctx->cmd->parameters[pargc],
+ sizeof(struct doveadm_cmd_param));
+ param->value_set = FALSE;
+ }
+ i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
+
+ if ((cctx->cmd->flags & CMD_FLAG_NO_OPTIONS) != 0) {
+ /* process -parameters as if they were regular parameters */
+ optind = 1;
+ return 0;
+ }
+
+ int c, li;
+ while ((c = getopt_long(argc, (char *const *)argv, str_c(optbuf),
+ array_front(&opts), &li)) > -1) {
+ switch (c) {
+ case 0:
+ for (unsigned int i = 0; i < array_count(pargv); i++) {
+ const struct option *opt = array_idx(&opts, li);
+ param = array_idx_modifiable(pargv, i);
+ if (opt->name == param->name)
+ doveadm_fill_param(param, optarg, pool);
+ }
+ break;
+ case '?':
+ case ':':
+ doveadm_cmd_params_clean(pargv);
+ 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);
+ }
+ }
+ }
+ return 0;
+}
+
+int doveadm_cmdline_run(int argc, const char *const argv[],
+ struct doveadm_cmd_context *cctx)
+{
+ ARRAY_TYPE(doveadm_cmd_param_arr_t) pargv;
+ unsigned int pargc;
+ pool_t pool = pool_datastack_create();
+
+ p_array_init(&pargv, pool, 20);
+ if (doveadm_cmd_process_options(argc, argv, cctx, pool, &pargv) < 0)
+ return -1;
+
+ /* 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: %s",
+ t_strarray_join(argv + optind, " "));
+ doveadm_cmd_params_clean(&pargv);
+ return -1;
+ }
+ }
+
+ doveadm_cmd_params_null_terminate_arrays(&pargv);
+ cctx->argv = array_get_modifiable(&pargv, &pargc);
+ cctx->argc = pargc;
+
+ cctx->cmd->cmd(cctx);
+
+ doveadm_cmd_params_clean(&pargv);
+ return 0;
+}
--- /dev/null
+#ifndef DOVEADM_CMD_PARSE_H
+#define DOVEADM_CMD_PARSE_H
+
+#include "net.h"
+
+#define DOVEADM_CMD_PARAMS_START .parameters = (const struct doveadm_cmd_param[]){
+#define DOVEADM_CMD_PARAM(optP, nameP, typeP, flagP ) { .short_opt = optP, .name = nameP, .type = typeP, .flags = flagP },
+#define DOVEADM_CMD_PARAMS_END { .short_opt = '\0', .name = NULL, .type = CMD_PARAM_BOOL, .flags = CMD_PARAM_FLAG_NONE } }
+
+struct doveadm_cmd_context;
+struct doveadm_mail_cmd_context;
+
+typedef enum {
+ CMD_PARAM_BOOL = 0, /* value in v_bool */
+ CMD_PARAM_INT64, /* value in v_int64 */
+ CMD_PARAM_IP, /* value in v_ip (struct ip_addr) */
+ CMD_PARAM_STR, /* value in v_string (const char*) */
+ CMD_PARAM_ARRAY, /* value in v_array (const char*[]) */
+ CMD_PARAM_ISTREAM /* value in v_istream (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;
+
+typedef enum {
+ CMD_FLAG_NONE = 0x0,
+ CMD_FLAG_HIDDEN = 0x1,
+ CMD_FLAG_NO_PRINT = 0x2,
+ /* Don't parse any -options for the command. */
+ CMD_FLAG_NO_OPTIONS = 0x4,
+ /* Prevent GNU getopt() from finding options after the first
+ non-option is seen (e.g. "-1 arg -2" would parse -1 but not -2
+ as option). */
+ CMD_FLAG_NO_UNORDERED_OPTIONS = 0x8,
+} doveadm_cmd_flag_t;
+
+struct doveadm_cmd_param {
+ char short_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 ip_addr v_ip;
+ struct istream* v_istream;
+ } value;
+ doveadm_cmd_param_flag_t flags;
+};
+ARRAY_DEFINE_TYPE(doveadm_cmd_param_arr_t, struct doveadm_cmd_param);
+
+typedef void doveadm_command_ver2_t(struct doveadm_cmd_context *cctx);
+
+struct doveadm_cmd_ver2 {
+ doveadm_command_ver2_t *cmd;
+ struct doveadm_mail_cmd_context *(*mail_cmd)(void);
+ const char *name;
+ const char *usage;
+ doveadm_cmd_flag_t flags;
+ const struct doveadm_cmd_param *parameters;
+};
+
+struct doveadm_cmd_context {
+ const struct doveadm_cmd_ver2 *cmd; /* for help */
+
+ pool_t pool;
+ int argc;
+ const struct doveadm_cmd_param *argv;
+
+ const char *username;
+ struct ip_addr local_ip, remote_ip;
+ in_port_t local_port, remote_port;
+ /* extra fields (e.g. forward_*) sent via doveadm protocol */
+ const char *const *extra_fields;
+
+ enum doveadm_client_type conn_type;
+ struct istream *input;
+ struct ostream *output;
+
+ /* non-NULL if doveadm-server should return referral to another
+ server instead. */
+ const char *referral;
+ bool proxy_redirect_reauth;
+};
+
+/* Returns 0 if success, -1 if parameters were invalid. */
+int doveadm_cmdline_run(int argc, const char *const argv[],
+ struct doveadm_cmd_context *cctx);
+
+bool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
+ const char *name, bool *value_r);
+bool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
+ const char *name, int64_t *value_r);
+bool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
+ const char *name, const char **value_r);
+bool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
+ const char *name, struct ip_addr *value_r);
+bool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
+ const char *name, const char *const **value_r);
+bool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
+ const char *name, struct istream **value_r);
+
+void doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv);
+void doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv);
+
+#endif
};
ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
-ARRAY_DEFINE_TYPE(getopt_option_array, struct option);
void doveadm_cmd_register_ver2(struct doveadm_cmd_ver2 *cmd)
{
array_free(&doveadm_cmds_ver2);
}
-static const struct doveadm_cmd_param *
-doveadm_cmd_param_get(const struct doveadm_cmd_context *cctx,
- const char *name)
-{
- i_assert(cctx != NULL);
- i_assert(cctx->argv != NULL);
- for(int i = 0; i < cctx->argc; i++) {
- if (strcmp(cctx->argv[i].name, name) == 0 &&
- cctx->argv[i].value_set)
- return &cctx->argv[i];
- }
- return NULL;
-}
-
-bool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
- const char *name, bool *value_r)
-{
- const struct doveadm_cmd_param *param;
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
-
- if (param->type == CMD_PARAM_BOOL) {
- *value_r = param->value.v_bool;
- return TRUE;
- }
- return FALSE;
-}
-
-bool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
- const char *name, int64_t *value_r)
-{
- const struct doveadm_cmd_param *param;
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
-
- if (param->type == CMD_PARAM_INT64) {
- *value_r = param->value.v_int64;
- return TRUE;
- }
- return FALSE;
-}
-
-bool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
- const char *name, const char **value_r)
-{
- const struct doveadm_cmd_param *param;
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
-
- if (param->type == CMD_PARAM_STR) {
- *value_r = param->value.v_string;
- return TRUE;
- }
- return FALSE;
-}
-
-bool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
- const char *name, struct ip_addr *value_r)
-{
- const struct doveadm_cmd_param *param;
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
-
- if (param->type == CMD_PARAM_IP) {
- memcpy(value_r, ¶m->value.v_ip, sizeof(struct ip_addr));
- return TRUE;
- }
- return FALSE;
-}
-
-bool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
- const char *name, const char *const **value_r)
-{
- const struct doveadm_cmd_param *param;
- unsigned int count;
-
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
- if (param->type == CMD_PARAM_ARRAY) {
- *value_r = array_get(¶m->value.v_array, &count);
- /* doveadm_cmd_params_null_terminate_arrays() should have been
- called, which guarantees that we're NULL-terminated */
- i_assert((*value_r)[count] == NULL);
- return TRUE;
- }
- return FALSE;
-}
-
-bool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
- const char *name, struct istream **value_r)
-{
- const struct doveadm_cmd_param *param;
- if ((param = doveadm_cmd_param_get(cctx, name)) == NULL)
- return FALSE;
-
- if (param->type == CMD_PARAM_ISTREAM) {
- *value_r = param->value.v_istream;
- return TRUE;
- }
- return FALSE;
-}
-
-void doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
-{
- struct doveadm_cmd_param *param;
-
- array_foreach_modifiable(pargv, param) {
- if (param->type == CMD_PARAM_ISTREAM &&
- param->value.v_istream != NULL)
- i_stream_destroy(¶m->value.v_istream);
- }
- array_clear(pargv);
-}
-
-void doveadm_cmd_params_null_terminate_arrays(
- ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
-{
- struct doveadm_cmd_param *param;
-
- array_foreach_modifiable(pargv, param) {
- if (param->type == CMD_PARAM_ARRAY &&
- array_is_created(¶m->value.v_array)) {
- array_append_zero(¶m->value.v_array);
- array_pop_back(¶m->value.v_array);
- }
- }
-}
-
-static void
-doveadm_build_options(const struct doveadm_cmd_param par[],
- string_t *shortopts,
- ARRAY_TYPE(getopt_option_array) *longopts)
-{
- for (size_t i = 0; par[i].name != NULL; i++) {
- struct option longopt;
-
- i_zero(&longopt);
- longopt.name = par[i].name;
- if (par[i].short_opt != '\0') {
- longopt.val = par[i].short_opt;
- str_append_c(shortopts, par[i].short_opt);
- if (par[i].type != CMD_PARAM_BOOL)
- str_append_c(shortopts, ':');
- }
- if (par[i].type != CMD_PARAM_BOOL)
- longopt.has_arg = 1;
- array_push_back(longopts, &longopt);
- }
- 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_BOOL:
- param->value.v_bool = TRUE;
- break;
- case CMD_PARAM_INT64:
- if (str_to_int64(value, ¶m->value.v_int64) != 0)
- param->value_set = FALSE;
- break;
- case CMD_PARAM_IP:
- if (net_addr2ip(value, ¶m->value.v_ip) != 0)
- param->value_set = FALSE;
- break;
- case CMD_PARAM_STR:
- param->value.v_string = p_strdup(pool, value);
- break;
- case CMD_PARAM_ARRAY:
- if (!array_is_created(¶m->value.v_array))
- p_array_init(¶m->value.v_array, pool, 8);
- const char *val = p_strdup(pool, value);
- array_push_back(¶m->value.v_array, &val);
- break;
- case CMD_PARAM_ISTREAM: {
- struct istream *is;
- if (strcmp(value,"-") == 0)
- is = i_stream_create_fd(STDIN_FILENO, IO_BLOCK_SIZE);
- else
- is = i_stream_create_file(value, IO_BLOCK_SIZE);
- param->value.v_istream = is;
- break;
- }
- }
-}
-
bool doveadm_cmdline_try_run(const char *cmd_name,
int argc, const char *const argv[],
struct doveadm_cmd_context *cctx)
doveadm_exit_code = EX_USAGE;
return TRUE;
}
-
-static int
-doveadm_cmd_process_options(int argc, const char *const argv[],
- struct doveadm_cmd_context *cctx, pool_t pool,
- ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv)
-{
- struct doveadm_cmd_param *param;
- ARRAY_TYPE(getopt_option_array) opts;
- string_t *optbuf = str_new(pool, 64);
-
- p_array_init(&opts, pool, 4);
-
- // build parameters
- if ((cctx->cmd->flags & CMD_FLAG_NO_UNORDERED_OPTIONS) != 0)
- str_append_c(optbuf, '+');
- doveadm_build_options(cctx->cmd->parameters, optbuf, &opts);
-
- unsigned int pargc;
- for (pargc = 0; cctx->cmd->parameters[pargc].name != NULL; pargc++) {
- param = array_append_space(pargv);
- memcpy(param, &cctx->cmd->parameters[pargc],
- sizeof(struct doveadm_cmd_param));
- param->value_set = FALSE;
- }
- i_assert(pargc == array_count(&opts)-1); /* opts is NULL-terminated */
-
- if ((cctx->cmd->flags & CMD_FLAG_NO_OPTIONS) != 0) {
- /* process -parameters as if they were regular parameters */
- optind = 1;
- return 0;
- }
-
- int c, li;
- while ((c = getopt_long(argc, (char *const *)argv, str_c(optbuf),
- array_front(&opts), &li)) > -1) {
- switch (c) {
- case 0:
- for (unsigned int i = 0; i < array_count(pargv); i++) {
- const struct option *opt = array_idx(&opts, li);
- param = array_idx_modifiable(pargv, i);
- if (opt->name == param->name)
- doveadm_fill_param(param, optarg, pool);
- }
- break;
- case '?':
- case ':':
- doveadm_cmd_params_clean(pargv);
- 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);
- }
- }
- }
- return 0;
-}
-
-int doveadm_cmdline_run(int argc, const char *const argv[],
- struct doveadm_cmd_context *cctx)
-{
- ARRAY_TYPE(doveadm_cmd_param_arr_t) pargv;
- unsigned int pargc;
- pool_t pool = pool_datastack_create();
-
- p_array_init(&pargv, pool, 20);
- if (doveadm_cmd_process_options(argc, argv, cctx, pool, &pargv) < 0)
- return -1;
-
- /* 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: %s",
- t_strarray_join(argv + optind, " "));
- doveadm_cmd_params_clean(&pargv);
- return -1;
- }
- }
-
- doveadm_cmd_params_null_terminate_arrays(&pargv);
- cctx->argv = array_get_modifiable(&pargv, &pargc);
- cctx->argc = pargc;
-
- cctx->cmd->cmd(cctx);
-
- doveadm_cmd_params_clean(&pargv);
- return 0;
-}
#ifndef DOVEADM_CMD_H
#define DOVEADM_CMD_H
-#include "net.h"
-
-#define DOVEADM_CMD_PARAMS_START .parameters = (const struct doveadm_cmd_param[]){
-#define DOVEADM_CMD_PARAM(optP, nameP, typeP, flagP ) { .short_opt = optP, .name = nameP, .type = typeP, .flags = flagP },
-#define DOVEADM_CMD_PARAMS_END { .short_opt = '\0', .name = NULL, .type = CMD_PARAM_BOOL, .flags = CMD_PARAM_FLAG_NONE } }
-
-struct doveadm_cmd_ver2;
-struct doveadm_cmd_context;
-struct doveadm_mail_cmd_context;
+#include "doveadm-cmd-parse.h"
typedef void doveadm_command_t(int argc, char *argv[]);
-typedef enum {
- CMD_PARAM_BOOL = 0, /* value will contain 1 (not pointer) */
- CMD_PARAM_INT64, /* ditto but contains number (not pointer) */
- CMD_PARAM_IP, /* value contains struct ip_addr */
- 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;
-
-typedef enum {
- CMD_FLAG_NONE = 0x0,
- CMD_FLAG_HIDDEN = 0x1,
- CMD_FLAG_NO_PRINT = 0x2,
- /* Don't parse any -options for the command. */
- CMD_FLAG_NO_OPTIONS = 0x4,
- /* Prevent GNU getopt() from finding options after the first
- non-option is seen (e.g. "-1 arg -2" would parse -1 but not -2
- as option). */
- CMD_FLAG_NO_UNORDERED_OPTIONS = 0x8,
-} doveadm_cmd_flag_t;
-
-struct doveadm_cmd_param {
- char short_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 ip_addr v_ip;
- struct istream* v_istream;
- } value;
- doveadm_cmd_param_flag_t flags;
-};
-ARRAY_DEFINE_TYPE(doveadm_cmd_param_arr_t, struct doveadm_cmd_param);
-
-typedef void doveadm_command_ver2_t(struct doveadm_cmd_context *cctx);
-
-struct doveadm_cmd_ver2 {
- doveadm_command_ver2_t *cmd;
- struct doveadm_mail_cmd_context *(*mail_cmd)(void);
- const char *name;
- const char *usage;
- doveadm_cmd_flag_t flags;
- const struct doveadm_cmd_param *parameters;
-};
-
-struct doveadm_cmd_context {
- const struct doveadm_cmd_ver2 *cmd; /* for help */
-
- pool_t pool;
- int argc;
- const struct doveadm_cmd_param *argv;
-
- const char *username;
- struct ip_addr local_ip, remote_ip;
- in_port_t local_port, remote_port;
- /* extra fields (e.g. forward_*) sent via doveadm protocol */
- const char *const *extra_fields;
-
- enum doveadm_client_type conn_type;
- struct istream *input;
- struct ostream *output;
-
- /* non-NULL if doveadm-server should return referral to another
- server instead. */
- const char *referral;
- bool proxy_redirect_reauth;
-};
-
ARRAY_DEFINE_TYPE(doveadm_cmd_ver2, struct doveadm_cmd_ver2);
extern ARRAY_TYPE(doveadm_cmd_ver2) doveadm_cmds_ver2;
bool doveadm_cmdline_try_run(const char *cmd_name,
int argc, const char *const argv[],
struct doveadm_cmd_context *cctx);
-/* Returns 0 if success, -1 if parameters were invalid. */
-int doveadm_cmdline_run(int argc, const char *const argv[],
- struct doveadm_cmd_context *cctx);
-
-bool doveadm_cmd_param_bool(const struct doveadm_cmd_context *cctx,
- const char *name, bool *value_r);
-bool doveadm_cmd_param_int64(const struct doveadm_cmd_context *cctx,
- const char *name, int64_t *value_r);
-bool doveadm_cmd_param_str(const struct doveadm_cmd_context *cctx,
- const char *name, const char **value_r);
-bool doveadm_cmd_param_ip(const struct doveadm_cmd_context *cctx,
- const char *name, struct ip_addr *value_r);
-bool doveadm_cmd_param_array(const struct doveadm_cmd_context *cctx,
- const char *name, const char *const **value_r);
-bool doveadm_cmd_param_istream(const struct doveadm_cmd_context *cctx,
- const char *name, struct istream **value_r);
-
-void doveadm_cmd_params_clean(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv);
-void doveadm_cmd_params_null_terminate_arrays(ARRAY_TYPE(doveadm_cmd_param_arr_t) *pargv);
extern struct doveadm_cmd_ver2 doveadm_cmd_dump;
extern struct doveadm_cmd_ver2 doveadm_cmd_service_stop_ver2;