summaryrefslogtreecommitdiffstats
path: root/src/util/dict_test.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:46:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:46:30 +0000
commitb5896ba9f6047e7031e2bdee0622d543e11a6734 (patch)
treefd7b460593a2fee1be579bec5697e6d887ea3421 /src/util/dict_test.c
parentInitial commit. (diff)
downloadpostfix-b5896ba9f6047e7031e2bdee0622d543e11a6734.tar.xz
postfix-b5896ba9f6047e7031e2bdee0622d543e11a6734.zip
Adding upstream version 3.4.23.upstream/3.4.23upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/util/dict_test.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/util/dict_test.c b/src/util/dict_test.c
new file mode 100644
index 0000000..ead61b2
--- /dev/null
+++ b/src/util/dict_test.c
@@ -0,0 +1,166 @@
+ /*
+ * Proof-of-concept test program. Create, update or read a database. Type
+ * '?' for a list of commands.
+ */
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <stringops.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <msg_vstream.h>
+#include <vstring_vstream.h>
+#include <dict.h>
+#include <dict_lmdb.h>
+#include <dict_db.h>
+
+static NORETURN usage(char *myname)
+{
+ msg_fatal("usage: %s type:file read|write|create [flags...]", myname);
+}
+
+void dict_test(int argc, char **argv)
+{
+ VSTRING *keybuf = vstring_alloc(1);
+ VSTRING *inbuf = vstring_alloc(1);
+ DICT *dict;
+ char *dict_name;
+ int open_flags;
+ char *bufp;
+ char *cmd;
+ const char *key;
+ const char *value;
+ int ch;
+ int dict_flags = 0;
+ int n;
+ int rc;
+
+#define USAGE "verbose|del key|get key|put key=value|first|next|masks|flags"
+
+ signal(SIGPIPE, SIG_IGN);
+
+ msg_vstream_init(argv[0], VSTREAM_ERR);
+ while ((ch = GETOPT(argc, argv, "v")) > 0) {
+ switch (ch) {
+ default:
+ usage(argv[0]);
+ case 'v':
+ msg_verbose++;
+ break;
+ }
+ }
+ optind = OPTIND;
+ if (argc - optind < 2)
+ usage(argv[0]);
+ if (strcasecmp(argv[optind + 1], "create") == 0)
+ open_flags = O_CREAT | O_RDWR | O_TRUNC;
+ else if (strcasecmp(argv[optind + 1], "write") == 0)
+ open_flags = O_RDWR;
+ else if (strcasecmp(argv[optind + 1], "read") == 0)
+ open_flags = O_RDONLY;
+ else
+ msg_fatal("unknown access mode: %s", argv[2]);
+ for (n = 2; argv[optind + n]; n++)
+ dict_flags |= dict_flags_mask(argv[optind + 2]);
+ if ((dict_flags & DICT_FLAG_OPEN_LOCK) == 0)
+ dict_flags |= DICT_FLAG_LOCK;
+ if ((dict_flags & (DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE)) == 0)
+ dict_flags |= DICT_FLAG_DUP_REPLACE;
+ dict_flags |= DICT_FLAG_UTF8_REQUEST;
+ vstream_fflush(VSTREAM_OUT);
+ dict_name = argv[optind];
+ dict_allow_surrogate = 1;
+ util_utf8_enable = 1;
+ dict = dict_open(dict_name, open_flags, dict_flags);
+ dict_register(dict_name, dict);
+ vstream_printf("owner=%s (uid=%ld)\n",
+ dict->owner.status == DICT_OWNER_TRUSTED ? "trusted" :
+ dict->owner.status == DICT_OWNER_UNTRUSTED ? "untrusted" :
+ dict->owner.status == DICT_OWNER_UNKNOWN ? "unspecified" :
+ "error", (long) dict->owner.uid);
+ vstream_fflush(VSTREAM_OUT);
+
+ while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
+ bufp = vstring_str(inbuf);
+ if (!isatty(0)) {
+ vstream_printf("> %s\n", bufp);
+ vstream_fflush(VSTREAM_OUT);
+ }
+ if (*bufp == '#')
+ continue;
+ if ((cmd = mystrtok(&bufp, " ")) == 0) {
+ vstream_printf("usage: %s\n", USAGE);
+ vstream_fflush(VSTREAM_OUT);
+ continue;
+ }
+ if (dict_changed_name())
+ msg_warn("dictionary has changed");
+ key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0;
+ value = mystrtok(&bufp, " =");
+ if (strcmp(cmd, "verbose") == 0 && !key) {
+ msg_verbose++;
+ } else if (strcmp(cmd, "del") == 0 && key && !value) {
+ if ((rc = dict_del(dict, key)) > 0)
+ vstream_printf("%s: not found\n", key);
+ else if (rc < 0)
+ vstream_printf("%s: error\n", key);
+ else
+ vstream_printf("%s: deleted\n", key);
+ } else if (strcmp(cmd, "get") == 0 && key && !value) {
+ if ((value = dict_get(dict, key)) == 0) {
+ vstream_printf("%s: %s\n", key, dict->error ?
+ "error" : "not found");
+ } else {
+ vstream_printf("%s=%s\n", key, value);
+ }
+ } else if (strcmp(cmd, "put") == 0 && key && value) {
+ if (dict_put(dict, key, value) != 0)
+ vstream_printf("%s: %s\n", key, dict->error ?
+ "error" : "not updated");
+ } else if (strcmp(cmd, "first") == 0 && !key && !value) {
+ if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0)
+ vstream_printf("%s=%s\n", key, value);
+ else
+ vstream_printf("%s\n", dict->error ?
+ "error" : "not found");
+ } else if (strcmp(cmd, "next") == 0 && !key && !value) {
+ if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0)
+ vstream_printf("%s=%s\n", key, value);
+ else
+ vstream_printf("%s\n", dict->error ?
+ "error" : "not found");
+ } else if (strcmp(cmd, "flags") == 0 && !key && !value) {
+ vstream_printf("dict flags %s\n",
+ dict_flags_str(dict->flags));
+ } else if (strcmp(cmd, "masks") == 0 && !key && !value) {
+ vstream_printf("DICT_FLAG_IMPL_MASK %s\n",
+ dict_flags_str(DICT_FLAG_IMPL_MASK));
+ vstream_printf("DICT_FLAG_PARANOID %s\n",
+ dict_flags_str(DICT_FLAG_PARANOID));
+ vstream_printf("DICT_FLAG_RQST_MASK %s\n",
+ dict_flags_str(DICT_FLAG_RQST_MASK));
+ vstream_printf("DICT_FLAG_INST_MASK %s\n",
+ dict_flags_str(DICT_FLAG_INST_MASK));
+ } else {
+ vstream_printf("usage: %s\n", USAGE);
+ }
+ vstream_fflush(VSTREAM_OUT);
+ }
+ vstring_free(keybuf);
+ vstring_free(inbuf);
+ dict_close(dict);
+}