1 /* $NetBSD: dict_test.c,v 1.2 2017/02/14 01:16:49 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
usage(char * myname)33 static NORETURN usage(char *myname)
34 {
35 msg_fatal("usage: %s type:file read|write|create [flags...]", myname);
36 }
37
dict_test(int argc,char ** argv)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 dict_register(dict_name, dict);
92 vstream_printf("owner=%s (uid=%ld)\n",
93 dict->owner.status == DICT_OWNER_TRUSTED ? "trusted" :
94 dict->owner.status == DICT_OWNER_UNTRUSTED ? "untrusted" :
95 dict->owner.status == DICT_OWNER_UNKNOWN ? "unspecified" :
96 "error", (long) dict->owner.uid);
97 vstream_fflush(VSTREAM_OUT);
98
99 while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
100 bufp = vstring_str(inbuf);
101 if (!isatty(0)) {
102 vstream_printf("> %s\n", bufp);
103 vstream_fflush(VSTREAM_OUT);
104 }
105 if (*bufp == '#')
106 continue;
107 if ((cmd = mystrtok(&bufp, " ")) == 0) {
108 vstream_printf("usage: %s\n", USAGE);
109 vstream_fflush(VSTREAM_OUT);
110 continue;
111 }
112 if (dict_changed_name())
113 msg_warn("dictionary has changed");
114 key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0;
115 value = mystrtok(&bufp, " =");
116 if (strcmp(cmd, "verbose") == 0 && !key) {
117 msg_verbose++;
118 } else if (strcmp(cmd, "del") == 0 && key && !value) {
119 if ((rc = dict_del(dict, key)) > 0)
120 vstream_printf("%s: not found\n", key);
121 else if (rc < 0)
122 vstream_printf("%s: error\n", key);
123 else
124 vstream_printf("%s: deleted\n", key);
125 } else if (strcmp(cmd, "get") == 0 && key && !value) {
126 if ((value = dict_get(dict, key)) == 0) {
127 vstream_printf("%s: %s\n", key, dict->error ?
128 "error" : "not found");
129 } else {
130 vstream_printf("%s=%s\n", key, value);
131 }
132 } else if (strcmp(cmd, "put") == 0 && key && value) {
133 if (dict_put(dict, key, value) != 0)
134 vstream_printf("%s: %s\n", key, dict->error ?
135 "error" : "not updated");
136 } else if (strcmp(cmd, "first") == 0 && !key && !value) {
137 if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0)
138 vstream_printf("%s=%s\n", key, value);
139 else
140 vstream_printf("%s\n", dict->error ?
141 "error" : "not found");
142 } else if (strcmp(cmd, "next") == 0 && !key && !value) {
143 if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0)
144 vstream_printf("%s=%s\n", key, value);
145 else
146 vstream_printf("%s\n", dict->error ?
147 "error" : "not found");
148 } else if (strcmp(cmd, "flags") == 0 && !key && !value) {
149 vstream_printf("dict flags %s\n",
150 dict_flags_str(dict->flags));
151 } else if (strcmp(cmd, "masks") == 0 && !key && !value) {
152 vstream_printf("DICT_FLAG_IMPL_MASK %s\n",
153 dict_flags_str(DICT_FLAG_IMPL_MASK));
154 vstream_printf("DICT_FLAG_PARANOID %s\n",
155 dict_flags_str(DICT_FLAG_PARANOID));
156 vstream_printf("DICT_FLAG_RQST_MASK %s\n",
157 dict_flags_str(DICT_FLAG_RQST_MASK));
158 vstream_printf("DICT_FLAG_INST_MASK %s\n",
159 dict_flags_str(DICT_FLAG_INST_MASK));
160 } else {
161 vstream_printf("usage: %s\n", USAGE);
162 }
163 vstream_fflush(VSTREAM_OUT);
164 }
165 vstring_free(keybuf);
166 vstring_free(inbuf);
167 dict_close(dict);
168 }
169