summaryrefslogtreecommitdiffstats
path: root/src/doveadm/doveadm-dict.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/doveadm/doveadm-dict.c
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doveadm/doveadm-dict.c')
-rw-r--r--src/doveadm/doveadm-dict.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/doveadm/doveadm-dict.c b/src/doveadm/doveadm-dict.c
new file mode 100644
index 0000000..12b901a
--- /dev/null
+++ b/src/doveadm/doveadm-dict.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "dict.h"
+#include "doveadm.h"
+#include "doveadm-print.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+static int
+cmd_dict_init_full(struct doveadm_cmd_context *cctx,
+ doveadm_command_ver2_t *cmd ATTR_UNUSED, enum dict_iterate_flags *iter_flags,
+ struct dict **dict_r, struct dict_op_settings *dopset_r)
+{
+ struct dict_settings dict_set;
+ struct dict *dict;
+ bool set = FALSE;
+ const char *dict_uri, *error, *key, *username = "";
+ i_zero(dopset_r);
+
+ if (doveadm_cmd_param_bool(cctx, "exact", &set) && set)
+ *iter_flags |= DICT_ITERATE_FLAG_EXACT_KEY;
+ if (doveadm_cmd_param_bool(cctx, "recurse", &set) && set)
+ *iter_flags |= DICT_ITERATE_FLAG_RECURSE;
+ if (doveadm_cmd_param_bool(cctx, "no-value", &set) && set)
+ *iter_flags |= DICT_ITERATE_FLAG_NO_VALUE;
+ (void)doveadm_cmd_param_str(cctx, "user", &username);
+ dopset_r->username = username;
+
+ if (!doveadm_cmd_param_str(cctx, "dict-uri", &dict_uri)) {
+ i_error("dictionary URI must be specified");
+ doveadm_exit_code = EX_USAGE;
+ return -1;
+ }
+
+ if (!doveadm_cmd_param_str(cctx, "prefix", &key) &&
+ !doveadm_cmd_param_str(cctx, "key", &key))
+ key = "";
+
+ if (!str_begins(key, DICT_PATH_PRIVATE) &&
+ !str_begins(key, DICT_PATH_SHARED)) {
+ i_error("Key must begin with '"DICT_PATH_PRIVATE
+ "' or '"DICT_PATH_SHARED"': %s", key);
+ doveadm_exit_code = EX_USAGE;
+ return -1;
+ }
+ if (username[0] == '\0' &&
+ str_begins(key, DICT_PATH_PRIVATE)) {
+ i_error("-u must be specified for "DICT_PATH_PRIVATE" keys");
+ doveadm_exit_code = EX_USAGE;
+ return -1;
+ }
+
+ dict_drivers_register_builtin();
+ i_zero(&dict_set);
+ dict_set.base_dir = doveadm_settings->base_dir;
+ if (dict_init(dict_uri, &dict_set, &dict, &error) < 0) {
+ i_error("dict_init(%s) failed: %s", dict_uri, error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ return -1;
+ }
+ *dict_r = dict;
+ return 0;
+}
+
+static int
+cmd_dict_init(struct doveadm_cmd_context *cctx,
+ doveadm_command_ver2_t *cmd, struct dict **dict_r,
+ struct dict_op_settings *set_r)
+{
+ enum dict_iterate_flags iter_flags = 0;
+ return cmd_dict_init_full(cctx, cmd, &iter_flags, dict_r, set_r);
+}
+
+struct doveadm_dict_ctx {
+ pool_t pool;
+ int ret;
+ const char *const *values;
+ const char *error;
+};
+
+static void dict_lookup_callback(const struct dict_lookup_result *result,
+ struct doveadm_dict_ctx *ctx)
+{
+ ctx->ret = result->ret;
+ ctx->values = result->values == NULL ? NULL :
+ p_strarray_dup(ctx->pool, result->values);
+ ctx->error = p_strdup(ctx->pool, result->error);
+}
+
+static void cmd_dict_get(struct doveadm_cmd_context *cctx)
+{
+ struct doveadm_dict_ctx ctx;
+ struct dict *dict;
+ const char *key;
+ struct dict_op_settings set;
+
+ if (!doveadm_cmd_param_str(cctx, "key", &key)) {
+ i_error("dict-get: Missing key");
+ doveadm_exit_code = EX_USAGE;
+ return;
+ }
+
+ if (cmd_dict_init(cctx, cmd_dict_get, &dict, &set) < 0)
+ return;
+
+ doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
+ doveadm_print_header("value", "", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+
+ i_zero(&ctx);
+ ctx.pool = pool_alloconly_create("doveadm dict lookup", 512);
+ ctx.ret = -2;
+ dict_lookup_async(dict, &set, key, dict_lookup_callback, &ctx);
+ while (ctx.ret == -2)
+ dict_wait(dict);
+ if (ctx.ret < 0) {
+ i_error("dict_lookup(%s) failed: %s", key, ctx.error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ } else if (ctx.ret == 0) {
+ i_error("%s doesn't exist", key);
+ doveadm_exit_code = DOVEADM_EX_NOTFOUND;
+ } else {
+ unsigned int i, values_count = str_array_length(ctx.values);
+
+ for (i = 1; i < values_count; i++)
+ doveadm_print_header("value", "", DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
+ for (i = 0; i < values_count; i++)
+ doveadm_print(ctx.values[i]);
+ }
+ pool_unref(&ctx.pool);
+ dict_deinit(&dict);
+}
+
+static void cmd_dict_set(struct doveadm_cmd_context *cctx)
+{
+ struct dict *dict;
+ struct dict_transaction_context *trans;
+ const char *error;
+ const char *key, *value = "";
+ struct dict_op_settings set;
+
+ if (!doveadm_cmd_param_str(cctx, "key", &key) ||
+ !doveadm_cmd_param_str(cctx, "value", &value)) {
+ i_error("dict set: Missing parameters");
+ doveadm_exit_code = EX_USAGE;
+ return;
+ }
+
+ if (cmd_dict_init(cctx, cmd_dict_set, &dict, &set) < 0)
+ return;
+
+ trans = dict_transaction_begin(dict, &set);
+ dict_set(trans, key, value);
+ if (dict_transaction_commit(&trans, &error) <= 0) {
+ i_error("dict_transaction_commit() failed: %s", error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ }
+ dict_deinit(&dict);
+}
+
+static void cmd_dict_unset(struct doveadm_cmd_context *cctx)
+{
+ struct dict *dict;
+ struct dict_transaction_context *trans;
+ const char *error;
+ const char *key;
+ struct dict_op_settings set;
+
+ if (!doveadm_cmd_param_str(cctx, "key", &key)) {
+ i_error("dict unset: Missing key");
+ doveadm_exit_code = EX_USAGE;
+ return;
+ }
+
+ if (cmd_dict_init(cctx, cmd_dict_unset, &dict, &set) < 0)
+ return;
+
+ trans = dict_transaction_begin(dict, &set);
+ dict_unset(trans, key);
+ if (dict_transaction_commit(&trans, &error) <= 0) {
+ i_error("dict_transaction_commit() failed: %s", error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ }
+ dict_deinit(&dict);
+}
+
+static void cmd_dict_inc(struct doveadm_cmd_context *cctx)
+{
+ struct dict *dict;
+ struct dict_transaction_context *trans;
+ const char *error;
+ const char *key;
+ int64_t diff;
+ int ret;
+ struct dict_op_settings set;
+
+ if (!doveadm_cmd_param_str(cctx, "key", &key) ||
+ !doveadm_cmd_param_int64(cctx, "difference", &diff)) {
+ i_error("dict-inc: Missing parameters");
+ doveadm_exit_code = EX_USAGE;
+ return;
+ }
+
+ if (cmd_dict_init(cctx, cmd_dict_inc, &dict, &set) < 0)
+ return;
+
+ trans = dict_transaction_begin(dict, &set);
+ dict_atomic_inc(trans, key, diff);
+ ret = dict_transaction_commit(&trans, &error);
+ if (ret < 0) {
+ i_error("dict_transaction_commit() failed: %s", error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ } else if (ret == 0) {
+ i_error("%s doesn't exist", key);
+ doveadm_exit_code = DOVEADM_EX_NOTFOUND;
+ }
+ dict_deinit(&dict);
+}
+
+static void cmd_dict_iter(struct doveadm_cmd_context *cctx)
+{
+ struct dict *dict;
+ struct dict_iterate_context *iter;
+ enum dict_iterate_flags iter_flags = 0;
+ const char *prefix, *key, *const *values, *error;
+ bool header_printed = FALSE;
+ struct dict_op_settings set;
+
+ if (!doveadm_cmd_param_str(cctx, "prefix", &prefix)) {
+ i_error("dict-iter: Missing prefix");
+ doveadm_exit_code = EX_USAGE;
+ return;
+ }
+
+ if (cmd_dict_init_full(cctx, cmd_dict_iter, &iter_flags, &dict, &set) < 0)
+ return;
+
+ doveadm_print_init(DOVEADM_PRINT_TYPE_TAB);
+ doveadm_print_header_simple("key");
+ if ((iter_flags & DICT_ITERATE_FLAG_NO_VALUE) == 0)
+ doveadm_print_header_simple("value");
+
+ iter = dict_iterate_init(dict, &set, prefix, iter_flags);
+ while (dict_iterate_values(iter, &key, &values)) {
+ unsigned int values_count = str_array_length(values);
+ if (!header_printed) {
+ for (unsigned int i = 1; i < values_count; i++)
+ doveadm_print_header_simple("value");
+ header_printed = TRUE;
+ }
+ doveadm_print(key);
+ if ((iter_flags & DICT_ITERATE_FLAG_NO_VALUE) == 0) {
+ for (unsigned int i = 0; i < values_count; i++)
+ doveadm_print(values[i]);
+ }
+ }
+ if (dict_iterate_deinit(&iter, &error) < 0) {
+ i_error("dict_iterate_deinit(%s) failed: %s", prefix, error);
+ doveadm_exit_code = EX_TEMPFAIL;
+ }
+ dict_deinit(&dict);
+}
+
+static struct doveadm_cmd_ver2 doveadm_cmd_dict[] = {
+{
+ .name = "dict get",
+ .cmd = cmd_dict_get,
+ .usage = "[-u <user>] <dict uri> <key>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('u', "user", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('\0', "dict-uri", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "key", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+},
+{
+ .name = "dict set",
+ .cmd = cmd_dict_set,
+ .usage = "[-u <user>] <dict uri> <key> <value>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('u', "user", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('\0', "dict-uri", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "key", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "value", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+},
+{
+ .name = "dict unset",
+ .cmd = cmd_dict_unset,
+ .usage = "[-u <user>] <dict uri> <key>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('u', "user", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('\0', "dict-uri", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "key", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+},
+{
+ .name = "dict inc",
+ .cmd = cmd_dict_inc,
+ .usage = "[-u <user>] <dict uri> <key> <diff>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('u', "user", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('\0', "dict-uri", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "key", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "difference", CMD_PARAM_INT64, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+},
+{
+ .name = "dict iter",
+ .cmd = cmd_dict_iter,
+ .usage = "[-u <user>] [-1RV] <dict uri> <prefix>",
+DOVEADM_CMD_PARAMS_START
+DOVEADM_CMD_PARAM('u', "user", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('1', "exact", CMD_PARAM_BOOL, 0)
+DOVEADM_CMD_PARAM('R', "recurse", CMD_PARAM_BOOL, 0)
+DOVEADM_CMD_PARAM('V', "no-value", CMD_PARAM_BOOL, 0)
+DOVEADM_CMD_PARAM('\0', "dict-uri", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAM('\0', "prefix", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
+DOVEADM_CMD_PARAMS_END
+}
+};
+
+void doveadm_register_dict_commands(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < N_ELEMENTS(doveadm_cmd_dict); i++)
+ doveadm_cmd_register_ver2(&doveadm_cmd_dict[i]);
+}