| @@ -1,716 +1,720 @@ | | | @@ -1,716 +1,720 @@ |
1 | /* $NetBSD: db.c,v 1.21 2008/10/07 01:32:51 lukem Exp $ */ | | 1 | /* $NetBSD: db.c,v 1.22 2008/10/07 10:03:47 lukem Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2002-2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2002-2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Luke Mewburn of Wasabi Systems. | | 8 | * by Luke Mewburn of Wasabi Systems. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
| | | 32 | #if HAVE_NBTOOL_CONFIG_H |
| | | 33 | #include "nbtool_config.h" |
| | | 34 | #endif |
| | | 35 | |
32 | #include <sys/cdefs.h> | | 36 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 37 | #ifndef lint |
34 | #ifdef __RCSID | | 38 | #ifdef __RCSID |
35 | __RCSID("$NetBSD: db.c,v 1.21 2008/10/07 01:32:51 lukem Exp $"); | | 39 | __RCSID("$NetBSD: db.c,v 1.22 2008/10/07 10:03:47 lukem Exp $"); |
36 | #endif /* __RCSID */ | | 40 | #endif /* __RCSID */ |
37 | #endif /* not lint */ | | 41 | #endif /* not lint */ |
38 | | | 42 | |
39 | #include <ctype.h> | | 43 | #include <ctype.h> |
40 | #include <db.h> | | 44 | #include <db.h> |
41 | #include <err.h> | | 45 | #include <err.h> |
42 | #include <fcntl.h> | | 46 | #include <fcntl.h> |
43 | #include <limits.h> | | 47 | #include <limits.h> |
44 | #include <stdio.h> | | 48 | #include <stdio.h> |
45 | #include <stdlib.h> | | 49 | #include <stdlib.h> |
46 | #include <string.h> | | 50 | #include <string.h> |
47 | #include <unistd.h> | | 51 | #include <unistd.h> |
48 | #include <vis.h> | | 52 | #include <vis.h> |
49 | | | 53 | |
50 | | | 54 | |
51 | typedef enum { | | 55 | typedef enum { |
52 | F_WRITE = 1<<0, | | 56 | F_WRITE = 1<<0, |
53 | F_DELETE = 1<<1, | | 57 | F_DELETE = 1<<1, |
54 | F_SHOW_KEY = 1<<2, | | 58 | F_SHOW_KEY = 1<<2, |
55 | F_SHOW_VALUE = 1<<3, | | 59 | F_SHOW_VALUE = 1<<3, |
56 | F_QUIET = 1<<10, | | 60 | F_QUIET = 1<<10, |
57 | F_IGNORECASE = 1<<11, | | 61 | F_IGNORECASE = 1<<11, |
58 | F_ENDIAN_BIG = 1<<12, | | 62 | F_ENDIAN_BIG = 1<<12, |
59 | F_ENDIAN_LITTLE = 1<<13, | | 63 | F_ENDIAN_LITTLE = 1<<13, |
60 | F_NO_NUL = 1<<14, | | 64 | F_NO_NUL = 1<<14, |
61 | F_CREATENEW = 1<<20, | | 65 | F_CREATENEW = 1<<20, |
62 | F_DUPLICATES = 1<<21, | | 66 | F_DUPLICATES = 1<<21, |
63 | F_REPLACE = 1<<22, | | 67 | F_REPLACE = 1<<22, |
64 | F_ENCODE_KEY = 1<<23, | | 68 | F_ENCODE_KEY = 1<<23, |
65 | F_ENCODE_VAL = 1<<24, | | 69 | F_ENCODE_VAL = 1<<24, |
66 | F_DECODE_KEY = 1<<25, | | 70 | F_DECODE_KEY = 1<<25, |
67 | F_DECODE_VAL = 1<<26, | | 71 | F_DECODE_VAL = 1<<26, |
68 | } flags_t; | | 72 | } flags_t; |
69 | | | 73 | |
70 | int main(int, char *[]); | | 74 | int main(int, char *[]); |
71 | void db_print(DBT *, DBT *); | | 75 | void db_print(DBT *, DBT *); |
72 | int db_dump(void); | | 76 | int db_dump(void); |
73 | int db_del(char *); | | 77 | int db_del(char *); |
74 | int db_get(char *); | | 78 | int db_get(char *); |
75 | int db_put(char *, char *); | | 79 | int db_put(char *, char *); |
76 | int parseline(FILE *, const char *, char **, char **); | | 80 | int parseline(FILE *, const char *, char **, char **); |
77 | int encode_data(size_t, char *, char **); | | 81 | int encode_data(size_t, char *, char **); |
78 | int decode_data(char *, char **); | | 82 | int decode_data(char *, char **); |
79 | void parse_encode_decode_arg(const char *, int); | | 83 | void parse_encode_decode_arg(const char *, int); |
80 | int parse_encode_option(char **); | | 84 | int parse_encode_option(char **); |
81 | void usage(void); | | 85 | void usage(void); |
82 | | | 86 | |
83 | flags_t flags = 0; | | 87 | flags_t flags = 0; |
84 | DB *db; | | 88 | DB *db; |
85 | const char *outputsep = "\t"; | | 89 | const char *outputsep = "\t"; |
86 | int visflags = 0; | | 90 | int visflags = 0; |
87 | const char *extra_echars = NULL; | | 91 | const char *extra_echars = NULL; |
88 | | | 92 | |
89 | int | | 93 | int |
90 | main(int argc, char *argv[]) | | 94 | main(int argc, char *argv[]) |
91 | { | | 95 | { |
92 | struct { | | 96 | struct { |
93 | char *file; | | 97 | char *file; |
94 | char *type; | | 98 | char *type; |
95 | DBTYPE dbtype; | | 99 | DBTYPE dbtype; |
96 | void *info; | | 100 | void *info; |
97 | int flags; | | 101 | int flags; |
98 | mode_t mode; | | 102 | mode_t mode; |
99 | unsigned int pagesize; | | 103 | unsigned int pagesize; |
100 | } oi; | | 104 | } oi; |
101 | BTREEINFO btreeinfo; | | 105 | BTREEINFO btreeinfo; |
102 | HASHINFO hashinfo; | | 106 | HASHINFO hashinfo; |
103 | FILE *infp; | | 107 | FILE *infp; |
104 | const char *infile, *fieldsep; | | 108 | const char *infile, *fieldsep; |
105 | char *p, *key, *val; | | 109 | char *p, *key, *val; |
106 | int ch, rv; | | 110 | int ch, rv; |
107 | long lval; | | 111 | long lval; |
108 | | | 112 | |
109 | setprogname(argv[0]); | | 113 | setprogname(argv[0]); |
110 | | | 114 | |
111 | infile = NULL; | | 115 | infile = NULL; |
112 | fieldsep = " "; | | 116 | fieldsep = " "; |
113 | infp = NULL; | | 117 | infp = NULL; |
114 | memset(&oi, 0, sizeof(oi)); | | 118 | memset(&oi, 0, sizeof(oi)); |
115 | oi.mode = 0644; | | 119 | oi.mode = 0644; |
116 | oi.pagesize = 4096; | | 120 | oi.pagesize = 4096; |
117 | | | 121 | |
118 | /* parse arguments */ | | 122 | /* parse arguments */ |
119 | while ( (ch = getopt(argc, argv, | | 123 | while ( (ch = getopt(argc, argv, |
120 | "CDdE:F:f:iKm:NO:P:qRS:T:U:VwX:")) != -1) { | | 124 | "CDdE:F:f:iKm:NO:P:qRS:T:U:VwX:")) != -1) { |
121 | switch (ch) { | | 125 | switch (ch) { |
122 | | | 126 | |
123 | case 'C': | | 127 | case 'C': |
124 | flags |= F_CREATENEW; | | 128 | flags |= F_CREATENEW; |
125 | break; | | 129 | break; |
126 | | | 130 | |
127 | case 'D': | | 131 | case 'D': |
128 | flags |= F_DUPLICATES; | | 132 | flags |= F_DUPLICATES; |
129 | break; | | 133 | break; |
130 | | | 134 | |
131 | case 'd': | | 135 | case 'd': |
132 | flags |= F_DELETE; | | 136 | flags |= F_DELETE; |
133 | break; | | 137 | break; |
134 | | | 138 | |
135 | case 'E': | | 139 | case 'E': |
136 | if (! optarg[0] || optarg[1]) | | 140 | if (! optarg[0] || optarg[1]) |
137 | goto badendian; | | 141 | goto badendian; |
138 | switch (toupper((int)optarg[0])) { | | 142 | switch (toupper((int)optarg[0])) { |
139 | case 'B': | | 143 | case 'B': |
140 | flags |= F_ENDIAN_BIG; | | 144 | flags |= F_ENDIAN_BIG; |
141 | break; | | 145 | break; |
142 | case 'L': | | 146 | case 'L': |
143 | flags |= F_ENDIAN_LITTLE; | | 147 | flags |= F_ENDIAN_LITTLE; |
144 | break; | | 148 | break; |
145 | case 'H': | | 149 | case 'H': |
146 | flags &= ~(F_ENDIAN_BIG | F_ENDIAN_LITTLE); | | 150 | flags &= ~(F_ENDIAN_BIG | F_ENDIAN_LITTLE); |
147 | break; | | 151 | break; |
148 | default: | | 152 | default: |
149 | badendian: | | 153 | badendian: |
150 | errx(1, "Bad endian `%s'", optarg); | | 154 | errx(1, "Bad endian `%s'", optarg); |
151 | } | | 155 | } |
152 | break; | | 156 | break; |
153 | | | 157 | |
154 | case 'F': | | 158 | case 'F': |
155 | if (! optarg[0]) | | 159 | if (! optarg[0]) |
156 | errx(1, "Invalid field separator `%s'", | | 160 | errx(1, "Invalid field separator `%s'", |
157 | optarg); | | 161 | optarg); |
158 | fieldsep = optarg; | | 162 | fieldsep = optarg; |
159 | break; | | 163 | break; |
160 | | | 164 | |
161 | case 'f': | | 165 | case 'f': |
162 | infile = optarg; | | 166 | infile = optarg; |
163 | break; | | 167 | break; |
164 | | | 168 | |
165 | case 'i': | | 169 | case 'i': |
166 | flags |= F_IGNORECASE; | | 170 | flags |= F_IGNORECASE; |
167 | break; | | 171 | break; |
168 | | | 172 | |
169 | case 'K': | | 173 | case 'K': |
170 | flags |= F_SHOW_KEY; | | 174 | flags |= F_SHOW_KEY; |
171 | break; | | 175 | break; |
172 | | | 176 | |
173 | case 'm': | | 177 | case 'm': |
174 | lval = strtol(optarg, &p, 8); | | 178 | lval = strtol(optarg, &p, 8); |
175 | if (p == optarg || *p != '\0') | | 179 | if (p == optarg || *p != '\0') |
176 | errx(1, "Invalid octal number `%s'", optarg); | | 180 | errx(1, "Invalid octal number `%s'", optarg); |
177 | if (lval < 0 || lval > 07777) | | 181 | if (lval < 0 || lval > 07777) |
178 | errx(1, "Invalid mode `%s'", optarg); | | 182 | errx(1, "Invalid mode `%s'", optarg); |
179 | oi.mode = (mode_t)lval; | | 183 | oi.mode = (mode_t)lval; |
180 | break; | | 184 | break; |
181 | | | 185 | |
182 | case 'N': | | 186 | case 'N': |
183 | flags |= F_NO_NUL; | | 187 | flags |= F_NO_NUL; |
184 | break; | | 188 | break; |
185 | | | 189 | |
186 | case 'O': | | 190 | case 'O': |
187 | outputsep = optarg; | | 191 | outputsep = optarg; |
188 | break; | | 192 | break; |
189 | | | 193 | |
190 | case 'P': | | 194 | case 'P': |
191 | lval = strtol(optarg, &p, 10); | | 195 | lval = strtol(optarg, &p, 10); |
192 | if (p == optarg || *p != '\0') | | 196 | if (p == optarg || *p != '\0') |
193 | errx(1, "Invalid pagesize `%s'", optarg); | | 197 | errx(1, "Invalid pagesize `%s'", optarg); |
194 | if (lval < 0 || lval >= UINT_MAX) | | 198 | if (lval < 0 || lval >= UINT_MAX) |
195 | errx(1, "Pagesize `%s' out of range", optarg); | | 199 | errx(1, "Pagesize `%s' out of range", optarg); |
196 | oi.pagesize = (unsigned int)lval; | | 200 | oi.pagesize = (unsigned int)lval; |
197 | break; | | 201 | break; |
198 | | | 202 | |
199 | case 'q': | | 203 | case 'q': |
200 | flags |= F_QUIET; | | 204 | flags |= F_QUIET; |
201 | break; | | 205 | break; |
202 | | | 206 | |
203 | case 'R': | | 207 | case 'R': |
204 | flags |= F_REPLACE; | | 208 | flags |= F_REPLACE; |
205 | break; | | 209 | break; |
206 | | | 210 | |
207 | case 'S': | | 211 | case 'S': |
208 | parse_encode_decode_arg(optarg, 1 /* encode */); | | 212 | parse_encode_decode_arg(optarg, 1 /* encode */); |
209 | if (! (flags & (F_ENCODE_KEY | F_ENCODE_VAL))) | | 213 | if (! (flags & (F_ENCODE_KEY | F_ENCODE_VAL))) |
210 | errx(1, "Invalid encoding argument `%s'", | | 214 | errx(1, "Invalid encoding argument `%s'", |
211 | optarg); | | 215 | optarg); |
212 | break; | | 216 | break; |
213 | | | 217 | |
214 | case 'T': | | 218 | case 'T': |
215 | visflags = parse_encode_option(&optarg); | | 219 | visflags = parse_encode_option(&optarg); |
216 | if (! visflags) | | 220 | if (! visflags) |
217 | errx(1, "Invalid encoding/decoding option `%s'", | | 221 | errx(1, "Invalid encoding/decoding option `%s'", |
218 | optarg); | | 222 | optarg); |
219 | break; | | 223 | break; |
220 | | | 224 | |
221 | case 'U': | | 225 | case 'U': |
222 | parse_encode_decode_arg(optarg, 0 /* decode */); | | 226 | parse_encode_decode_arg(optarg, 0 /* decode */); |
223 | if (! (flags & (F_DECODE_KEY | F_DECODE_VAL))) | | 227 | if (! (flags & (F_DECODE_KEY | F_DECODE_VAL))) |
224 | errx(1, "Invalid decoding argument `%s'", | | 228 | errx(1, "Invalid decoding argument `%s'", |
225 | optarg); | | 229 | optarg); |
226 | break; | | 230 | break; |
227 | | | 231 | |
228 | case 'V': | | 232 | case 'V': |
229 | flags |= F_SHOW_VALUE; | | 233 | flags |= F_SHOW_VALUE; |
230 | break; | | 234 | break; |
231 | | | 235 | |
232 | case 'w': | | 236 | case 'w': |
233 | flags |= F_WRITE; | | 237 | flags |= F_WRITE; |
234 | break; | | 238 | break; |
235 | | | 239 | |
236 | case 'X': | | 240 | case 'X': |
237 | extra_echars = optarg; | | 241 | extra_echars = optarg; |
238 | break; | | 242 | break; |
239 | | | 243 | |
240 | default: | | 244 | default: |
241 | usage(); | | 245 | usage(); |
242 | | | 246 | |
243 | } | | 247 | } |
244 | } | | 248 | } |
245 | argc -= optind; | | 249 | argc -= optind; |
246 | argv += optind; | | 250 | argv += optind; |
247 | | | 251 | |
248 | /* validate arguments */ | | 252 | /* validate arguments */ |
249 | if (argc < 2) | | 253 | if (argc < 2) |
250 | usage(); | | 254 | usage(); |
251 | oi.type = argv[0]; | | 255 | oi.type = argv[0]; |
252 | oi.file = argv[1]; | | 256 | oi.file = argv[1]; |
253 | argc -= 2; | | 257 | argc -= 2; |
254 | argv += 2; | | 258 | argv += 2; |
255 | | | 259 | |
256 | if (flags & F_WRITE) { | | 260 | if (flags & F_WRITE) { |
257 | if (flags & (F_SHOW_KEY | F_SHOW_VALUE | F_DELETE)) | | 261 | if (flags & (F_SHOW_KEY | F_SHOW_VALUE | F_DELETE)) |
258 | usage(); | | 262 | usage(); |
259 | if ((!infile && argc < 2) || (argc % 2)) | | 263 | if ((!infile && argc < 2) || (argc % 2)) |
260 | usage(); | | 264 | usage(); |
261 | if (0 != (visflags & ~(VIS_HTTPSTYLE))) | | 265 | if (0 != (visflags & ~(VIS_HTTPSTYLE))) |
262 | errx(1, "Unsupported decoding option provided to -T"); | | 266 | errx(1, "Unsupported decoding option provided to -T"); |
263 | oi.flags = O_RDWR | O_CREAT | O_EXLOCK; | | 267 | oi.flags = O_RDWR | O_CREAT | O_EXLOCK; |
264 | if (flags & F_CREATENEW) | | 268 | if (flags & F_CREATENEW) |
265 | oi.flags |= O_TRUNC; | | 269 | oi.flags |= O_TRUNC; |
266 | } else if (flags & F_DELETE) { | | 270 | } else if (flags & F_DELETE) { |
267 | if (flags & (F_SHOW_KEY | F_SHOW_VALUE | F_WRITE)) | | 271 | if (flags & (F_SHOW_KEY | F_SHOW_VALUE | F_WRITE)) |
268 | usage(); | | 272 | usage(); |
269 | if (!infile && argc < 1) | | 273 | if (!infile && argc < 1) |
270 | usage(); | | 274 | usage(); |
271 | if (0 != (visflags & ~(VIS_HTTPSTYLE))) | | 275 | if (0 != (visflags & ~(VIS_HTTPSTYLE))) |
272 | errx(1, "Unsupported decoding option provided to -T"); | | 276 | errx(1, "Unsupported decoding option provided to -T"); |
273 | oi.flags = O_RDWR | O_CREAT | O_EXLOCK; | | 277 | oi.flags = O_RDWR | O_CREAT | O_EXLOCK; |
274 | } else { | | 278 | } else { |
275 | if (! (flags & (F_SHOW_KEY | F_SHOW_VALUE))) | | 279 | if (! (flags & (F_SHOW_KEY | F_SHOW_VALUE))) |
276 | flags |= (F_SHOW_KEY | F_SHOW_VALUE); | | 280 | flags |= (F_SHOW_KEY | F_SHOW_VALUE); |
277 | oi.flags = O_RDONLY | O_SHLOCK; | | 281 | oi.flags = O_RDONLY | O_SHLOCK; |
278 | } | | 282 | } |
279 | | | 283 | |
280 | /* validate oi.type */ | | 284 | /* validate oi.type */ |
281 | if (strcmp(oi.type, "btree") == 0) { | | 285 | if (strcmp(oi.type, "btree") == 0) { |
282 | memset(&btreeinfo, 0, sizeof(btreeinfo)); | | 286 | memset(&btreeinfo, 0, sizeof(btreeinfo)); |
283 | if (flags & F_ENDIAN_BIG) | | 287 | if (flags & F_ENDIAN_BIG) |
284 | btreeinfo.lorder = 4321; | | 288 | btreeinfo.lorder = 4321; |
285 | else if (flags & F_ENDIAN_LITTLE) | | 289 | else if (flags & F_ENDIAN_LITTLE) |
286 | btreeinfo.lorder = 1234; | | 290 | btreeinfo.lorder = 1234; |
287 | if (flags & F_DUPLICATES) | | 291 | if (flags & F_DUPLICATES) |
288 | btreeinfo.flags = R_DUP; | | 292 | btreeinfo.flags = R_DUP; |
289 | btreeinfo.psize = oi.pagesize; | | 293 | btreeinfo.psize = oi.pagesize; |
290 | btreeinfo.cachesize = 1024 * 1024; | | 294 | btreeinfo.cachesize = 1024 * 1024; |
291 | oi.info = &btreeinfo; | | 295 | oi.info = &btreeinfo; |
292 | oi.dbtype = DB_BTREE; | | 296 | oi.dbtype = DB_BTREE; |
293 | } else if (strcmp(oi.type, "hash") == 0) { | | 297 | } else if (strcmp(oi.type, "hash") == 0) { |
294 | memset(&hashinfo, 0, sizeof(hashinfo)); | | 298 | memset(&hashinfo, 0, sizeof(hashinfo)); |
295 | if (flags & F_ENDIAN_BIG) | | 299 | if (flags & F_ENDIAN_BIG) |
296 | hashinfo.lorder = 4321; | | 300 | hashinfo.lorder = 4321; |
297 | else if (flags & F_ENDIAN_LITTLE) | | 301 | else if (flags & F_ENDIAN_LITTLE) |
298 | hashinfo.lorder = 1234; | | 302 | hashinfo.lorder = 1234; |
299 | hashinfo.bsize = oi.pagesize; | | 303 | hashinfo.bsize = oi.pagesize; |
300 | hashinfo.cachesize = 1024 * 1024; | | 304 | hashinfo.cachesize = 1024 * 1024; |
301 | oi.info = &hashinfo; | | 305 | oi.info = &hashinfo; |
302 | oi.dbtype = DB_HASH; | | 306 | oi.dbtype = DB_HASH; |
303 | } else { | | 307 | } else { |
304 | warnx("Unknown database type `%s'", oi.type); | | 308 | warnx("Unknown database type `%s'", oi.type); |
305 | usage(); | | 309 | usage(); |
306 | } | | 310 | } |
307 | | | 311 | |
308 | if (infile) { | | 312 | if (infile) { |
309 | if (strcmp(infile, "-") == 0) | | 313 | if (strcmp(infile, "-") == 0) |
310 | infp = stdin; | | 314 | infp = stdin; |
311 | else if ((infp = fopen(infile, "r")) == NULL) | | 315 | else if ((infp = fopen(infile, "r")) == NULL) |
312 | err(1, "Opening input file `%s'", infile); | | 316 | err(1, "Opening input file `%s'", infile); |
313 | } | | 317 | } |
314 | | | 318 | |
315 | /* open database */ | | 319 | /* open database */ |
316 | db = dbopen(oi.file, oi.flags, oi.mode, oi.dbtype, oi.info); | | 320 | db = dbopen(oi.file, oi.flags, oi.mode, oi.dbtype, oi.info); |
317 | if (db == NULL) | | 321 | if (db == NULL) |
318 | err(1, "Opening database `%s'", oi.file); | | 322 | err(1, "Opening database `%s'", oi.file); |
319 | | | 323 | |
320 | | | 324 | |
321 | /* manipulate database */ | | 325 | /* manipulate database */ |
322 | rv = 0; | | 326 | rv = 0; |
323 | if (flags & F_WRITE) { /* write entries */ | | 327 | if (flags & F_WRITE) { /* write entries */ |
324 | for (ch = 0; ch < argc; ch += 2) | | 328 | for (ch = 0; ch < argc; ch += 2) |
325 | if ((rv = db_put(argv[ch], argv[ch+1]))) | | 329 | if ((rv = db_put(argv[ch], argv[ch+1]))) |
326 | goto cleanup; | | 330 | goto cleanup; |
327 | if (infp) { | | 331 | if (infp) { |
328 | while (parseline(infp, fieldsep, &key, &val)) { | | 332 | while (parseline(infp, fieldsep, &key, &val)) { |
329 | if ((rv = db_put(key, val))) | | 333 | if ((rv = db_put(key, val))) |
330 | goto cleanup; | | 334 | goto cleanup; |
331 | } | | 335 | } |
332 | if (ferror(infp)) { | | 336 | if (ferror(infp)) { |
333 | warnx("Reading `%s'", infile); | | 337 | warnx("Reading `%s'", infile); |
334 | goto cleanup; | | 338 | goto cleanup; |
335 | } | | 339 | } |
336 | } | | 340 | } |
337 | } else if (!infp && argc == 0) { /* read all */ | | 341 | } else if (!infp && argc == 0) { /* read all */ |
338 | db_dump(); | | 342 | db_dump(); |
339 | } else { /* read/delete specific */ | | 343 | } else { /* read/delete specific */ |
340 | int (*dbop)(char *); | | 344 | int (*dbop)(char *); |
341 | | | 345 | |
342 | if (flags & F_DELETE) | | 346 | if (flags & F_DELETE) |
343 | dbop = db_del; | | 347 | dbop = db_del; |
344 | else | | 348 | else |
345 | dbop = db_get; | | 349 | dbop = db_get; |
346 | for (ch = 0; ch < argc; ch++) { | | 350 | for (ch = 0; ch < argc; ch++) { |
347 | if ((rv = dbop(argv[ch]))) | | 351 | if ((rv = dbop(argv[ch]))) |
348 | goto cleanup; | | 352 | goto cleanup; |
349 | } | | 353 | } |
350 | if (infp) { | | 354 | if (infp) { |
351 | while (parseline(infp, fieldsep, &key, NULL)) { | | 355 | while (parseline(infp, fieldsep, &key, NULL)) { |
352 | if ((rv = dbop(key))) | | 356 | if ((rv = dbop(key))) |
353 | goto cleanup; | | 357 | goto cleanup; |
354 | } | | 358 | } |
355 | if (ferror(infp)) { | | 359 | if (ferror(infp)) { |
356 | warnx("Reading `%s'", infile); | | 360 | warnx("Reading `%s'", infile); |
357 | goto cleanup; | | 361 | goto cleanup; |
358 | } | | 362 | } |
359 | } | | 363 | } |
360 | } | | 364 | } |
361 | | | 365 | |
362 | /* close database */ | | 366 | /* close database */ |
363 | cleanup: | | 367 | cleanup: |
364 | if (db->close(db) == -1) | | 368 | if (db->close(db) == -1) |
365 | err(1, "Closing database `%s'", oi.file); | | 369 | err(1, "Closing database `%s'", oi.file); |
366 | if (infp) | | 370 | if (infp) |
367 | fclose(infp); | | 371 | fclose(infp); |
368 | return (rv); | | 372 | return (rv); |
369 | } | | 373 | } |
370 | | | 374 | |
371 | void | | 375 | void |
372 | db_print(DBT *key, DBT *val) | | 376 | db_print(DBT *key, DBT *val) |
373 | { | | 377 | { |
374 | int len; | | 378 | int len; |
375 | char *data; | | 379 | char *data; |
376 | | | 380 | |
377 | #define MINUSNUL(x) ((x) > 0 ? (x) - (flags & F_NO_NUL ? 0 : 1) : 0) | | 381 | #define MINUSNUL(x) ((x) > 0 ? (x) - (flags & F_NO_NUL ? 0 : 1) : 0) |
378 | | | 382 | |
379 | if (flags & F_SHOW_KEY) { | | 383 | if (flags & F_SHOW_KEY) { |
380 | if (flags & F_ENCODE_KEY) { | | 384 | if (flags & F_ENCODE_KEY) { |
381 | len = encode_data(MINUSNUL(key->size), | | 385 | len = encode_data(MINUSNUL(key->size), |
382 | (char *)key->data, &data); | | 386 | (char *)key->data, &data); |
383 | } else { | | 387 | } else { |
384 | len = (int)MINUSNUL(key->size); | | 388 | len = (int)MINUSNUL(key->size); |
385 | data = (char *)key->data; | | 389 | data = (char *)key->data; |
386 | } | | 390 | } |
387 | printf("%.*s", len, data); | | 391 | printf("%.*s", len, data); |
388 | } | | 392 | } |
389 | if ((flags & F_SHOW_KEY) && (flags & F_SHOW_VALUE)) | | 393 | if ((flags & F_SHOW_KEY) && (flags & F_SHOW_VALUE)) |
390 | printf("%s", outputsep); | | 394 | printf("%s", outputsep); |
391 | if (flags & F_SHOW_VALUE) { | | 395 | if (flags & F_SHOW_VALUE) { |
392 | if (flags & F_ENCODE_VAL) { | | 396 | if (flags & F_ENCODE_VAL) { |
393 | len = encode_data(MINUSNUL(val->size), | | 397 | len = encode_data(MINUSNUL(val->size), |
394 | (char *)val->data, &data); | | 398 | (char *)val->data, &data); |
395 | } else { | | 399 | } else { |
396 | len = (int)MINUSNUL(val->size); | | 400 | len = (int)MINUSNUL(val->size); |
397 | data = (char *)val->data; | | 401 | data = (char *)val->data; |
398 | } | | 402 | } |
399 | printf("%.*s", len, data); | | 403 | printf("%.*s", len, data); |
400 | } | | 404 | } |
401 | printf("\n"); | | 405 | printf("\n"); |
402 | } | | 406 | } |
403 | | | 407 | |
404 | int | | 408 | int |
405 | db_dump(void) | | 409 | db_dump(void) |
406 | { | | 410 | { |
407 | DBT key, val; | | 411 | DBT key, val; |
408 | int rv; | | 412 | int rv; |
409 | | | 413 | |
410 | while ((rv = db->seq(db, &key, &val, R_NEXT)) == 0) | | 414 | while ((rv = db->seq(db, &key, &val, R_NEXT)) == 0) |
411 | db_print(&key, &val); | | 415 | db_print(&key, &val); |
412 | if (rv == -1) | | 416 | if (rv == -1) |
413 | warn("Error dumping database"); | | 417 | warn("Error dumping database"); |
414 | return (rv == 1 ? 0 : 1); | | 418 | return (rv == 1 ? 0 : 1); |
415 | } | | 419 | } |
416 | | | 420 | |
417 | static void | | 421 | static void |
418 | db_makekey(DBT *key, char *keystr, int downcase, int decode) | | 422 | db_makekey(DBT *key, char *keystr, int downcase, int decode) |
419 | { | | 423 | { |
420 | char *p, *ks; | | 424 | char *p, *ks; |
421 | int klen; | | 425 | int klen; |
422 | | | 426 | |
423 | memset(key, 0, sizeof(*key)); | | 427 | memset(key, 0, sizeof(*key)); |
424 | if (decode) { | | 428 | if (decode) { |
425 | if ((klen = decode_data(keystr, &ks)) == -1) | | 429 | if ((klen = decode_data(keystr, &ks)) == -1) |
426 | errx(1, "Invalid escape sequence in `%s'", keystr); | | 430 | errx(1, "Invalid escape sequence in `%s'", keystr); |
427 | } else { | | 431 | } else { |
428 | klen = strlen(keystr); | | 432 | klen = strlen(keystr); |
429 | ks = keystr; | | 433 | ks = keystr; |
430 | } | | 434 | } |
431 | key->data = ks; | | 435 | key->data = ks; |
432 | key->size = klen + (flags & F_NO_NUL ? 0 : 1); | | 436 | key->size = klen + (flags & F_NO_NUL ? 0 : 1); |
433 | if (downcase && (flags & F_IGNORECASE)) { | | 437 | if (downcase && (flags & F_IGNORECASE)) { |
434 | for (p = ks; *p; p++) | | 438 | for (p = ks; *p; p++) |
435 | if (isupper((int)*p)) | | 439 | if (isupper((int)*p)) |
436 | *p = tolower((int)*p); | | 440 | *p = tolower((int)*p); |
437 | } | | 441 | } |
438 | } | | 442 | } |
439 | | | 443 | |
440 | int | | 444 | int |
441 | db_del(char *keystr) | | 445 | db_del(char *keystr) |
442 | { | | 446 | { |
443 | DBT key; | | 447 | DBT key; |
444 | int r; | | 448 | int r; |
445 | | | 449 | |
446 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); | | 450 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); |
447 | r = db->del(db, &key, 0); | | 451 | r = db->del(db, &key, 0); |
448 | switch (r) { | | 452 | switch (r) { |
449 | case -1: | | 453 | case -1: |
450 | if (! (flags & F_QUIET)) | | 454 | if (! (flags & F_QUIET)) |
451 | warn("Error deleting key `%s'", keystr); | | 455 | warn("Error deleting key `%s'", keystr); |
452 | r = 1; | | 456 | r = 1; |
453 | break; | | 457 | break; |
454 | case 0: | | 458 | case 0: |
455 | if (! (flags & F_QUIET)) | | 459 | if (! (flags & F_QUIET)) |
456 | printf("Deleted key `%s'\n", keystr); | | 460 | printf("Deleted key `%s'\n", keystr); |
457 | break; | | 461 | break; |
458 | case 1: | | 462 | case 1: |
459 | if (! (flags & F_QUIET)) | | 463 | if (! (flags & F_QUIET)) |
460 | warnx("Unknown key `%s'", keystr); | | 464 | warnx("Unknown key `%s'", keystr); |
461 | break; | | 465 | break; |
462 | default: | | 466 | default: |
463 | abort(); | | 467 | abort(); |
464 | } | | 468 | } |
465 | if (flags & F_DECODE_KEY) | | 469 | if (flags & F_DECODE_KEY) |
466 | free(key.data); | | 470 | free(key.data); |
467 | return (r); | | 471 | return (r); |
468 | } | | 472 | } |
469 | | | 473 | |
470 | int | | 474 | int |
471 | db_get(char *keystr) | | 475 | db_get(char *keystr) |
472 | { | | 476 | { |
473 | DBT key, val; | | 477 | DBT key, val; |
474 | char *wantkey; | | 478 | char *wantkey; |
475 | int r, found; | | 479 | int r, found; |
476 | u_int seqflags; | | 480 | u_int seqflags; |
477 | | | 481 | |
478 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); | | 482 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); |
479 | wantkey = strdup(key.data); | | 483 | wantkey = strdup(key.data); |
480 | if (wantkey == NULL) | | 484 | if (wantkey == NULL) |
481 | err(1, "Cannot allocate key buffer"); | | 485 | err(1, "Cannot allocate key buffer"); |
482 | | | 486 | |
483 | found = 0; | | 487 | found = 0; |
484 | seqflags = R_CURSOR; | | 488 | seqflags = R_CURSOR; |
485 | while ((r = db->seq(db, &key, &val, seqflags)) == 0) { | | 489 | while ((r = db->seq(db, &key, &val, seqflags)) == 0) { |
486 | if (strcmp((char *)key.data, wantkey) != 0) { | | 490 | if (strcmp((char *)key.data, wantkey) != 0) { |
487 | r = 1; | | 491 | r = 1; |
488 | break; | | 492 | break; |
489 | } | | 493 | } |
490 | seqflags = R_NEXT; | | 494 | seqflags = R_NEXT; |
491 | found++; | | 495 | found++; |
492 | db_print(&key, &val); | | 496 | db_print(&key, &val); |
493 | if (! (flags & F_DUPLICATES)) | | 497 | if (! (flags & F_DUPLICATES)) |
494 | break; | | 498 | break; |
495 | } | | 499 | } |
496 | | | 500 | |
497 | switch (r) { | | 501 | switch (r) { |
498 | case -1: | | 502 | case -1: |
499 | warn("Error reading key `%s'", keystr); | | 503 | warn("Error reading key `%s'", keystr); |
500 | r = 1; | | 504 | r = 1; |
501 | break; | | 505 | break; |
502 | case 0: | | 506 | case 0: |
503 | break; | | 507 | break; |
504 | case 1: | | 508 | case 1: |
505 | if (found) { | | 509 | if (found) { |
506 | r = 0; | | 510 | r = 0; |
507 | break; | | 511 | break; |
508 | } | | 512 | } |
509 | if (! (flags & F_QUIET)) { | | 513 | if (! (flags & F_QUIET)) { |
510 | warnx("Unknown key `%s'", keystr); | | 514 | warnx("Unknown key `%s'", keystr); |
511 | } | | 515 | } |
512 | break; | | 516 | break; |
513 | default: | | 517 | default: |
514 | abort(); | | 518 | abort(); |
515 | } | | 519 | } |
516 | if (flags & F_DECODE_KEY) | | 520 | if (flags & F_DECODE_KEY) |
517 | free(key.data); | | 521 | free(key.data); |
518 | free(wantkey); | | 522 | free(wantkey); |
519 | return (r); | | 523 | return (r); |
520 | } | | 524 | } |
521 | | | 525 | |
522 | int | | 526 | int |
523 | db_put(char *keystr, char *valstr) | | 527 | db_put(char *keystr, char *valstr) |
524 | { | | 528 | { |
525 | DBT key, val; | | 529 | DBT key, val; |
526 | int r = 0; | | 530 | int r = 0; |
527 | | | 531 | |
528 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); | | 532 | db_makekey(&key, keystr, 1, (flags & F_DECODE_KEY ? 1 : 0)); |
529 | db_makekey(&val, valstr, 0, (flags & F_DECODE_VAL ? 1 : 0)); | | 533 | db_makekey(&val, valstr, 0, (flags & F_DECODE_VAL ? 1 : 0)); |
530 | r = db->put(db, &key, &val, (flags & F_REPLACE) ? 0 : R_NOOVERWRITE); | | 534 | r = db->put(db, &key, &val, (flags & F_REPLACE) ? 0 : R_NOOVERWRITE); |
531 | switch (r) { | | 535 | switch (r) { |
532 | case -1: | | 536 | case -1: |
533 | warn("Error writing key `%s'", keystr); | | 537 | warn("Error writing key `%s'", keystr); |
534 | r = 1; | | 538 | r = 1; |
535 | break; | | 539 | break; |
536 | case 0: | | 540 | case 0: |
537 | if (! (flags & F_QUIET)) | | 541 | if (! (flags & F_QUIET)) |
538 | printf("Added key `%s'\n", keystr); | | 542 | printf("Added key `%s'\n", keystr); |
539 | break; | | 543 | break; |
540 | case 1: | | 544 | case 1: |
541 | if (! (flags & F_QUIET)) | | 545 | if (! (flags & F_QUIET)) |
542 | warnx("Key `%s' already exists", keystr); | | 546 | warnx("Key `%s' already exists", keystr); |
543 | break; | | 547 | break; |
544 | default: | | 548 | default: |
545 | abort(); | | 549 | abort(); |
546 | } | | 550 | } |
547 | if (flags & F_DECODE_KEY) | | 551 | if (flags & F_DECODE_KEY) |
548 | free(key.data); | | 552 | free(key.data); |
549 | if (flags & F_DECODE_VAL) | | 553 | if (flags & F_DECODE_VAL) |
550 | free(val.data); | | 554 | free(val.data); |
551 | return (r); | | 555 | return (r); |
552 | } | | 556 | } |
553 | | | 557 | |
554 | int | | 558 | int |
555 | parseline(FILE *fp, const char *sep, char **kp, char **vp) | | 559 | parseline(FILE *fp, const char *sep, char **kp, char **vp) |
556 | { | | 560 | { |
557 | size_t len; | | 561 | size_t len; |
558 | char *key, *val; | | 562 | char *key, *val; |
559 | | | 563 | |
560 | key = fgetln(fp, &len); | | 564 | key = fgetln(fp, &len); |
561 | if (key == NULL) /* end of file, or error */ | | 565 | if (key == NULL) /* end of file, or error */ |
562 | return (0); | | 566 | return (0); |
563 | | | 567 | |
564 | if (key[len-1] == '\n') /* check for \n at EOL */ | | 568 | if (key[len-1] == '\n') /* check for \n at EOL */ |
565 | key[--len] = '\0'; | | 569 | key[--len] = '\0'; |
566 | else | | 570 | else |
567 | return (0); | | 571 | return (0); |
568 | | | 572 | |
569 | *kp = key; | | 573 | *kp = key; |
570 | if (vp == NULL) /* don't split if don't want value */ | | 574 | if (vp == NULL) /* don't split if don't want value */ |
571 | return (1); | | 575 | return (1); |
572 | if ((val = strstr(key, sep)) == NULL) | | 576 | if ((val = strstr(key, sep)) == NULL) |
573 | val = key + len; | | 577 | val = key + len; |
574 | else { | | 578 | else { |
575 | *val = '\0'; | | 579 | *val = '\0'; |
576 | val += strlen(sep); | | 580 | val += strlen(sep); |
577 | } | | 581 | } |
578 | *vp = val; | | 582 | *vp = val; |
579 | return (1); | | 583 | return (1); |
580 | } | | 584 | } |
581 | | | 585 | |
582 | int | | 586 | int |
583 | encode_data(size_t len, char *data, char **edata) | | 587 | encode_data(size_t len, char *data, char **edata) |
584 | { | | 588 | { |
585 | static char *buf = NULL; | | 589 | static char *buf = NULL; |
586 | char *nbuf; | | 590 | char *nbuf; |
587 | static size_t buflen = 0; | | 591 | static size_t buflen = 0; |
588 | size_t elen; | | 592 | size_t elen; |
589 | | | 593 | |
590 | elen = 1 + (len * 4); | | 594 | elen = 1 + (len * 4); |
591 | if (elen > buflen) { | | 595 | if (elen > buflen) { |
592 | if ((nbuf = realloc(buf, elen)) == NULL) | | 596 | if ((nbuf = realloc(buf, elen)) == NULL) |
593 | err(1, "Cannot allocate encoding buffer"); | | 597 | err(1, "Cannot allocate encoding buffer"); |
594 | buf = nbuf; | | 598 | buf = nbuf; |
595 | buflen = elen; | | 599 | buflen = elen; |
596 | } | | 600 | } |
597 | *edata = buf; | | 601 | *edata = buf; |
598 | if (extra_echars) { | | 602 | if (extra_echars) { |
599 | return (strsvisx(buf, data, len, visflags, extra_echars)); | | 603 | return (strsvisx(buf, data, len, visflags, extra_echars)); |
600 | } else { | | 604 | } else { |
601 | return (strvisx(buf, data, len, visflags)); | | 605 | return (strvisx(buf, data, len, visflags)); |
602 | } | | 606 | } |
603 | } | | 607 | } |
604 | | | 608 | |
605 | int | | 609 | int |
606 | decode_data(char *data, char **ddata) | | 610 | decode_data(char *data, char **ddata) |
607 | { | | 611 | { |
608 | char *buf; | | 612 | char *buf; |
609 | | | 613 | |
610 | if ((buf = malloc(strlen(data) + 1)) == NULL) | | 614 | if ((buf = malloc(strlen(data) + 1)) == NULL) |
611 | err(1, "Cannot allocate decoding buffer"); | | 615 | err(1, "Cannot allocate decoding buffer"); |
612 | *ddata = buf; | | 616 | *ddata = buf; |
613 | return (strunvisx(buf, data, (visflags & VIS_HTTPSTYLE))); | | 617 | return (strunvisx(buf, data, (visflags & VIS_HTTPSTYLE))); |
614 | } | | 618 | } |
615 | | | 619 | |
616 | void | | 620 | void |
617 | parse_encode_decode_arg(const char *arg, int encode) | | 621 | parse_encode_decode_arg(const char *arg, int encode) |
618 | { | | 622 | { |
619 | if (! arg[0] || arg[1]) | | 623 | if (! arg[0] || arg[1]) |
620 | return; | | 624 | return; |
621 | if (arg[0] == 'k' || arg[0] == 'b') { | | 625 | if (arg[0] == 'k' || arg[0] == 'b') { |
622 | if (encode) | | 626 | if (encode) |
623 | flags |= F_ENCODE_KEY; | | 627 | flags |= F_ENCODE_KEY; |
624 | else | | 628 | else |
625 | flags |= F_DECODE_KEY; | | 629 | flags |= F_DECODE_KEY; |
626 | } | | 630 | } |
627 | if (arg[0] == 'v' || arg[0] == 'b') { | | 631 | if (arg[0] == 'v' || arg[0] == 'b') { |
628 | if (encode) | | 632 | if (encode) |
629 | flags |= F_ENCODE_VAL; | | 633 | flags |= F_ENCODE_VAL; |
630 | else | | 634 | else |
631 | flags |= F_DECODE_VAL; | | 635 | flags |= F_DECODE_VAL; |
632 | } | | 636 | } |
633 | return; | | 637 | return; |
634 | } | | 638 | } |
635 | | | 639 | |
636 | int | | 640 | int |
637 | parse_encode_option(char **arg) | | 641 | parse_encode_option(char **arg) |
638 | { | | 642 | { |
639 | int r = 0; | | 643 | int r = 0; |
640 | int encmask = ~(VIS_CSTYLE | VIS_HTTPSTYLE | VIS_OCTAL); | | 644 | int encmask = ~(VIS_CSTYLE | VIS_HTTPSTYLE | VIS_OCTAL); |
641 | | | 645 | |
642 | for(; **arg; (*arg)++) { | | 646 | for(; **arg; (*arg)++) { |
643 | switch (**arg) { | | 647 | switch (**arg) { |
644 | case 'b': | | 648 | case 'b': |
645 | r |= VIS_NOSLASH; | | 649 | r |= VIS_NOSLASH; |
646 | break; | | 650 | break; |
647 | case 'c': | | 651 | case 'c': |
648 | r &= encmask; | | 652 | r &= encmask; |
649 | r |= VIS_CSTYLE; | | 653 | r |= VIS_CSTYLE; |
650 | break; | | 654 | break; |
651 | case 'h': | | 655 | case 'h': |
652 | r &= encmask; | | 656 | r &= encmask; |
653 | r |= VIS_HTTPSTYLE; | | 657 | r |= VIS_HTTPSTYLE; |
654 | break; | | 658 | break; |
655 | case 'o': | | 659 | case 'o': |
656 | r &= encmask; | | 660 | r &= encmask; |
657 | r |= VIS_OCTAL; | | 661 | r |= VIS_OCTAL; |
658 | break; | | 662 | break; |
659 | case 's': | | 663 | case 's': |
660 | r |= VIS_SAFE; | | 664 | r |= VIS_SAFE; |
661 | break; | | 665 | break; |
662 | case 't': | | 666 | case 't': |
663 | r |= VIS_TAB; | | 667 | r |= VIS_TAB; |
664 | break; | | 668 | break; |
665 | case 'w': | | 669 | case 'w': |
666 | r |= VIS_WHITE; | | 670 | r |= VIS_WHITE; |
667 | break; | | 671 | break; |
668 | default: | | 672 | default: |
669 | return (0); | | 673 | return (0); |
670 | break; | | 674 | break; |
671 | } | | 675 | } |
672 | } | | 676 | } |
673 | return (r); | | 677 | return (r); |
674 | } | | 678 | } |
675 | | | 679 | |
676 | void | | 680 | void |
677 | usage(void) | | 681 | usage(void) |
678 | { | | 682 | { |
679 | const char *p = getprogname(); | | 683 | const char *p = getprogname(); |
680 | | | 684 | |
681 | fprintf(stderr, | | 685 | fprintf(stderr, |
682 | "usage: %s [-KiNqV] [-E endian] [-f infile] [-O outsep] [-S visitem]\n" | | 686 | "usage: %s [-KiNqV] [-E endian] [-f infile] [-O outsep] [-S visitem]\n" |
683 | " [-T visspec] [-X extravis] type dbfile [key [...]]\n" | | 687 | " [-T visspec] [-X extravis] type dbfile [key [...]]\n" |
684 | " %s -d [-iNq] [-E endian] [-f infile] [-T visspec] [-U unvisitem]\n" | | 688 | " %s -d [-iNq] [-E endian] [-f infile] [-T visspec] [-U unvisitem]\n" |
685 | " type dbfile [key [...]]\n" | | 689 | " type dbfile [key [...]]\n" |
686 | " %s -w [-CDiNqR] [-E endian] [-F isep] [-f infile] [-m mode]\n" | | 690 | " %s -w [-CDiNqR] [-E endian] [-F isep] [-f infile] [-m mode]\n" |
687 | " [-P pagesize] [-T visspec] [-U unvisitem]\n" | | 691 | " [-P pagesize] [-T visspec] [-U unvisitem]\n" |
688 | " type dbfile [key value [...]]\n" | | 692 | " type dbfile [key value [...]]\n" |
689 | ,p ,p ,p ); | | 693 | ,p ,p ,p ); |
690 | fprintf(stderr, | | 694 | fprintf(stderr, |
691 | "Supported modes:\n" | | 695 | "Supported modes:\n" |
692 | " read keys [default]\n" | | 696 | " read keys [default]\n" |
693 | " -d delete keys\n" | | 697 | " -d delete keys\n" |
694 | " -w write (add) keys/values\n" | | 698 | " -w write (add) keys/values\n" |
695 | "Supported options:\n" | | 699 | "Supported options:\n" |
696 | " -C create empty (truncated) database\n" | | 700 | " -C create empty (truncated) database\n" |
697 | " -D allow duplicates\n" | | 701 | " -D allow duplicates\n" |
698 | " -E endian database endian: `B'ig, `L'ittle, `H'ost [default: H]\n" | | 702 | " -E endian database endian: `B'ig, `L'ittle, `H'ost [default: H]\n" |
699 | " -F isep input field separator string [default: a space]\n" | | 703 | " -F isep input field separator string [default: a space]\n" |
700 | " -f infile file of keys (read|delete) or keys/vals (write)\n" | | 704 | " -f infile file of keys (read|delete) or keys/vals (write)\n" |
701 | " -i ignore case of key by converting to lower case\n" | | 705 | " -i ignore case of key by converting to lower case\n" |
702 | " -K print key\n" | | 706 | " -K print key\n" |
703 | " -m mode mode of created database [default: 0644]\n" | | 707 | " -m mode mode of created database [default: 0644]\n" |
704 | " -N don't NUL terminate key\n" | | 708 | " -N don't NUL terminate key\n" |
705 | " -O outsep output field separator string [default: a tab]\n" | | 709 | " -O outsep output field separator string [default: a tab]\n" |
706 | " -P pagesize database page size [default: 4096]\n" | | 710 | " -P pagesize database page size [default: 4096]\n" |
707 | " -q quiet operation (missing keys aren't errors)\n" | | 711 | " -q quiet operation (missing keys aren't errors)\n" |
708 | " -R replace existing keys\n" | | 712 | " -R replace existing keys\n" |
709 | " -S visitem items to strvis(3) encode: 'k'ey, 'v'alue, 'b'oth\n" | | 713 | " -S visitem items to strvis(3) encode: 'k'ey, 'v'alue, 'b'oth\n" |
710 | " -T visspec options to control -S and -U; like vis(1) options\n" | | 714 | " -T visspec options to control -S and -U; like vis(1) options\n" |
711 | " -U unvisitem items to strunvis(3) decode: 'k'ey, 'v'alue, 'b'oth\n" | | 715 | " -U unvisitem items to strunvis(3) decode: 'k'ey, 'v'alue, 'b'oth\n" |
712 | " -V print value\n" | | 716 | " -V print value\n" |
713 | " -X extravis extra characters to encode with -S\n" | | 717 | " -X extravis extra characters to encode with -S\n" |
714 | ); | | 718 | ); |
715 | exit(1); | | 719 | exit(1); |
716 | } | | 720 | } |