1 /* $NetBSD: dict_test.c,v 1.3 2026/05/09 18:49:22 christos Exp $ */ 2 3 /* 4 * Proof-of-concept test program. Create, update or read a database. Type 5 * '?' for a list of commands. 6 */ 7 8 /* System library. */ 9 10 #include <sys_defs.h> 11 #include <stdlib.h> 12 #include <fcntl.h> 13 #include <unistd.h> 14 #include <signal.h> 15 #include <string.h> 16 17 #ifdef STRCASECMP_IN_STRINGS_H 18 #include <strings.h> 19 #endif 20 21 /* Utility library. */ 22 23 #include <msg.h> 24 #include <stringops.h> 25 #include <vstring.h> 26 #include <vstream.h> 27 #include <msg_vstream.h> 28 #include <vstring_vstream.h> 29 #include <dict.h> 30 #include <dict_lmdb.h> 31 #include <dict_db.h> 32 33 static NORETURN usage(char *myname) 34 { 35 msg_fatal("usage: %s type:file read|write|create [flags...]", myname); 36 } 37 38 void dict_test(int argc, char **argv) 39 { 40 VSTRING *keybuf = vstring_alloc(1); 41 VSTRING *inbuf = vstring_alloc(1); 42 DICT *dict; 43 char *dict_name; 44 int open_flags; 45 char *bufp; 46 char *cmd; 47 const char *key; 48 const char *value; 49 int ch; 50 int dict_flags = 0; 51 int n; 52 int rc; 53 54 #define USAGE "verbose|del key|get key|put key=value|first|next|masks|flags" 55 56 signal(SIGPIPE, SIG_IGN); 57 58 msg_vstream_init(argv[0], VSTREAM_ERR); 59 while ((ch = GETOPT(argc, argv, "v")) > 0) { 60 switch (ch) { 61 default: 62 usage(argv[0]); 63 case 'v': 64 msg_verbose++; 65 break; 66 } 67 } 68 optind = OPTIND; 69 if (argc - optind < 2) 70 usage(argv[0]); 71 if (strcasecmp(argv[optind + 1], "create") == 0) 72 open_flags = O_CREAT | O_RDWR | O_TRUNC; 73 else if (strcasecmp(argv[optind + 1], "write") == 0) 74 open_flags = O_RDWR; 75 else if (strcasecmp(argv[optind + 1], "read") == 0) 76 open_flags = O_RDONLY; 77 else 78 msg_fatal("unknown access mode: %s", argv[2]); 79 for (n = 2; argv[optind + n]; n++) 80 dict_flags |= dict_flags_mask(argv[optind + 2]); 81 if ((dict_flags & DICT_FLAG_OPEN_LOCK) == 0) 82 dict_flags |= DICT_FLAG_LOCK; 83 if ((dict_flags & (DICT_FLAG_DUP_WARN | DICT_FLAG_DUP_IGNORE)) == 0) 84 dict_flags |= DICT_FLAG_DUP_REPLACE; 85 dict_flags |= DICT_FLAG_UTF8_REQUEST; 86 vstream_fflush(VSTREAM_OUT); 87 dict_name = argv[optind]; 88 dict_allow_surrogate = 1; 89 util_utf8_enable = 1; 90 dict = dict_open(dict_name, open_flags, dict_flags); 91 vstream_printf("owner=%s (uid=%ld)\n", 92 dict->owner.status == DICT_OWNER_TRUSTED ? "trusted" : 93 dict->owner.status == DICT_OWNER_UNTRUSTED ? "untrusted" : 94 dict->owner.status == DICT_OWNER_UNKNOWN ? "unspecified" : 95 "error", (long) dict->owner.uid); 96 vstream_fflush(VSTREAM_OUT); 97 98 while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { 99 bufp = vstring_str(inbuf); 100 if (!isatty(0)) { 101 vstream_printf("> %s\n", bufp); 102 vstream_fflush(VSTREAM_OUT); 103 } 104 if (*bufp == '#') 105 continue; 106 if ((cmd = mystrtok(&bufp, " ")) == 0) { 107 vstream_printf("usage: %s\n", USAGE); 108 vstream_fflush(VSTREAM_OUT); 109 continue; 110 } 111 if (dict_changed_name()) 112 msg_warn("dictionary has changed"); 113 key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; 114 value = mystrtok(&bufp, " ="); 115 if (strcmp(cmd, "verbose") == 0 && !key) { 116 msg_verbose++; 117 } else if (strcmp(cmd, "del") == 0 && key && !value) { 118 if ((rc = dict_del(dict, key)) > 0) 119 vstream_printf("%s: not found\n", key); 120 else if (rc < 0) 121 vstream_printf("%s: error\n", key); 122 else 123 vstream_printf("%s: deleted\n", key); 124 } else if (strcmp(cmd, "get") == 0 && key && !value) { 125 if ((value = dict_get(dict, key)) == 0) { 126 vstream_printf("%s: %s\n", key, dict->error ? 127 "error" : "not found"); 128 } else { 129 vstream_printf("%s=%s\n", key, value); 130 } 131 } else if (strcmp(cmd, "put") == 0 && key && value) { 132 if (dict_put(dict, key, value) != 0) 133 vstream_printf("%s: %s\n", key, dict->error ? 134 "error" : "not updated"); 135 } else if (strcmp(cmd, "first") == 0 && !key && !value) { 136 if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) 137 vstream_printf("%s=%s\n", key, value); 138 else 139 vstream_printf("%s\n", dict->error ? 140 "error" : "not found"); 141 } else if (strcmp(cmd, "next") == 0 && !key && !value) { 142 if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) 143 vstream_printf("%s=%s\n", key, value); 144 else 145 vstream_printf("%s\n", dict->error ? 146 "error" : "not found"); 147 } else if (strcmp(cmd, "flags") == 0 && !key && !value) { 148 vstream_printf("dict flags %s\n", 149 dict_flags_str(dict->flags)); 150 } else if (strcmp(cmd, "masks") == 0 && !key && !value) { 151 vstream_printf("DICT_FLAG_PARANOID %s\n", 152 dict_flags_str(DICT_FLAG_PARANOID)); 153 } else { 154 vstream_printf("usage: %s\n", USAGE); 155 } 156 vstream_fflush(VSTREAM_OUT); 157 } 158 vstring_free(keybuf); 159 vstring_free(inbuf); 160 dict_close(dict); 161 } 162