Coverage Report

Created: 2025-07-12 06:05

/src/gdbm/tools/var.c
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
}