Line | Count | Source (jump to first uncovered line) |
1 | | /* This file is part of GDBM, the GNU data base manager. |
2 | | Copyright (C) 1990-2025 Free Software Foundation, Inc. |
3 | | |
4 | | GDBM is free software; you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation; either version 3, or (at your option) |
7 | | any later version. |
8 | | |
9 | | GDBM is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with GDBM. If not, see <http://www.gnu.org/licenses/>. */ |
16 | | |
17 | | #include "gdbmtool.h" |
18 | | |
19 | | #define VARF_DFL 0x00 /* Default flags -- everything disabled */ |
20 | 456k | #define VARF_SET 0x01 /* Variable is set */ |
21 | 68.1k | #define VARF_INIT 0x02 /* Variable is initialized */ |
22 | 5.45k | #define VARF_PROT 0x04 /* Variable is protected, i.e. cannot be unset */ |
23 | 0 | #define VARF_OCTAL 0x08 /* For integer variables -- use octal base */ |
24 | | |
25 | 172k | #define VAR_IS_SET(v) ((v)->flags & VARF_SET) |
26 | | |
27 | | union value |
28 | | { |
29 | | char *string; |
30 | | int b; |
31 | | int num; |
32 | | }; |
33 | | |
34 | | struct variable |
35 | | { |
36 | | char *name; |
37 | | int type; |
38 | | int flags; |
39 | | union value init; |
40 | | union value v; |
41 | | void *data; |
42 | | int (*sethook) (struct variable *, union value *); |
43 | | int (*typeconv) (struct variable *, int, void **); |
44 | | void (*freehook) (void *); |
45 | | }; |
46 | | |
47 | | static int open_sethook (struct variable *, union value *); |
48 | | static int open_typeconv (struct variable *var, int type, void **retptr); |
49 | | static int format_sethook (struct variable *, union value *); |
50 | | static int format_typeconv (struct variable *var, int type, void **retptr); |
51 | | static int fd_sethook (struct variable *, union value *); |
52 | | static int centfree_sethook (struct variable *var, union value *v); |
53 | | static int coalesce_sethook (struct variable *var, union value *v); |
54 | | static int cachesize_sethook (struct variable *var, union value *v); |
55 | | static int errormask_sethook (struct variable *var, union value *v); |
56 | | static int errormask_typeconv (struct variable *var, int type, void **retptr); |
57 | | static void errormask_freehook (void *); |
58 | | static int errorexit_sethook (struct variable *var, union value *v); |
59 | | |
60 | | static struct variable vartab[] = { |
61 | | /* Top-level prompt */ |
62 | | { |
63 | | .name = "ps1", |
64 | | .type = VART_STRING, |
65 | | .flags = VARF_INIT, |
66 | | .init = { .string = "%p>%_" } |
67 | | }, |
68 | | /* Second-level prompt (used within "def" block) */ |
69 | | { |
70 | | .name = "ps2", |
71 | | .type = VART_STRING, |
72 | | .flags = VARF_INIT, |
73 | | .init = { .string = "%_>%_" } |
74 | | }, |
75 | | /* This delimits array members */ |
76 | | { |
77 | | .name = "delim1", |
78 | | .type = VART_STRING, |
79 | | .flags = VARF_INIT|VARF_PROT, |
80 | | .init = { .string = "," } |
81 | | }, |
82 | | /* This delimits structure members */ |
83 | | { |
84 | | .name = "delim2", |
85 | | .type = VART_STRING, |
86 | | .flags = VARF_INIT|VARF_PROT, |
87 | | .init = { .string = "," } |
88 | | }, |
89 | | { |
90 | | .name = "confirm", |
91 | | .type = VART_BOOL, |
92 | | .flags = VARF_INIT, |
93 | | .init = { .b = 1 } |
94 | | }, |
95 | | { |
96 | | .name = "cachesize", |
97 | | .type = VART_INT, |
98 | | .flags = VARF_DFL, |
99 | | .sethook = cachesize_sethook |
100 | | }, |
101 | | { |
102 | | .name = "blocksize", |
103 | | .type = VART_INT, |
104 | | .flags = VARF_DFL |
105 | | }, |
106 | | { |
107 | | .name = "open", |
108 | | .type = VART_STRING, |
109 | | .flags = VARF_DFL, |
110 | | .sethook = open_sethook, |
111 | | .typeconv = open_typeconv |
112 | | }, |
113 | | { |
114 | | .name = "lock", |
115 | | .type = VART_BOOL, |
116 | | .flags = VARF_INIT, |
117 | | .init = { .b = 1 } |
118 | | }, |
119 | | { |
120 | | .name = "mmap", |
121 | | .type = VART_BOOL, |
122 | | .flags = VARF_INIT, |
123 | | .init = { .b = 1 } |
124 | | }, |
125 | | { |
126 | | .name = "sync", |
127 | | .type = VART_BOOL, |
128 | | .flags = VARF_INIT, |
129 | | .init = { .b = 0 } |
130 | | }, |
131 | | { |
132 | | .name = "coalesce", |
133 | | .type = VART_BOOL, |
134 | | .flags = VARF_INIT, |
135 | | .init = { .b = 0 }, |
136 | | .sethook = coalesce_sethook |
137 | | }, |
138 | | { |
139 | | .name = "centfree", |
140 | | .type = VART_BOOL, |
141 | | .flags = VARF_INIT, |
142 | | .init = { .b = 0 }, |
143 | | .sethook = centfree_sethook |
144 | | }, |
145 | | { |
146 | | .name = "filemode", |
147 | | .type = VART_INT, |
148 | | .flags = VARF_INIT|VARF_OCTAL|VARF_PROT, |
149 | | .init = { .num = 0644 } |
150 | | }, |
151 | | { |
152 | | .name = "format", |
153 | | .type = VART_STRING, |
154 | | .flags = VARF_INIT, |
155 | | .init = { .string = "standard" }, |
156 | | .sethook = format_sethook, |
157 | | .typeconv = format_typeconv |
158 | | }, |
159 | | { |
160 | | .name = "pager", |
161 | | .type = VART_STRING, |
162 | | .flags = VARF_DFL |
163 | | }, |
164 | | { |
165 | | .name = "quiet", |
166 | | .type = VART_BOOL, |
167 | | .flags = VARF_DFL |
168 | | }, |
169 | | { |
170 | | .name = "filename", |
171 | | .type = VART_STRING, |
172 | | .flags = VARF_INIT|VARF_PROT, |
173 | | { .string = GDBMTOOL_DEFFILE } |
174 | | }, |
175 | | { |
176 | | .name = "fd", |
177 | | .type = VART_INT, |
178 | | .flags = VARF_DFL, |
179 | | .sethook = fd_sethook |
180 | | }, |
181 | | { |
182 | | .name = "errorexit", |
183 | | .type = VART_STRING, |
184 | | .sethook = errorexit_sethook, |
185 | | .typeconv = errormask_typeconv, |
186 | | .freehook = errormask_freehook |
187 | | }, |
188 | | { |
189 | | .name = "errormask", |
190 | | .type = VART_STRING, |
191 | | .sethook = errormask_sethook, |
192 | | .typeconv = errormask_typeconv, |
193 | | .freehook = errormask_freehook |
194 | | }, |
195 | | { |
196 | | .name = "timing", |
197 | | .type = VART_BOOL |
198 | | }, |
199 | | { |
200 | | .name = "trace", |
201 | | .type = VART_BOOL |
202 | | }, |
203 | | { NULL } |
204 | | }; |
205 | | |
206 | | static struct variable * |
207 | | varfind (const char *name) |
208 | 245k | { |
209 | 245k | struct variable *vp; |
210 | | |
211 | 4.30M | for (vp = vartab; vp->name; vp++) |
212 | 4.29M | if (strcmp (vp->name, name) == 0) |
213 | 243k | return vp; |
214 | | |
215 | 2.20k | return NULL; |
216 | 245k | } |
217 | | |
218 | | typedef int (*setvar_t) (union value *, void *, int); |
219 | | |
220 | | static int |
221 | | s2s (union value *vp, void *val, int flags) |
222 | 24.9k | { |
223 | 24.9k | vp->string = estrdup (val); |
224 | 24.9k | return VAR_OK; |
225 | 24.9k | } |
226 | | |
227 | | static int |
228 | | b2s (union value *vp, void *val, int flags) |
229 | 7.66k | { |
230 | 7.66k | vp->string = estrdup (*(int*)val ? "true" : "false"); |
231 | 7.66k | return VAR_OK; |
232 | 7.66k | } |
233 | | |
234 | | static int |
235 | | i2s (union value *vp, void *val, int flags) |
236 | 0 | { |
237 | 0 | char buf[128]; |
238 | 0 | snprintf (buf, sizeof buf, "%d", *(int*)val); |
239 | 0 | vp->string = estrdup (buf); |
240 | 0 | return VAR_OK; |
241 | 0 | } |
242 | | |
243 | | static int |
244 | | s2b (union value *vp, void *val, int flags) |
245 | 0 | { |
246 | 0 | static char *trueval[] = { "on", "true", "yes", NULL }; |
247 | 0 | static char *falseval[] = { "off", "false", "no", NULL }; |
248 | 0 | int i; |
249 | 0 | unsigned long n; |
250 | 0 | char *p; |
251 | |
|
252 | 0 | for (i = 0; trueval[i]; i++) |
253 | 0 | if (strcasecmp (trueval[i], val) == 0) |
254 | 0 | { |
255 | 0 | vp->b = 1; |
256 | 0 | return VAR_OK; |
257 | 0 | } |
258 | | |
259 | 0 | for (i = 0; falseval[i]; i++) |
260 | 0 | if (strcasecmp (falseval[i], val) == 0) |
261 | 0 | { |
262 | 0 | vp->b = 0; |
263 | 0 | return VAR_OK; |
264 | 0 | } |
265 | | |
266 | 0 | n = strtoul (val, &p, 0); |
267 | 0 | if (*p) |
268 | 0 | return VAR_ERR_BADTYPE; |
269 | 0 | vp->b = !!n; |
270 | 0 | return VAR_OK; |
271 | 0 | } |
272 | | |
273 | | static int |
274 | | s2i (union value *vp, void *val, int flags) |
275 | 0 | { |
276 | 0 | char *p; |
277 | 0 | int n = strtoul (val, &p, (flags & VARF_OCTAL) ? 8 : 10); |
278 | |
|
279 | 0 | if (*p) |
280 | 0 | return VAR_ERR_BADTYPE; |
281 | | |
282 | 0 | vp->num = n; |
283 | 0 | return VAR_OK; |
284 | 0 | } |
285 | | |
286 | | static int |
287 | | b2b (union value *vp, void *val, int flags) |
288 | 23.8k | { |
289 | 23.8k | vp->b = !!*(int*)val; |
290 | 23.8k | return VAR_OK; |
291 | 23.8k | } |
292 | | |
293 | | static int |
294 | | b2i (union value *vp, void *val, int flags) |
295 | 0 | { |
296 | 0 | vp->num = *(int*)val; |
297 | 0 | return VAR_OK; |
298 | 0 | } |
299 | | |
300 | | static int |
301 | | i2i (union value *vp, void *val, int flags) |
302 | 8.69k | { |
303 | 8.69k | vp->num = *(int*)val; |
304 | 8.69k | return VAR_OK; |
305 | 8.69k | } |
306 | | |
307 | | static int |
308 | | i2b (union value *vp, void *val, int flags) |
309 | 0 | { |
310 | 0 | vp->b = *(int*)val; |
311 | 0 | return VAR_OK; |
312 | 0 | } |
313 | | |
314 | | static setvar_t setvar[3][3] = { |
315 | | /* s b i */ |
316 | | /* s */ { s2s, b2s, i2s }, |
317 | | /* b */ { s2b, b2b, i2b }, |
318 | | /* i */ { s2i, b2i, i2i } |
319 | | }; |
320 | | |
321 | | int |
322 | | variable_set (const char *name, int type, void *val) |
323 | 70.6k | { |
324 | 70.6k | struct variable *vp = varfind (name); |
325 | 70.6k | int rc; |
326 | 70.6k | union value v, *valp; |
327 | | |
328 | 70.6k | if (!vp) |
329 | 2.20k | return VAR_ERR_NOTDEF; |
330 | | |
331 | 68.4k | if (val) |
332 | 65.1k | { |
333 | 65.1k | memset (&v, 0, sizeof (v)); |
334 | 65.1k | rc = setvar[vp->type][type] (&v, val, vp->flags); |
335 | 65.1k | if (rc) |
336 | 0 | return rc; |
337 | 65.1k | valp = &v; |
338 | 65.1k | } |
339 | 3.24k | else |
340 | 3.24k | { |
341 | 3.24k | if (vp->flags & VARF_PROT) |
342 | 0 | return VAR_ERR_BADVALUE; |
343 | 3.24k | valp = NULL; |
344 | 3.24k | } |
345 | | |
346 | 68.4k | if (vp->sethook && (rc = vp->sethook (vp, valp)) != VAR_OK) |
347 | 4.31k | return rc; |
348 | | |
349 | 64.1k | if (vp->type == VART_STRING && (vp->flags & VARF_SET)) |
350 | 4.41k | free (vp->v.string); |
351 | | |
352 | 64.1k | if (!val) |
353 | 3.24k | { |
354 | 3.24k | vp->flags &= VARF_SET; |
355 | 3.24k | } |
356 | 60.8k | else |
357 | 60.8k | { |
358 | 60.8k | vp->v = v; |
359 | 60.8k | vp->flags |= VARF_SET; |
360 | 60.8k | } |
361 | | |
362 | 64.1k | return VAR_OK; |
363 | 68.4k | } |
364 | | |
365 | | int |
366 | | variable_unset (const char *name) |
367 | 2.20k | { |
368 | 2.20k | struct variable *vp = varfind (name); |
369 | 2.20k | int rc; |
370 | | |
371 | 2.20k | if (!vp) |
372 | 0 | return VAR_ERR_NOTDEF; |
373 | 2.20k | if (vp->flags & VARF_PROT) |
374 | 0 | return VAR_ERR_BADVALUE; |
375 | | |
376 | 2.20k | if (vp->sethook && (rc = vp->sethook (vp, NULL)) != VAR_OK) |
377 | 0 | return rc; |
378 | | |
379 | 2.20k | if (vp->type == VART_STRING) |
380 | 0 | { |
381 | 0 | free (vp->v.string); |
382 | 0 | vp->v.string = NULL; |
383 | 0 | } |
384 | 2.20k | vp->flags &= ~VARF_SET; |
385 | | |
386 | 2.20k | return VAR_OK; |
387 | 2.20k | } |
388 | | |
389 | | int |
390 | | variable_get (const char *name, int type, void **val) |
391 | 172k | { |
392 | 172k | struct variable *vp = varfind (name); |
393 | | |
394 | 172k | if (!vp) |
395 | 0 | return VAR_ERR_NOTDEF; |
396 | | |
397 | 172k | if (!VAR_IS_SET (vp)) |
398 | 102k | return VAR_ERR_NOTSET; |
399 | | |
400 | 70.2k | if (type != vp->type) |
401 | 43.4k | { |
402 | 43.4k | if (vp->typeconv) |
403 | 43.4k | { |
404 | 43.4k | return vp->typeconv (vp, type, val); |
405 | 43.4k | } |
406 | 0 | else |
407 | 0 | return VAR_ERR_BADTYPE; |
408 | 43.4k | } |
409 | | |
410 | 26.8k | if (val) |
411 | 26.8k | { |
412 | 26.8k | switch (vp->type) |
413 | 26.8k | { |
414 | 6.18k | case VART_STRING: |
415 | 6.18k | *val = vp->v.string; |
416 | 6.18k | break; |
417 | | |
418 | 14.1k | case VART_BOOL: |
419 | 14.1k | *(int*)val = vp->v.b; |
420 | 14.1k | break; |
421 | | |
422 | 6.49k | case VART_INT: |
423 | 6.49k | *(int*)val = vp->v.num; |
424 | 6.49k | break; |
425 | 26.8k | } |
426 | 26.8k | } |
427 | | |
428 | 26.8k | return VAR_OK; |
429 | 26.8k | } |
430 | | |
431 | | static int |
432 | | varcmp (const void *a, const void *b) |
433 | 0 | { |
434 | 0 | return strcmp (((struct variable const *)a)->name, |
435 | 0 | ((struct variable const *)b)->name); |
436 | 0 | } |
437 | | |
438 | | void |
439 | | variable_print_all (FILE *fp) |
440 | 0 | { |
441 | 0 | struct variable *vp; |
442 | 0 | char *s; |
443 | 0 | static int sorted; |
444 | |
|
445 | 0 | if (!sorted) |
446 | 0 | { |
447 | 0 | qsort (vartab, ARRAY_SIZE (vartab) - 1, sizeof (vartab[0]), varcmp); |
448 | 0 | sorted = 1; |
449 | 0 | } |
450 | |
|
451 | 0 | for (vp = vartab; vp->name; vp++) |
452 | 0 | { |
453 | 0 | if (!VAR_IS_SET (vp)) |
454 | 0 | { |
455 | 0 | fprintf (fp, "# %s is unset", vp->name); |
456 | 0 | } |
457 | 0 | else |
458 | 0 | { |
459 | 0 | switch (vp->type) |
460 | 0 | { |
461 | 0 | case VART_INT: |
462 | 0 | fprintf (fp, (vp->flags & VARF_OCTAL) ? "%s=%03o" : "%s=%d", |
463 | 0 | vp->name, vp->v.num); |
464 | 0 | break; |
465 | | |
466 | 0 | case VART_BOOL: |
467 | 0 | fprintf (fp, "%s%s", vp->v.b ? "" : "no", vp->name); |
468 | 0 | break; |
469 | | |
470 | 0 | case VART_STRING: |
471 | 0 | fprintf (fp, "%s=\"", vp->name); |
472 | 0 | for (s = vp->v.string; *s; s++) |
473 | 0 | { |
474 | 0 | int c; |
475 | |
|
476 | 0 | if (isprint (*s)) |
477 | 0 | fputc (*s, fp); |
478 | 0 | else if ((c = escape (*s))) |
479 | 0 | fprintf (fp, "\\%c", c); |
480 | 0 | else |
481 | 0 | fprintf (fp, "\\%03o", *s); |
482 | 0 | } |
483 | 0 | fprintf (fp, "\""); |
484 | 0 | } |
485 | 0 | } |
486 | 0 | fputc ('\n', fp); |
487 | 0 | } |
488 | 0 | } |
489 | | |
490 | | int |
491 | | variable_is_set (const char *name) |
492 | 0 | { |
493 | 0 | struct variable *vp = varfind (name); |
494 | |
|
495 | 0 | if (!vp) |
496 | 0 | return 0; |
497 | 0 | return VAR_IS_SET (vp); |
498 | 0 | } |
499 | | |
500 | | int |
501 | | variable_is_true (const char *name) |
502 | 108k | { |
503 | 108k | int n; |
504 | | |
505 | 108k | if (variable_get (name, VART_BOOL, (void **) &n) == VAR_OK) |
506 | 14.1k | return n; |
507 | 94.7k | return 0; |
508 | 108k | } |
509 | | |
510 | | void |
511 | | variables_free (void) |
512 | 3.24k | { |
513 | 3.24k | struct variable *vp; |
514 | | |
515 | 77.9k | for (vp = vartab; vp->name; vp++) |
516 | 74.6k | { |
517 | 74.6k | if (vp->type == VART_STRING && (vp->flags & VARF_SET)) |
518 | 28.1k | free (vp->v.string); |
519 | 74.6k | vp->v.string = NULL; |
520 | 74.6k | if (vp->freehook && vp->data) |
521 | 5.45k | { |
522 | 5.45k | vp->freehook (vp->data); |
523 | 5.45k | vp->data = NULL; |
524 | 5.45k | } |
525 | 74.6k | vp->flags &= ~VARF_SET; |
526 | 74.6k | } |
527 | 3.24k | } |
528 | | |
529 | | void |
530 | | variables_init (void) |
531 | 3.24k | { |
532 | 3.24k | struct variable *vp; |
533 | | |
534 | 77.9k | for (vp = vartab; vp->name; vp++) |
535 | 74.6k | { |
536 | 74.6k | if (!(vp->flags & VARF_SET) && (vp->flags & VARF_INIT)) |
537 | 38.9k | { |
538 | 38.9k | if (vp->type == VART_STRING) |
539 | 16.2k | variable_set (vp->name, vp->type, vp->init.string); |
540 | 22.7k | else |
541 | 22.7k | variable_set (vp->name, vp->type, &vp->init); |
542 | 38.9k | } |
543 | 74.6k | } |
544 | 3.24k | } |
545 | | |
546 | | struct kwtrans |
547 | | { |
548 | | char *s; |
549 | | int t; |
550 | | }; |
551 | | |
552 | | static int |
553 | | string_to_int (char const *s, struct kwtrans *t) |
554 | 6.49k | { |
555 | 6.49k | int i; |
556 | | |
557 | 12.9k | for (i = 0; t[i].s; i++) |
558 | 12.9k | if (strcmp (t[i].s, s) == 0) |
559 | 6.49k | return t[i].t; |
560 | 0 | return -1; |
561 | 6.49k | } |
562 | | |
563 | | #if 0 |
564 | | static char const * |
565 | | int_to_string (int n, struct kwtrans *t) |
566 | | { |
567 | | int i; |
568 | | |
569 | | for (i = 0; t[i].s; i++) |
570 | | if (t[i].t == n) |
571 | | return t[i].s; |
572 | | return NULL; |
573 | | } |
574 | | #endif |
575 | | |
576 | | static struct kwtrans db_open_flags[] = { |
577 | | { "newdb", GDBM_NEWDB }, |
578 | | { "wrcreat", GDBM_WRCREAT }, |
579 | | { "rw", GDBM_WRCREAT }, |
580 | | { "reader", GDBM_READER }, |
581 | | { "readonly", GDBM_READER }, |
582 | | { NULL } |
583 | | }; |
584 | | |
585 | | static int |
586 | | open_sethook (struct variable *var, union value *v) |
587 | 3.24k | { |
588 | 3.24k | int n; |
589 | 3.24k | if (!v) |
590 | 0 | return VAR_ERR_BADVALUE; |
591 | 3.24k | n = string_to_int (v->string, db_open_flags); |
592 | 3.24k | if (n == -1) |
593 | 0 | return VAR_ERR_BADVALUE; |
594 | 3.24k | return VAR_OK; |
595 | 3.24k | } |
596 | | |
597 | | static int |
598 | | open_typeconv (struct variable *var, int type, void **retptr) |
599 | 3.24k | { |
600 | 3.24k | if (type == VART_INT) |
601 | 3.24k | { |
602 | 3.24k | *(int*) retptr = string_to_int (var->v.string, db_open_flags); |
603 | 3.24k | return VAR_OK; |
604 | 3.24k | } |
605 | 0 | return VAR_ERR_BADTYPE; |
606 | 3.24k | } |
607 | | |
608 | | static int |
609 | | format_sethook (struct variable *var, union value *v) |
610 | 3.24k | { |
611 | 3.24k | if (!v) |
612 | 0 | return VAR_OK; |
613 | 3.24k | return _gdbm_str2fmt (v->string) == -1 ? VAR_ERR_BADVALUE : VAR_OK; |
614 | 3.24k | } |
615 | | |
616 | | static int |
617 | | format_typeconv (struct variable *var, int type, void **retptr) |
618 | 3.24k | { |
619 | 3.24k | if (type == VART_INT) |
620 | 3.24k | { |
621 | 3.24k | *(int*) retptr = _gdbm_str2fmt (var->v.string); |
622 | 3.24k | return VAR_OK; |
623 | 3.24k | } |
624 | 0 | return VAR_ERR_BADTYPE; |
625 | 3.24k | } |
626 | | |
627 | | static int |
628 | | fd_sethook (struct variable *var, union value *v) |
629 | 7.66k | { |
630 | 7.66k | if (!v) |
631 | 2.20k | return VAR_OK; |
632 | 5.45k | if (v->num < 0) |
633 | 0 | return VAR_ERR_BADVALUE; |
634 | 5.45k | return VAR_OK; |
635 | 5.45k | } |
636 | | |
637 | | static int |
638 | | cachesize_sethook (struct variable *var, union value *v) |
639 | 0 | { |
640 | 0 | if (!v) |
641 | 0 | return VAR_OK; |
642 | 0 | if (v->num < 0) |
643 | 0 | return VAR_ERR_BADVALUE; |
644 | 0 | return gdbmshell_setopt ("GDBM_SETCACHESIZE", GDBM_SETCACHESIZE, v->num) == 0 |
645 | 0 | ? VAR_OK : VAR_ERR_GDBM; |
646 | 0 | } |
647 | | |
648 | | static int |
649 | | centfree_sethook (struct variable *var, union value *v) |
650 | 5.45k | { |
651 | 5.45k | if (!v) |
652 | 0 | return VAR_OK; |
653 | 5.45k | return gdbmshell_setopt ("GDBM_SETCENTFREE", GDBM_SETCENTFREE, v->b) == 0 |
654 | 5.45k | ? VAR_OK : VAR_ERR_GDBM; |
655 | 5.45k | } |
656 | | |
657 | | static int |
658 | | coalesce_sethook (struct variable *var, union value *v) |
659 | 5.45k | { |
660 | 5.45k | if (!v) |
661 | 0 | return VAR_OK; |
662 | 5.45k | return gdbmshell_setopt ("GDBM_SETCOALESCEBLKS", GDBM_SETCOALESCEBLKS, v->b) == 0 |
663 | 5.45k | ? VAR_OK : VAR_ERR_GDBM; |
664 | 5.45k | } |
665 | | |
666 | | const char * const errname[_GDBM_MAX_ERRNO+1] = { |
667 | | [GDBM_NO_ERROR] = "GDBM_NO_ERROR", |
668 | | [GDBM_MALLOC_ERROR] = "GDBM_MALLOC_ERROR", |
669 | | [GDBM_BLOCK_SIZE_ERROR] = "GDBM_BLOCK_SIZE_ERROR", |
670 | | [GDBM_FILE_OPEN_ERROR] = "GDBM_FILE_OPEN_ERROR", |
671 | | [GDBM_FILE_WRITE_ERROR] = "GDBM_FILE_WRITE_ERROR", |
672 | | [GDBM_FILE_SEEK_ERROR] = "GDBM_FILE_SEEK_ERROR", |
673 | | [GDBM_FILE_READ_ERROR] = "GDBM_FILE_READ_ERROR", |
674 | | [GDBM_BAD_MAGIC_NUMBER] = "GDBM_BAD_MAGIC_NUMBER", |
675 | | [GDBM_EMPTY_DATABASE] = "GDBM_EMPTY_DATABASE", |
676 | | [GDBM_CANT_BE_READER] = "GDBM_CANT_BE_READER", |
677 | | [GDBM_CANT_BE_WRITER] = "GDBM_CANT_BE_WRITER", |
678 | | [GDBM_READER_CANT_DELETE] = "GDBM_READER_CANT_DELETE", |
679 | | [GDBM_READER_CANT_STORE] = "GDBM_READER_CANT_STORE", |
680 | | [GDBM_READER_CANT_REORGANIZE] = "GDBM_READER_CANT_REORGANIZE", |
681 | | [GDBM_UNKNOWN_ERROR] = "GDBM_UNKNOWN_ERROR", |
682 | | [GDBM_ITEM_NOT_FOUND] = "GDBM_ITEM_NOT_FOUND", |
683 | | [GDBM_REORGANIZE_FAILED] = "GDBM_REORGANIZE_FAILED", |
684 | | [GDBM_CANNOT_REPLACE] = "GDBM_CANNOT_REPLACE", |
685 | | [GDBM_MALFORMED_DATA] = "GDBM_MALFORMED_DATA", |
686 | | [GDBM_OPT_ALREADY_SET] = "GDBM_OPT_ALREADY_SET", |
687 | | [GDBM_OPT_BADVAL] = "GDBM_OPT_BADVAL", |
688 | | [GDBM_BYTE_SWAPPED] = "GDBM_BYTE_SWAPPED", |
689 | | [GDBM_BAD_FILE_OFFSET] = "GDBM_BAD_FILE_OFFSET", |
690 | | [GDBM_BAD_OPEN_FLAGS] = "GDBM_BAD_OPEN_FLAGS", |
691 | | [GDBM_FILE_STAT_ERROR] = "GDBM_FILE_STAT_ERROR", |
692 | | [GDBM_FILE_EOF] = "GDBM_FILE_EOF", |
693 | | [GDBM_NO_DBNAME] = "GDBM_NO_DBNAME", |
694 | | [GDBM_ERR_FILE_OWNER] = "GDBM_ERR_FILE_OWNER", |
695 | | [GDBM_ERR_FILE_MODE] = "GDBM_ERR_FILE_MODE", |
696 | | [GDBM_NEED_RECOVERY] = "GDBM_NEED_RECOVERY", |
697 | | [GDBM_BACKUP_FAILED] = "GDBM_BACKUP_FAILED", |
698 | | [GDBM_DIR_OVERFLOW] = "GDBM_DIR_OVERFLOW", |
699 | | [GDBM_BAD_BUCKET] = "GDBM_BAD_BUCKET", |
700 | | [GDBM_BAD_HEADER] = "GDBM_BAD_HEADER", |
701 | | [GDBM_BAD_AVAIL] = "GDBM_BAD_AVAIL", |
702 | | [GDBM_BAD_HASH_TABLE] = "GDBM_BAD_HASH_TABLE", |
703 | | [GDBM_BAD_DIR_ENTRY] = "GDBM_BAD_DIR_ENTRY", |
704 | | [GDBM_FILE_CLOSE_ERROR] = "GDBM_FILE_CLOSE_ERROR", |
705 | | [GDBM_FILE_SYNC_ERROR] = "GDBM_FILE_SYNC_ERROR", |
706 | | [GDBM_FILE_TRUNCATE_ERROR] = "GDBM_FILE_TRUNCATE_ERROR", |
707 | | [GDBM_BUCKET_CACHE_CORRUPTED] = "GDBM_BUCKET_CACHE_CORRUPTED", |
708 | | [GDBM_BAD_HASH_ENTRY] = "GDBM_BAD_HASH_ENTRY", |
709 | | [GDBM_ERR_SNAPSHOT_CLONE] = "GDBM_ERR_SNAPSHOT_CLONE", |
710 | | [GDBM_ERR_REALPATH] = "GDBM_ERR_REALPATH", |
711 | | [GDBM_ERR_USAGE] = "GDBM_ERR_USAGE", |
712 | | }; |
713 | | |
714 | | static int |
715 | | str2errcode (char const *str) |
716 | 0 | { |
717 | 0 | int i; |
718 | 0 | #define GDBM_PREFIX "GDBM_" |
719 | 0 | #define GDBM_PREFIX_LEN (sizeof (GDBM_PREFIX) - 1) |
720 | |
|
721 | 0 | if (strncasecmp (str, GDBM_PREFIX, GDBM_PREFIX_LEN) == 0) |
722 | 0 | str += GDBM_PREFIX_LEN; |
723 | |
|
724 | 0 | for (i = 0; i < ARRAY_SIZE (errname); i++) |
725 | 0 | if (strcasecmp (errname[i] + GDBM_PREFIX_LEN, str) == 0) |
726 | 0 | return i; |
727 | | |
728 | 0 | return -1; |
729 | 0 | } |
730 | | |
731 | 50.0k | #define ERROR_MASK_SIZE (_GDBM_MAX_ERRNO+1) |
732 | | |
733 | | static int |
734 | | errormask_sethook (struct variable *var, union value *v) |
735 | 7.66k | { |
736 | 7.66k | char *errmask = var->data; |
737 | | |
738 | 7.66k | if (!v || strcmp (v->string, "false") == 0) |
739 | 2.20k | { |
740 | 2.20k | if (var->data) |
741 | 2.20k | memset (errmask, 0, ERROR_MASK_SIZE); |
742 | 2.20k | } |
743 | 5.45k | else |
744 | 5.45k | { |
745 | 5.45k | char *t; |
746 | | |
747 | 5.45k | if (!errmask) |
748 | 5.45k | { |
749 | 5.45k | errmask = calloc (ERROR_MASK_SIZE, sizeof (char)); |
750 | 5.45k | var->data = errmask; |
751 | 5.45k | } |
752 | | |
753 | 5.45k | if (strcmp (v->string, "true") == 0) |
754 | 5.45k | { |
755 | 5.45k | memset (errmask, 1, ERROR_MASK_SIZE); |
756 | 5.45k | free (v->string); |
757 | 5.45k | v->string = estrdup ("all"); |
758 | 5.45k | } |
759 | 0 | else |
760 | 0 | { |
761 | 0 | for (t = strtok (v->string, ","); t; t = strtok (NULL, ",")) |
762 | 0 | { |
763 | 0 | int len, val, e; |
764 | |
|
765 | 0 | while (t[0] == ' ' || t[0] == '\t') |
766 | 0 | t++; |
767 | 0 | len = strlen (t); |
768 | 0 | while (len > 0 && (t[len-1] == ' ' || t[len-1] == '\t')) |
769 | 0 | len--; |
770 | 0 | t[len] = 0; |
771 | |
|
772 | 0 | if (t[0] == '-') |
773 | 0 | { |
774 | 0 | val = 0; |
775 | 0 | t++; |
776 | 0 | } |
777 | 0 | else if (t[0] == '+') |
778 | 0 | { |
779 | 0 | val = 1; |
780 | 0 | t++; |
781 | 0 | } |
782 | 0 | else |
783 | 0 | { |
784 | 0 | val = 1; |
785 | 0 | } |
786 | 0 | if (strcmp (t, "all") == 0) |
787 | 0 | { |
788 | 0 | for (e = 1; e < ERROR_MASK_SIZE; e++) |
789 | 0 | errmask[e] = val; |
790 | 0 | } |
791 | 0 | else |
792 | 0 | { |
793 | 0 | e = str2errcode (t); |
794 | 0 | if (e == -1) |
795 | 0 | terror (_("unrecognized error code: %s"), t); |
796 | 0 | else |
797 | 0 | errmask[e] = val; |
798 | 0 | } |
799 | 0 | } |
800 | 0 | } |
801 | 5.45k | } |
802 | 7.66k | return VAR_OK; |
803 | 7.66k | } |
804 | | |
805 | | static int |
806 | | errormask_typeconv (struct variable *var, int type, void **retptr) |
807 | 36.9k | { |
808 | 36.9k | char *errmask = var->data; |
809 | | |
810 | 36.9k | if (type == VART_INT) |
811 | 36.9k | { |
812 | 36.9k | int n = *(int*) retptr; |
813 | 36.9k | if (n >= 0 && n < ERROR_MASK_SIZE) |
814 | 36.9k | { |
815 | 36.9k | *(int*) retptr = errmask ? errmask[n] : 0; |
816 | 36.9k | return VAR_OK; |
817 | 36.9k | } |
818 | 0 | else |
819 | 0 | return VAR_ERR_BADVALUE; |
820 | 36.9k | } |
821 | 0 | return VAR_ERR_BADTYPE; |
822 | 36.9k | } |
823 | | |
824 | | static void |
825 | | errormask_freehook (void *data) |
826 | 5.45k | { |
827 | 5.45k | free (data); |
828 | 5.45k | } |
829 | | |
830 | | static int |
831 | | errorexit_sethook (struct variable *var, union value *v) |
832 | 5.45k | { |
833 | 5.45k | if (interactive ()) |
834 | 0 | { |
835 | 0 | return VAR_ERR_BADVALUE; |
836 | 0 | } |
837 | 5.45k | return errormask_sethook (var, v); |
838 | 5.45k | } |