1 /* This file is part of GDBM, the GNU data base manager.
2 Copyright (C) 1990, 1991, 1993, 2007, 2011, 2013 Free Software Foundation,
5 GDBM is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
10 GDBM is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
26 #include <sys/ioctl.h>
27 #ifdef HAVE_SYS_TERMIOS_H
28 # include <sys/termios.h>
35 char *file_name = NULL; /* Database file name */
36 GDBM_FILE gdbm_file = NULL; /* Database to operate upon */
37 datum key_data; /* Current key */
38 datum return_data; /* Current data */
39 int open_mode; /* Default open mode */
41 #define SIZE_T_MAX ((size_t)-1)
55 switch (variable_get ("cachesize", VART_INT, (void**) &cache_size))
63 switch (variable_get ("blocksize", VART_INT, (void**) &block_size))
72 if (!variable_is_true ("lock"))
74 if (!variable_is_true ("mmap"))
76 if (variable_is_true ("sync"))
79 if (open_mode == GDBM_NEWDB)
81 if (interactive && variable_is_true ("confirm") &&
82 access (dbname, F_OK) == 0)
84 if (!getyn (_("database %s already exists; overwrite"), dbname))
89 if (variable_get ("filemode", VART_INT, (void**) &filemode))
92 db = gdbm_open (dbname, block_size, open_mode | flags, filemode, NULL);
96 terror (_("cannot open database %s: %s"), dbname,
97 gdbm_strerror (gdbm_errno));
102 gdbm_setopt (db, GDBM_CACHESIZE, &cache_size, sizeof (int)) == -1)
103 terror (_("gdbm_setopt failed: %s"), gdbm_strerror (gdbm_errno));
106 gdbm_close (gdbm_file);
119 file_name = estrdup (GDBMTOOL_DEFFILE);
120 terror (_("warning: using default database file %s"),
123 return opendb (file_name);
129 bucket_print_lines (hash_bucket *bucket)
131 return 6 + gdbm_file->header->bucket_elems + 3 + bucket->av_count;
134 /* Debug procedure to print the contents of the current hash bucket. */
136 print_bucket (FILE *fp, hash_bucket *bucket, const char *mesg)
141 _("******* %s **********\n\nbits = %d\ncount= %d\nHash Table:\n"),
142 mesg, bucket->bucket_bits, bucket->count);
144 _(" # hash value key size data size data adr home\n"));
145 for (index = 0; index < gdbm_file->header->bucket_elems; index++)
146 fprintf (fp, " %4d %12x %11d %11d %11lu %5d\n", index,
147 bucket->h_table[index].hash_value,
148 bucket->h_table[index].key_size,
149 bucket->h_table[index].data_size,
150 (unsigned long) bucket->h_table[index].data_pointer,
151 bucket->h_table[index].hash_value %
152 gdbm_file->header->bucket_elems);
154 fprintf (fp, _("\nAvail count = %1d\n"), bucket->av_count);
155 fprintf (fp, _("Avail adr size\n"));
156 for (index = 0; index < bucket->av_count; index++)
157 fprintf (fp, "%9lu%9d\n",
158 (unsigned long) bucket->bucket_avail[index].av_adr,
159 bucket->bucket_avail[index].av_size);
163 _gdbm_avail_list_size (GDBM_FILE dbf, size_t min_size)
171 lines = 4 + dbf->header->avail.count;
172 if (lines > min_size)
174 /* Initialize the variables for a pass throught the avail stack. */
175 temp = dbf->header->avail.next_block;
176 size = (((dbf->header->avail.size * sizeof (avail_elem)) >> 1)
177 + sizeof (avail_block));
178 av_stk = emalloc (size);
180 /* Traverse the stack. */
183 if (__lseek (dbf, temp, SEEK_SET) != temp)
185 terror ("lseek: %s", strerror (errno));
189 if ((rc = _gdbm_full_read (dbf, av_stk, size)))
191 if (rc == GDBM_FILE_EOF)
192 terror ("read: %s", gdbm_strerror (rc));
194 terror ("read: %s (%s)",
195 gdbm_strerror (rc), strerror (errno));
199 lines += av_stk->count;
200 if (lines > min_size)
202 temp = av_stk->next_block;
210 _gdbm_print_avail_list (FILE *fp, GDBM_FILE dbf)
217 /* Print the the header avail block. */
218 fprintf (fp, _("\nheader block\nsize = %d\ncount = %d\n"),
219 dbf->header->avail.size, dbf->header->avail.count);
220 for (temp = 0; temp < dbf->header->avail.count; temp++)
222 fprintf (fp, " %15d %10lu \n",
223 dbf->header->avail.av_table[temp].av_size,
224 (unsigned long) dbf->header->avail.av_table[temp].av_adr);
227 /* Initialize the variables for a pass throught the avail stack. */
228 temp = dbf->header->avail.next_block;
229 size = (((dbf->header->avail.size * sizeof (avail_elem)) >> 1)
230 + sizeof (avail_block));
231 av_stk = emalloc (size);
233 /* Print the stack. */
236 if (__lseek (dbf, temp, SEEK_SET) != temp)
238 terror ("lseek: %s", strerror (errno));
242 if ((rc = _gdbm_full_read (dbf, av_stk, size)))
244 if (rc == GDBM_FILE_EOF)
245 terror ("read: %s", gdbm_strerror (rc));
247 terror ("read: %s (%s)", gdbm_strerror (rc), strerror (errno));
251 /* Print the block! */
252 fprintf (fp, _("\nblock = %d\nsize = %d\ncount = %d\n"), temp,
253 av_stk->size, av_stk->count);
254 for (temp = 0; temp < av_stk->count; temp++)
256 fprintf (fp, " %15d %10lu \n", av_stk->av_table[temp].av_size,
257 (unsigned long) av_stk->av_table[temp].av_adr);
259 temp = av_stk->next_block;
265 _gdbm_print_bucket_cache (FILE *fp, GDBM_FILE dbf)
270 if (dbf->bucket_cache != NULL)
273 _("Bucket Cache (size %d):\n Index: Address Changed Data_Hash \n"),
275 for (index = 0; index < dbf->cache_size; index++)
277 changed = dbf->bucket_cache[index].ca_changed;
278 fprintf (fp, " %5d: %7lu %7s %x\n",
280 (unsigned long) dbf->bucket_cache[index].ca_adr,
281 (changed ? _("True") : _("False")),
282 dbf->bucket_cache[index].ca_data.hash_val);
286 fprintf (fp, _("Bucket cache has not been initialized.\n"));
292 int len = strlen (str);
294 if (str[len - 1] == '\n')
310 ws.ws_col = ws.ws_row = 0;
311 if ((ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) || ws.ws_row == 0)
313 const char *lines = getenv ("LINES");
315 ws.ws_row = strtol (lines, NULL, 10);
320 const char *lines = getenv ("LINES");
322 return strtol (lines, NULL, 10);
328 #define ARG_UNUSED __attribute__ ((__unused__))
335 struct gdbmarg **argv;
343 open_handler (struct handler_param *param)
345 if (opendb (param->argv[0]->v.string) == 0)
348 file_name = estrdup (param->argv[0]->v.string);
354 close_handler (struct handler_param *param)
357 terror (_("nothing to close"));
360 gdbm_close (gdbm_file);
367 count_to_str (gdbm_count_t count, char *buf, size_t bufsize)
369 char *p = buf + bufsize;
379 *--p = '0' + count % 10;
385 /* count - count items in the database */
387 count_handler (struct handler_param *param)
391 if (gdbm_count (gdbm_file, &count))
392 terror ("gdbm_count: %s", gdbm_strerror (gdbm_errno));
396 char *p = count_to_str (count, buf, sizeof buf);
399 terror (_("count buffer overflow"));
402 ngettext ("There is %s item in the database.\n",
403 "There are %s items in the database.\n",
409 /* delete KEY - delete a key*/
411 delete_handler (struct handler_param *param)
413 if (gdbm_delete (gdbm_file, param->argv[0]->v.dat) != 0)
415 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
416 terror (_("Item not found"));
418 terror (_("Can't delete: %s"), gdbm_strerror (gdbm_errno));
422 /* fetch KEY - fetch a record by its key */
424 fetch_handler (struct handler_param *param)
426 return_data = gdbm_fetch (gdbm_file, param->argv[0]->v.dat);
427 if (return_data.dptr != NULL)
429 datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
430 fputc ('\n', param->fp);
431 free (return_data.dptr);
434 fprintf (stderr, _("No such item found.\n"));
437 /* store KEY DATA - store data */
439 store_handler (struct handler_param *param)
441 if (gdbm_store (gdbm_file,
442 param->argv[0]->v.dat, param->argv[1]->v.dat,
444 fprintf (stderr, _("Item not inserted.\n"));
447 /* first - begin iteration */
450 firstkey_handler (struct handler_param *param)
452 if (key_data.dptr != NULL)
453 free (key_data.dptr);
454 key_data = gdbm_firstkey (gdbm_file);
455 if (key_data.dptr != NULL)
457 datum_format (param->fp, &key_data, dsdef[DS_KEY]);
458 fputc ('\n', param->fp);
460 return_data = gdbm_fetch (gdbm_file, key_data);
461 datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
462 fputc ('\n', param->fp);
464 free (return_data.dptr);
467 fprintf (param->fp, _("No such item found.\n"));
470 /* next [KEY] - next key */
472 nextkey_handler (struct handler_param *param)
474 if (param->argc == 1)
476 if (key_data.dptr != NULL)
477 free (key_data.dptr);
478 key_data.dptr = emalloc (param->argv[0]->v.dat.dsize);
479 key_data.dsize = param->argv[0]->v.dat.dsize;
480 memcpy (key_data.dptr, param->argv[0]->v.dat.dptr, key_data.dsize);
482 return_data = gdbm_nextkey (gdbm_file, key_data);
483 if (return_data.dptr != NULL)
485 key_data = return_data;
486 datum_format (param->fp, &key_data, dsdef[DS_KEY]);
487 fputc ('\n', param->fp);
489 return_data = gdbm_fetch (gdbm_file, key_data);
490 datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
491 fputc ('\n', param->fp);
493 free (return_data.dptr);
497 fprintf (stderr, _("No such item found.\n"));
498 free (key_data.dptr);
499 key_data.dptr = NULL;
505 reorganize_handler (struct handler_param *param ARG_UNUSED)
507 if (gdbm_reorganize (gdbm_file))
508 fprintf (stderr, _("Reorganization failed.\n"));
510 fprintf (stderr, _("Reorganization succeeded.\n"));
513 /* avail - print available list */
515 avail_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
520 *exp_count = _gdbm_avail_list_size (gdbm_file, SIZE_T_MAX);
525 avail_handler (struct handler_param *param)
527 _gdbm_print_avail_list (param->fp, gdbm_file);
530 /* C - print current bucket */
532 print_current_bucket_begin (struct handler_param *param ARG_UNUSED,
539 *exp_count = bucket_print_lines (gdbm_file->bucket) + 3;
544 print_current_bucket_handler (struct handler_param *param)
546 print_bucket (param->fp, gdbm_file->bucket, _("Current bucket"));
547 fprintf (param->fp, _("\n current directory entry = %d.\n"),
548 gdbm_file->bucket_dir);
549 fprintf (param->fp, _(" current bucket address = %lu.\n"),
550 (unsigned long) gdbm_file->cache_entry->ca_adr);
554 getnum (int *pnum, char *arg, char **endp)
557 unsigned long x = strtoul (arg, &p, 10);
558 if (*p && !isspace (*p))
560 printf (_("not a number (stopped near %s)\n"), p);
563 while (*p && isspace (*p))
569 printf (_("not a number (stopped near %s)\n"), p);
576 /* bucket NUM - print a bucket and set it as a current one.
577 Uses print_current_bucket_handler */
579 print_bucket_begin (struct handler_param *param, size_t *exp_count)
586 if (getnum (&temp, param->argv[0]->v.string, NULL))
589 if (temp >= GDBM_DIR_COUNT (gdbm_file))
591 fprintf (stderr, _("Not a bucket.\n"));
594 _gdbm_get_bucket (gdbm_file, temp);
596 *exp_count = bucket_print_lines (gdbm_file->bucket) + 3;
601 /* dir - print hash directory */
603 print_dir_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
608 *exp_count = GDBM_DIR_COUNT (gdbm_file) + 3;
613 print_dir_handler (struct handler_param *param)
617 fprintf (param->fp, _("Hash table directory.\n"));
618 fprintf (param->fp, _(" Size = %d. Bits = %d. \n\n"),
619 gdbm_file->header->dir_size, gdbm_file->header->dir_bits);
621 for (i = 0; i < GDBM_DIR_COUNT (gdbm_file); i++)
622 fprintf (param->fp, " %10d: %12lu\n",
623 i, (unsigned long) gdbm_file->dir[i]);
626 /* header - print file handler */
628 print_header_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
638 print_header_handler (struct handler_param *param)
640 FILE *fp = param->fp;
642 fprintf (fp, _("\nFile Header: \n\n"));
643 fprintf (fp, _(" table = %lu\n"),
644 (unsigned long) gdbm_file->header->dir);
645 fprintf (fp, _(" table size = %d\n"), gdbm_file->header->dir_size);
646 fprintf (fp, _(" table bits = %d\n"), gdbm_file->header->dir_bits);
647 fprintf (fp, _(" block size = %d\n"), gdbm_file->header->block_size);
648 fprintf (fp, _(" bucket elems = %d\n"), gdbm_file->header->bucket_elems);
649 fprintf (fp, _(" bucket size = %d\n"), gdbm_file->header->bucket_size);
650 fprintf (fp, _(" header magic = %x\n"), gdbm_file->header->header_magic);
651 fprintf (fp, _(" next block = %lu\n"),
652 (unsigned long) gdbm_file->header->next_block);
653 fprintf (fp, _(" avail size = %d\n"), gdbm_file->header->avail.size);
654 fprintf (fp, _(" avail count = %d\n"), gdbm_file->header->avail.count);
655 fprintf (fp, _(" avail nx blk = %lu\n"),
656 (unsigned long) gdbm_file->header->avail.next_block);
659 /* hash KEY - hash the key */
661 hash_handler (struct handler_param *param)
663 fprintf (param->fp, _("hash value = %x. \n"),
664 _gdbm_hash (param->argv[0]->v.dat));
667 /* cache - print the bucket cache */
669 print_cache_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
674 *exp_count = gdbm_file->bucket_cache ? gdbm_file->cache_size + 1 : 1;
679 print_cache_handler (struct handler_param *param)
681 _gdbm_print_bucket_cache (param->fp, gdbm_file);
684 /* version - print GDBM version */
686 print_version_handler (struct handler_param *param)
688 fprintf (param->fp, "%s\n", gdbm_version);
691 /* list - List all entries */
693 list_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
701 if (gdbm_count (gdbm_file, &count))
703 else if (count > SIZE_T_MAX)
704 *exp_count = SIZE_T_MAX;
713 list_handler (struct handler_param *param)
718 key = gdbm_firstkey (gdbm_file);
721 datum nextkey = gdbm_nextkey (gdbm_file, key);
723 data = gdbm_fetch (gdbm_file, key);
726 terror (_("cannot fetch data; the key was:"));
727 datum_format (stderr, &key, dsdef[DS_KEY]);
731 datum_format (param->fp, &key, dsdef[DS_KEY]);
732 fputc (' ', param->fp);
733 datum_format (param->fp, &data, dsdef[DS_CONTENT]);
734 fputc ('\n', param->fp);
742 /* quit - quit the program */
744 quit_handler (struct handler_param *param ARG_UNUSED)
746 if (gdbm_file != NULL)
747 gdbm_close (gdbm_file);
752 /* export FILE [truncate] - export to a flat file format */
754 export_handler (struct handler_param *param)
756 int format = GDBM_DUMP_FMT_ASCII;
757 int flags = GDBM_WRCREAT;
761 for (i = 1; i < param->argc; i++)
763 if (strcmp (param->argv[i]->v.string, "truncate") == 0)
765 else if (strcmp (param->argv[i]->v.string, "binary") == 0)
766 format = GDBM_DUMP_FMT_BINARY;
767 else if (strcmp (param->argv[i]->v.string, "ascii") == 0)
768 format = GDBM_DUMP_FMT_ASCII;
771 terror (_("unrecognized argument: %s"),
772 param->argv[i]->v.string);
777 if (variable_get ("filemode", VART_INT, (void**) &filemode))
779 if (gdbm_dump (gdbm_file, param->argv[0]->v.string, format, flags, filemode))
781 terror (_("error dumping database: %s"),
782 gdbm_strerror (gdbm_errno));
786 /* import FILE [replace] [nometa] - import from a flat file */
788 import_handler (struct handler_param *param)
790 int flag = GDBM_INSERT;
791 unsigned long err_line;
796 for (i = 1; i < param->argc; i++)
798 if (strcmp (param->argv[i]->v.string, "replace") == 0)
800 else if (strcmp (param->argv[i]->v.string, "nometa") == 0)
801 meta_mask = GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER;
804 terror (_("unrecognized argument: %s"),
805 param->argv[i]->v.string);
810 rc = gdbm_load (&gdbm_file, param->argv[0]->v.string, flag,
811 meta_mask, &err_line);
812 if (rc && gdbm_errno == GDBM_NO_DBNAME)
816 open_mode = GDBM_NEWDB;
823 rc = gdbm_load (&gdbm_file, param->argv[0]->v.string, flag,
824 meta_mask, &err_line);
830 case GDBM_ERR_FILE_OWNER:
831 case GDBM_ERR_FILE_MODE:
832 terror (_("error restoring metadata: %s (%s)"),
833 gdbm_strerror (gdbm_errno), strerror (errno));
838 terror ("%s:%lu: %s", param->argv[0], err_line,
839 gdbm_strerror (gdbm_errno));
841 terror (_("cannot load from %s: %s"), param->argv[0],
842 gdbm_strerror (gdbm_errno));
848 if (gdbm_setopt (gdbm_file, GDBM_GETDBNAME, &file_name, sizeof (file_name)))
849 terror (_("gdbm_setopt failed: %s"), gdbm_strerror (gdbm_errno));
852 /* status - print current program status */
854 status_handler (struct handler_param *param)
857 fprintf (param->fp, _("Database file: %s\n"), file_name);
859 fprintf (param->fp, "%s\n", _("No database name"));
861 fprintf (param->fp, "%s\n", _("Database is open"));
863 fprintf (param->fp, "%s\n", _("Database is not open"));
864 dsprint (param->fp, DS_KEY, dsdef[DS_KEY]);
865 dsprint (param->fp, DS_CONTENT, dsdef[DS_CONTENT]);
869 source_handler (struct handler_param *param)
871 char *fname = tildexpand (param->argv[0]->v.string);
872 if (setsource (fname, 0) == 0)
878 void help_handler (struct handler_param *param);
879 int help_begin (struct handler_param *param, size_t *exp_count);
890 char *name; /* Command name */
891 size_t len; /* Name length */
893 int (*begin) (struct handler_param *param, size_t *);
894 void (*handler) (struct handler_param *param);
895 void (*end) (void *data);
896 struct argdef args[NARGS];
901 struct command command_tab[] = {
902 #define S(s) #s, sizeof (#s) - 1
904 checkdb, count_handler, NULL,
905 { { NULL } }, N_("count (number of entries)") },
907 checkdb, delete_handler, NULL,
908 { { N_("KEY"), ARG_DATUM, DS_KEY }, { NULL } }, N_("delete a record") },
910 checkdb, export_handler, NULL,
911 { { N_("FILE"), ARG_STRING },
912 { "[truncate]", ARG_STRING },
913 { "[binary|ascii]", ARG_STRING },
917 checkdb, fetch_handler, NULL,
918 { { N_("KEY"), ARG_DATUM, DS_KEY }, { NULL } }, N_("fetch record") },
920 NULL, import_handler, NULL,
921 { { N_("FILE"), ARG_STRING },
922 { "[replace]", ARG_STRING },
923 { "[nometa]" , ARG_STRING },
927 list_begin, list_handler, NULL,
928 { { NULL } }, N_("list") },
930 checkdb, nextkey_handler, NULL,
931 { { N_("[KEY]"), ARG_STRING },
935 checkdb, store_handler, NULL,
936 { { N_("KEY"), ARG_DATUM, DS_KEY },
937 { N_("DATA"), ARG_DATUM, DS_CONTENT },
941 checkdb, firstkey_handler, NULL,
942 { { NULL } }, N_("firstkey") },
943 { S(reorganize), T_CMD,
944 checkdb, reorganize_handler, NULL,
945 { { NULL } }, N_("reorganize") },
947 avail_begin, avail_handler, NULL,
948 { { NULL } }, N_("print avail list") },
950 print_bucket_begin, print_current_bucket_handler, NULL,
951 { { N_("NUMBER"), ARG_STRING },
952 { NULL } }, N_("print a bucket") },
954 print_current_bucket_begin, print_current_bucket_handler, NULL,
956 N_("print current bucket") },
958 print_dir_begin, print_dir_handler, NULL,
959 { { NULL } }, N_("print hash directory") },
961 print_header_begin , print_header_handler, NULL,
962 { { NULL } }, N_("print database file header") },
964 NULL, hash_handler, NULL,
965 { { N_("KEY"), ARG_DATUM, DS_KEY },
966 { NULL } }, N_("hash value of key") },
968 print_cache_begin, print_cache_handler, NULL,
969 { { NULL } }, N_("print the bucket cache") },
971 NULL, status_handler, NULL,
972 { { NULL } }, N_("print current program status") },
974 NULL, print_version_handler, NULL,
975 { { NULL } }, N_("print version of gdbm") },
977 help_begin, help_handler, NULL,
978 { { NULL } }, N_("print this help list") },
980 NULL, quit_handler, NULL,
981 { { NULL } }, N_("quit the program") },
984 { { "[VAR=VALUE...]" }, { NULL } }, N_("set or list variables") },
987 { { "VAR..." }, { NULL } }, N_("unset variables") },
990 { { "key|content", ARG_STRING },
991 { "{ FIELD-LIST }", ARG_STRING },
992 { NULL } }, N_("define datum structure") },
994 NULL, source_handler, NULL,
995 { { "FILE", ARG_STRING },
996 { NULL } }, N_("source command script") },
998 NULL, close_handler, NULL,
999 { { NULL } }, N_("close the database") },
1001 NULL, open_handler, NULL,
1002 { { "FILE", ARG_STRING }, { NULL } },
1003 N_("open new database") },
1009 cmdcmp (const void *a, const void *b)
1011 struct command const *ac = a;
1012 struct command const *bc = b;
1013 return strcmp (ac->name, bc->name);
1019 qsort (command_tab, sizeof (command_tab) / sizeof (command_tab[0]) - 1,
1020 sizeof (command_tab[0]), cmdcmp);
1024 /* ? - help handler */
1028 help_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count)
1031 *exp_count = sizeof (command_tab) / sizeof (command_tab[0]) + 1;
1036 help_handler (struct handler_param *param)
1038 struct command *cmd;
1039 FILE *fp = param->fp;
1041 for (cmd = command_tab; cmd->name; cmd++)
1046 n = fprintf (fp, " %s", cmd->name);
1048 for (i = 0; i < NARGS && cmd->args[i].name; i++)
1049 n += fprintf (fp, " %s", gettext (cmd->args[i].name));
1052 fprintf (fp, "%*.s", CMDCOLS-n, "");
1053 fprintf (fp, " %s", gettext (cmd->doc));
1059 command_lookup (const char *str, struct locus *loc, struct command **pcmd)
1061 enum { fcom_init, fcom_found, fcom_ambig, fcom_abort } state = fcom_init;
1062 struct command *cmd, *found = NULL;
1063 size_t len = strlen (str);
1065 for (cmd = command_tab; state != fcom_abort && cmd->name; cmd++)
1067 if (memcmp (cmd->name, str, len < cmd->len ? len : cmd->len) == 0)
1083 fprintf (stderr, "ambiguous command: %s\n", str);
1084 fprintf (stderr, " %s\n", found->name);
1089 fprintf (stderr, " %s\n", cmd->name);
1093 /* should not happen */
1099 if (state == fcom_init)
1101 interactive ? _("Invalid command. Try ? for help.") :
1102 _("Unknown command"));
1110 char *parseopt_program_doc = N_("examine and/or modify a GDBM database");
1111 char *parseopt_program_args = N_("DBFILE");
1113 struct gdbm_option optab[] = {
1114 { 'b', "block-size", N_("SIZE"), N_("set block size") },
1115 { 'c', "cache-size", N_("SIZE"), N_("set cache size") },
1116 { 'f', "file", N_("FILE"), N_("read commands from FILE") },
1117 { 'g', NULL, "FILE", NULL, PARSEOPT_HIDDEN },
1118 { 'l', "no-lock", NULL, N_("disable file locking") },
1119 { 'm', "no-mmap", NULL, N_("do not use mmap") },
1120 { 'n', "newdb", NULL, N_("create database") },
1121 { 'N', "norc", NULL, N_("do not read .gdbmtoolrc file") },
1122 { 'r', "read-only", NULL, N_("open database in read-only mode") },
1123 { 's', "synchronize", NULL, N_("synchronize to disk after each write") },
1124 { 'q', "quiet", NULL, N_("don't print initial banner") },
1132 gdbmarg_string (char *string, struct locus *loc)
1134 struct gdbmarg *arg = ecalloc (1, sizeof (*arg));
1136 arg->type = ARG_STRING;
1140 arg->v.string = string;
1145 gdbmarg_datum (datum *dat, struct locus *loc)
1147 struct gdbmarg *arg = ecalloc (1, sizeof (*arg));
1149 arg->type = ARG_DATUM;
1158 gdbmarg_kvpair (struct kvpair *kvp, struct locus *loc)
1160 struct gdbmarg *arg = ecalloc (1, sizeof (*arg));
1162 arg->type = ARG_KVPAIR;
1166 arg->v.kvpair = kvp;
1173 struct slist *lp = emalloc (sizeof (*lp));
1180 slist_free (struct slist *lp)
1184 struct slist *next = lp->next;
1192 kvpair_string (struct locus *loc, char *val)
1194 struct kvpair *p = ecalloc (1, sizeof (*p));
1195 p->type = KV_STRING;
1203 kvpair_list (struct locus *loc, struct slist *s)
1205 struct kvpair *p = ecalloc (1, sizeof (*p));
1215 kvlist_free (struct kvpair *kvp)
1219 struct kvpair *next = kvp->next;
1228 slist_free (kvp->val.l);
1237 gdbmarg_free (struct gdbmarg *arg)
1239 if (arg && --arg->ref == 0)
1244 free (arg->v.string);
1248 kvlist_free (arg->v.kvpair);
1252 free (arg->v.dat.dptr);
1262 gdbmarg_destroy (struct gdbmarg **parg)
1264 if (parg && gdbmarg_free (*parg))
1269 gdbmarglist_init (struct gdbmarglist *lst, struct gdbmarg *arg)
1273 lst->head = lst->tail = arg;
1277 gdbmarglist_add (struct gdbmarglist *lst, struct gdbmarg *arg)
1281 lst->tail->next = arg;
1288 gdbmarglist_free (struct gdbmarglist *lst)
1290 struct gdbmarg *arg;
1292 for (arg = lst->head; arg; )
1294 struct gdbmarg *next = arg->next;
1300 struct handler_param param;
1304 param_free_argv (struct handler_param *param, int n)
1308 for (i = 0; i < n; i++)
1309 gdbmarg_destroy (¶m->argv[i]);
1313 typedef struct gdbmarg *(*coerce_type_t) (struct gdbmarg *arg,
1314 struct argdef *def);
1317 coerce_ref (struct gdbmarg *arg, struct argdef *def)
1324 coerce_k2d (struct gdbmarg *arg, struct argdef *def)
1328 if (datum_scan (&d, dsdef[def->ds], arg->v.kvpair))
1330 return gdbmarg_datum (&d, &arg->loc);
1334 coerce_s2d (struct gdbmarg *arg, struct argdef *def)
1339 memset (&kvp, 0, sizeof (kvp));
1340 kvp.type = KV_STRING;
1341 kvp.val.s = arg->v.string;
1343 if (datum_scan (&d, dsdef[def->ds], &kvp))
1345 return gdbmarg_datum (&d, &arg->loc);
1348 #define coerce_fail NULL
1350 coerce_type_t coerce_tab[ARG_MAX][ARG_MAX] = {
1352 /* s */ { coerce_ref, coerce_fail, coerce_fail },
1353 /* d */ { coerce_s2d, coerce_ref, coerce_k2d },
1354 /* k */ { coerce_fail, coerce_fail, coerce_ref }
1357 char *argtypestr[] = { "string", "datum", "k/v pair" };
1360 coerce (struct gdbmarg *arg, struct argdef *def)
1362 if (!coerce_tab[def->type][arg->type])
1364 lerror (&arg->loc, _("cannot coerce %s to %s"),
1365 argtypestr[arg->type], argtypestr[def->type]);
1368 return coerce_tab[def->type][arg->type] (arg, def);
1372 run_command (struct command *cmd, struct gdbmarglist *arglist)
1375 struct gdbmarg *arg;
1378 size_t expected_lines, *expected_lines_ptr;
1381 variable_get ("pager", VART_STRING, (void**) &pager);
1383 arg = arglist ? arglist->head : NULL;
1385 for (i = 0; cmd->args[i].name && arg; i++, arg = arg->next)
1390 param.argv = erealloc (param.argv,
1391 sizeof (param.argv[0]) * argmax);
1393 if ((param.argv[i] = coerce (arg, &cmd->args[i])) == NULL)
1395 param_free_argv (¶m, i);
1400 for (; cmd->args[i].name; i++)
1402 char *argname = cmd->args[i].name;
1405 if (*argname == '[')
1406 /* Optional argument */
1411 terror (_("%s: not enough arguments"), cmd->name);
1414 printf ("%s? ", argname);
1416 if (fgets (argbuf, sizeof argbuf, stdin) == NULL)
1418 terror (_("unexpected eof"));
1426 param.argv = erealloc (param.argv,
1427 sizeof (param.argv[0]) * argmax);
1430 t = gdbmarg_string (estrdup (argbuf), &yylloc);
1431 if ((param.argv[i] = coerce (t, &cmd->args[i])) == NULL)
1434 param_free_argv (¶m, i);
1441 terror (_("%s: too many arguments"), cmd->name);
1445 /* Prepare for calling the handler */
1450 param.argv = ecalloc (argmax, sizeof (param.argv[0]));
1452 param.argv[i] = NULL;
1458 expected_lines_ptr = (interactive && pager) ? &expected_lines : NULL;
1459 if (!(cmd->begin && cmd->begin (¶m, expected_lines_ptr)))
1461 if (pager && expected_lines > get_screen_lines ())
1463 pagfp = popen (pager, "w");
1468 terror (_("cannot run pager `%s': %s"), pager,
1477 cmd->handler (¶m);
1479 cmd->end (param.data);
1480 else if (param.data)
1487 param_free_argv (¶m, param.argc);
1495 if (access (GDBMTOOLRC, R_OK) == 0)
1497 if (setsource (GDBMTOOLRC, 0) == 0)
1503 char *p = getenv ("HOME");
1506 struct passwd *pw = getpwuid (getuid ());
1509 terror (_("cannot find home directory"));
1514 fname = mkfilename (p, GDBMTOOLRC, NULL);
1515 if (access (fname, R_OK) == 0)
1517 if (setsource (fname, 0) == 0)
1525 main (int argc, char *argv[])
1533 set_progname (argv[0]);
1535 #ifdef HAVE_SETLOCALE
1536 setlocale (LC_ALL, "");
1538 bindtextdomain (PACKAGE, LOCALEDIR);
1539 textdomain (PACKAGE);
1543 /* Initialize variables. */
1545 dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("string"), NULL, 1);
1546 dsdef[DS_CONTENT] = dsegm_new_field (datadef_lookup ("string"), NULL, 1);
1548 variable_set ("open", VART_STRING, "wrcreat");
1549 variable_set ("pager", VART_STRING, getenv ("PAGER"));
1551 for (opt = parseopt_first (argc, argv, optab);
1553 opt = parseopt_next ())
1563 variable_set ("lock", VART_BOOL, &bv);
1568 variable_set ("mmap", VART_BOOL, &bv);
1573 variable_set ("sync", VART_BOOL, &bv);
1577 variable_set ("open", VART_STRING, "readonly");
1581 variable_set ("open", VART_STRING, "newdb");
1589 variable_set ("cachesize", VART_STRING, optarg);
1593 variable_set ("blocksize", VART_STRING, optarg);
1602 variable_set ("quiet", VART_BOOL, &bv);
1606 terror (_("unknown option; try `%s -h' for more info"),
1616 terror (_("too many arguments"));
1621 file_name = argv[0];
1623 signal (SIGPIPE, SIG_IGN);
1625 memset (¶m, 0, sizeof (param));
1631 /* Welcome message. */
1632 if (intr && !variable_is_true ("quiet"))
1633 printf (_("\nWelcome to the gdbm tool. Type ? for help.\n\n"));
1635 if (setsource (source, intr))