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