xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_test.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
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