diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 19:59:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 19:59:03 +0000 |
commit | a848231ae0f346dc7cc000973fbeb65b0894ee92 (patch) | |
tree | 44b60b367c86723cc78383ef247885d72b388afe /src/util/dict_test.c | |
parent | Initial commit. (diff) | |
download | postfix-a848231ae0f346dc7cc000973fbeb65b0894ee92.tar.xz postfix-a848231ae0f346dc7cc000973fbeb65b0894ee92.zip |
Adding upstream version 3.8.5.upstream/3.8.5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/util/dict_test.c')
-rw-r--r-- | src/util/dict_test.c | 166 |
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); +} |