aboutsummaryrefslogtreecommitdiff
path: root/src/testgdbm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testgdbm.c')
-rw-r--r--src/testgdbm.c925
1 files changed, 925 insertions, 0 deletions
diff --git a/src/testgdbm.c b/src/testgdbm.c
new file mode 100644
index 0000000..ad454dc
--- /dev/null
+++ b/src/testgdbm.c
@@ -0,0 +1,925 @@
+/* testgdbm.c - Driver program to test the database routines and to
+ help debug gdbm. Uses inside information to show "system" information */
+
+/* This file is part of GDBM, the GNU data base manager.
+ Copyright (C) 1990, 1991, 1993, 2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+/* Include system configuration before all else. */
+#include "autoconf.h"
+
+#include "gdbmdefs.h"
+#include "gdbmerrno.h"
+#include "extern.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <stdarg.h>
+
+extern const char *gdbm_version;
+
+extern const char *gdbm_strerror (gdbm_error);
+
+char *progname; /* Program name */
+
+char *file_name = NULL; /* Database file name */
+gdbm_file_info *gdbm_file = NULL; /* Database to operate upon */
+int interactive; /* Are we running in interactive mode? */
+datum key_data; /* Current key */
+datum return_data; /* Current data */
+int key_z = 1; /* Keys are nul-terminated strings */
+int data_z = 1; /* Data are nul-terminated strings */
+
+
+/* Debug procedure to print the contents of the current hash bucket. */
+void
+print_bucket (hash_bucket * bucket, char *mesg)
+{
+ int index;
+
+ printf ("******* %s **********\n\nbits = %d\ncount= %d\nHash Table:\n",
+ mesg, bucket->bucket_bits, bucket->count);
+ printf
+ (" # hash value key size data size data adr home\n");
+ for (index = 0; index < gdbm_file->header->bucket_elems; index++)
+ printf (" %4d %12x %11d %11d %11d %5d\n", index,
+ bucket->h_table[index].hash_value,
+ bucket->h_table[index].key_size,
+ bucket->h_table[index].data_size,
+ bucket->h_table[index].data_pointer,
+ bucket->h_table[index].hash_value %
+ gdbm_file->header->bucket_elems);
+
+ printf ("\nAvail count = %1d\n", bucket->av_count);
+ printf ("Avail adr size\n");
+ for (index = 0; index < bucket->av_count; index++)
+ printf ("%9d%9d\n", bucket->bucket_avail[index].av_adr,
+ bucket->bucket_avail[index].av_size);
+}
+
+
+void
+_gdbm_print_avail_list (gdbm_file_info * dbf)
+{
+ int temp;
+ int size;
+ avail_block *av_stk;
+
+ /* Print the the header avail block. */
+ printf ("\nheader block\nsize = %d\ncount = %d\n",
+ dbf->header->avail.size, dbf->header->avail.count);
+ for (temp = 0; temp < dbf->header->avail.count; temp++)
+ {
+ printf (" %15d %10d \n", dbf->header->avail.av_table[temp].av_size,
+ dbf->header->avail.av_table[temp].av_adr);
+ }
+
+ /* Initialize the variables for a pass throught the avail stack. */
+ temp = dbf->header->avail.next_block;
+ size = (((dbf->header->avail.size * sizeof (avail_elem)) >> 1)
+ + sizeof (avail_block));
+ av_stk = (avail_block *) malloc (size);
+ if (av_stk == NULL)
+ {
+ printf ("Out of memory\n");
+ exit (2);
+ }
+
+ /* Print the stack. */
+ while (FALSE)
+ {
+ __lseek (dbf, temp, L_SET);
+ __read (dbf, av_stk, size);
+
+ /* Print the block! */
+ printf ("\nblock = %d\nsize = %d\ncount = %d\n", temp,
+ av_stk->size, av_stk->count);
+ for (temp = 0; temp < av_stk->count; temp++)
+ {
+ printf (" %15d %10d \n", av_stk->av_table[temp].av_size,
+ av_stk->av_table[temp].av_adr);
+ }
+ temp = av_stk->next_block;
+ }
+}
+
+void
+_gdbm_print_bucket_cache (FILE *fp, gdbm_file_info * dbf)
+{
+ int index;
+ char changed;
+
+ if (dbf->bucket_cache != NULL)
+ {
+ fprintf
+ (fp,
+ "Bucket Cache (size %d):\n Index: Address Changed Data_Hash \n",
+ dbf->cache_size);
+ for (index = 0; index < dbf->cache_size; index++)
+ {
+ changed = dbf->bucket_cache[index].ca_changed;
+ fprintf (fp, " %5d: %7d %7s %x\n",
+ index,
+ dbf->bucket_cache[index].ca_adr,
+ (changed ? "True" : "False"),
+ dbf->bucket_cache[index].ca_data.hash_val);
+ }
+ }
+ else
+ fprintf (fp, "Bucket cache has not been initialized.\n");
+}
+
+void
+usage ()
+{
+ printf ("Usage: %s OPTIONS\n", progname);
+ printf ("Test and modify a GDBM database.\n");
+ printf ("\n");
+ printf ("OPTIONS are:\n\n");
+ printf (" -b SIZE set block size\n");
+ printf (" -c SIZE set cache size\n");
+ printf (" -g FILE operate on FILE instead of `junk.gdbm'\n");
+ printf (" -h print this help summary\n");
+ printf (" -n create database\n");
+ printf (" -r open database in read-only mode\n");
+ printf (" -s synchronize to the disk after each write\n");
+ printf (" -v print program version\n");
+ printf ("\n");
+ printf ("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+}
+
+void
+version ()
+{
+ printf ("testgdbm (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ printf ("Copyright (C) 2007 Free Software Foundation, Inc.\n");
+ printf ("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n");
+ printf ("This is free software: you are free to change and redistribute it.\n");
+ printf ("There is NO WARRANTY, to the extent permitted by law.\n");
+}
+
+void
+error (int code, char *fmt, ...)
+{
+ va_list ap;
+ fprintf (stderr, "%s: ", progname);
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (fmt);
+ fputc ('\n', stderr);
+ if (code)
+ exit (code);
+}
+
+int
+trimnl (char *str)
+{
+ int len = strlen (str);
+
+ if (str[len - 1] == '\n')
+ {
+ str[--len] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+void
+read_from_file (const char *name, int replace)
+{
+ int line = 0;
+ char buf[1024];
+ datum key;
+ datum data;
+ FILE *fp;
+ int flag = replace ? GDBM_REPLACE : 0;
+
+ fp = fopen (name, "r");
+ if (!fp)
+ {
+ fprintf (stderr, "cannot open file `%s' for reading: %s\n",
+ name, strerror (errno));
+ return;
+ }
+
+ while (fgets (buf, sizeof buf, fp))
+ {
+ char *p;
+
+ if (!trimnl (buf))
+ {
+ fprintf (stderr, "%s:%d: line too long\n", name, line);
+ continue;
+ }
+
+ line++;
+ p = strchr (buf, ' ');
+ if (!p)
+ {
+ fprintf (stderr, "%s:%d: malformed line\n", name, line);
+ continue;
+ }
+
+ for (*p++ = 0; *p && isspace (*p); p++)
+ ;
+ key.dptr = buf;
+ key.dsize = strlen (buf) + key_z;
+ data.dptr = p;
+ data.dsize = strlen (p) + data_z;
+ if (gdbm_store (gdbm_file, key, data, flag) != 0)
+ fprintf (stderr, "%d: item not inserted\n", line);
+ }
+ fclose (fp);
+}
+
+int
+get_screen_lines ()
+{
+ if (isatty (1))
+ {
+ struct winsize ws;
+
+ ws.ws_col = ws.ws_row = 0;
+ if ((ioctl(1, TIOCGWINSZ, (char *) &ws) < 0) || ws.ws_row == 0)
+ {
+ const char *lines = getenv ("LINES");
+ if (lines)
+ ws.ws_row = strtol (lines, NULL, 10);
+ }
+ return ws.ws_row;
+ }
+ return -1;
+}
+
+void
+page_data (int count, void (*func) (FILE *, void *), void *data)
+{
+ FILE *out = stdout;
+ if (interactive && (count < 0 || count > get_screen_lines ()))
+ {
+ char *pager = getenv ("PAGER");
+ if (pager)
+ {
+ out = popen (getenv ("PAGER"), "w");
+ if (!out)
+ {
+ fprintf (stderr, "cannot run pager `%s': %s\n", pager,
+ strerror (errno));
+ out = stdout;
+ }
+ }
+ }
+ func (out, data);
+ if (out != stdout)
+ pclose (out);
+}
+
+int
+get_record_count ()
+{
+ datum key, data;
+ int count = 0;
+ data = gdbm_firstkey (gdbm_file);
+ while (data.dptr != NULL)
+ {
+ count++;
+ key = data;
+ data = gdbm_nextkey (gdbm_file, key);
+ free (key.dptr);
+ }
+ return count;
+}
+
+
+#define ARG_UNUSED __attribute__ ((__unused__))
+
+#define NARGS 2
+
+void
+count_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ printf ("There are %d items in the database.\n", get_record_count ());
+}
+
+void
+delete_handler (char *arg[NARGS])
+{
+ if (key_data.dptr != NULL)
+ free (key_data.dptr);
+ key_data.dptr = strdup (arg[0]);
+ key_data.dsize = strlen (arg[0]) + key_z;
+ if (gdbm_delete (gdbm_file, key_data) != 0)
+ printf ("Item not found or deleted\n");
+}
+
+void
+fetch_handler (char *arg[NARGS])
+{
+ if (key_data.dptr != NULL)
+ free (key_data.dptr);
+ key_data.dptr = strdup (arg[0]);
+ key_data.dsize = strlen (arg[0]) + key_z;
+ return_data = gdbm_fetch (gdbm_file, key_data);
+ if (return_data.dptr != NULL)
+ {
+ printf ("data is ->%.*s\n", return_data.dsize, return_data.dptr);
+ free (return_data.dptr);
+ }
+ else
+ printf ("No such item found.\n");
+}
+
+void
+nextkey_handler (char *arg[NARGS])
+{
+ if (arg[0])
+ {
+ if (key_data.dptr != NULL)
+ free (key_data.dptr);
+ key_data.dptr = strdup (arg[0]);
+ key_data.dsize = strlen (arg[0]) + key_z;
+ }
+ return_data = gdbm_nextkey (gdbm_file, key_data);
+ if (return_data.dptr != NULL)
+ {
+ key_data = return_data;
+ printf ("key is ->%.*s\n", key_data.dsize, key_data.dptr);
+ return_data = gdbm_fetch (gdbm_file, key_data);
+ printf ("data is ->%.*s\n", return_data.dsize, return_data.dptr);
+ free (return_data.dptr);
+ }
+ else
+ {
+ printf ("No such item found.\n");
+ free (key_data.dptr);
+ key_data.dptr = NULL;
+ }
+}
+
+void
+store_handler (char *arg[NARGS])
+{
+ datum key;
+ datum data;
+
+ key.dptr = arg[0];
+ key.dsize = strlen (arg[0]) + key_z;
+ data.dptr = arg[1];
+ data.dsize = strlen (arg[1]) + data_z;
+ if (gdbm_store (gdbm_file, key, data, GDBM_REPLACE) != 0)
+ printf ("Item not inserted. \n");
+}
+
+void
+firstkey_handler (char *arg[NARGS])
+{
+ if (key_data.dptr != NULL)
+ free (key_data.dptr);
+ key_data = gdbm_firstkey (gdbm_file);
+ if (key_data.dptr != NULL)
+ {
+ printf ("key is ->%.*s\n", key_data.dsize, key_data.dptr);
+ return_data = gdbm_fetch (gdbm_file, key_data);
+ printf ("data is ->%.*s\n", return_data.dsize, return_data.dptr);
+ free (return_data.dptr);
+ }
+ else
+ printf ("No such item found.\n");
+}
+
+void
+next_on_last_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ return_data = gdbm_nextkey (gdbm_file, key_data);
+ if (return_data.dptr != NULL)
+ {
+ free (key_data.dptr);
+ key_data = return_data;
+ printf ("key is ->%.*s\n", key_data.dsize, key_data.dptr);
+ return_data = gdbm_fetch (gdbm_file, key_data);
+ printf ("data is ->%.*s\n", return_data.dsize, return_data.dptr);
+ free (return_data.dptr);
+ }
+ else
+ printf ("No such item found.\n");
+}
+
+void
+reorganize_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ if (gdbm_reorganize (gdbm_file))
+ printf ("Reorganization failed.\n");
+ else
+ printf ("Reorganization succeeded.\n");
+}
+
+void
+avail_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ _gdbm_print_avail_list (gdbm_file);
+}
+
+void
+print_current_bucket_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ print_bucket (gdbm_file->bucket, "Current bucket");
+ printf ("\n current directory entry = %d.\n",
+ gdbm_file->bucket_dir);
+ printf (" current bucket address = %d.\n",
+ gdbm_file->cache_entry->ca_adr);
+}
+
+int
+getnum (int *pnum, char *arg, char **endp)
+{
+ char *p;
+ unsigned long x = strtoul (arg, &p, 10);
+ if (*p && !isspace (*p))
+ {
+ printf ("not a number (stopped near %s)\n", p);
+ return 1;
+ }
+ while (*p && isspace (*p))
+ p++;
+ if (endp)
+ *endp = p;
+ else
+ {
+ printf ("not a number (stopped near %s)\n", p);
+ return 1;
+ }
+ *pnum = x;
+ return 0;
+}
+
+void
+print_bucket_handler (char *arg[NARGS])
+{
+ int temp;
+
+ if (getnum (&temp, arg[0], NULL))
+ return;
+
+ if (temp >= gdbm_file->header->dir_size / 4)
+ {
+ printf ("Not a bucket. \n");
+ }
+ _gdbm_get_bucket (gdbm_file, temp);
+
+ printf ("Your bucket is now ");
+ print_current_bucket_handler (NULL);
+}
+
+void
+_print_dir (FILE *out, void *data)
+{
+ int i;
+
+ fprintf (out, "Hash table directory.\n");
+ fprintf (out, " Size = %d. Bits = %d. \n\n",
+ gdbm_file->header->dir_size, gdbm_file->header->dir_bits);
+
+ for (i = 0; i < gdbm_file->header->dir_size / 4; i++)
+ fprintf (out, " %10d: %12d\n", i, gdbm_file->dir[i]);
+}
+
+void
+print_dir_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ page_data (gdbm_file->header->dir_size / 4 + 3, _print_dir, NULL);
+}
+
+void
+print_header_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ printf ("\nFile Header: \n\n");
+ printf (" table = %d\n", gdbm_file->header->dir);
+ printf (" table size = %d\n", gdbm_file->header->dir_size);
+ printf (" table bits = %d\n", gdbm_file->header->dir_bits);
+ printf (" block size = %d\n", gdbm_file->header->block_size);
+ printf (" bucket elems = %d\n", gdbm_file->header->bucket_elems);
+ printf (" bucket size = %d\n", gdbm_file->header->bucket_size);
+ printf (" header magic = %x\n", gdbm_file->header->header_magic);
+ printf (" next block = %d\n", gdbm_file->header->next_block);
+ printf (" avail size = %d\n", gdbm_file->header->avail.size);
+ printf (" avail count = %d\n", gdbm_file->header->avail.count);
+ printf (" avail nx blk = %d\n",
+ gdbm_file->header->avail.next_block);
+}
+
+void
+hash_handler (char *arg[NARGS])
+{
+ datum key;
+
+ key.dptr = arg[0];
+ key.dsize = strlen (arg[0]) + key_z;
+ printf ("hash value = %x. \n", _gdbm_hash (key));
+}
+
+static void
+print_bucket_cache (FILE *out, void *data)
+{
+ _gdbm_print_bucket_cache (out, data);
+}
+
+void
+print_cache_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ page_data (gdbm_file->bucket_cache ? gdbm_file->cache_size + 1 : 1,
+ print_bucket_cache, gdbm_file);
+}
+
+void
+print_version_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ printf ("%s\n", gdbm_version);
+}
+
+void
+read_handler (char *arg[NARGS])
+{
+ read_from_file (arg[0], arg[1] && strcmp (arg[1], "replace"));
+}
+
+void
+list_all (FILE *out, void *x)
+{
+ datum key;
+ datum data;
+
+ key = gdbm_firstkey (gdbm_file);
+ while (key.dptr)
+ {
+ datum nextkey = gdbm_nextkey (gdbm_file, key);
+
+ data = gdbm_fetch (gdbm_file, key);
+ if (!data.dptr)
+ fprintf (out, "cannot fetch data (key %.*s)\n", key.dsize, key.dptr);
+ else
+ {
+ fprintf (out, "%.*s %.*s\n", key.dsize, key.dptr, data.dsize,
+ data.dptr);
+ free (data.dptr);
+ }
+ free (key.dptr);
+ key = nextkey;
+ }
+}
+
+void
+list_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ page_data (get_record_count (), list_all, NULL);
+}
+
+void
+quit_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ if (gdbm_file != NULL)
+ gdbm_close (gdbm_file);
+
+ exit (0);
+}
+
+void
+export_handler (char *arg[NARGS])
+{
+ int flags = GDBM_WRCREAT;
+
+ if (arg[1] != NULL && strcmp(arg[1], "truncate") == 0)
+ flags = GDBM_NEWDB;
+
+ if (gdbm_export (gdbm_file, arg[0], flags, 0600) == -1)
+ printf ("gdbm_export failed, %s\n", gdbm_strerror (gdbm_errno));
+}
+
+void
+import_handler (char *arg[NARGS])
+{
+ int flag = GDBM_INSERT;
+
+ if (arg[1] != NULL && strcmp(arg[1], "replace") == 0)
+ flag = GDBM_REPLACE;
+
+ if (gdbm_import (gdbm_file, arg[0], flag) == -1)
+ printf ("gdbm_import failed, %s\n", gdbm_strerror (gdbm_errno));
+}
+
+void
+status_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ printf ("Database file: %s\n", file_name);
+ printf ("Zero terminated keys: %s\n", key_z ? "yes" : "no");
+ printf ("Zero terminated data: %s\n", data_z ? "yes" : "no");
+}
+
+void
+key_z_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ key_z = !key_z;
+ printf ("Zero terminated keys: %s\n", key_z ? "yes" : "no");
+}
+
+void
+data_z_handler (char *arg[NARGS] ARG_UNUSED)
+{
+ data_z = !data_z;
+ printf ("Zero terminated data: %s\n", data_z ? "yes" : "no");
+}
+
+
+void help_handler (char *arg[NARGS]);
+
+struct command
+{
+ int abbrev;
+ void (*handler) (char *[NARGS]);
+ char *args[NARGS];
+ char *doc;
+};
+
+
+struct command command_tab[] = {
+ { 'c', count_handler, { NULL, NULL, }, "count (number of entries)" },
+ { 'd', delete_handler, { "key", NULL, }, "delete" },
+ { 'e', export_handler, { "file", "[truncate]", }, "export" },
+ { 'f', fetch_handler, { "key", NULL }, "fetch" },
+ { 'i', import_handler, { "file", "[replace]", }, "import" },
+ { 'l', list_handler, { NULL, NULL }, "list" },
+ { 'n', nextkey_handler, { "[key]", NULL }, "nextkey" },
+ { 'q', quit_handler, { NULL, NULL }, "quit" },
+ { 's', store_handler, { "key", "data" }, "store" },
+ { '1', firstkey_handler, { NULL, NULL }, "firstkey" },
+ { '2', next_on_last_handler, { NULL, NULL, },
+ "nextkey on last key (from n, 1 or 2)" },
+ { '<', read_handler, { "file", "[replace]" },
+ "read entries from file and store" },
+ { 'r', reorganize_handler, { NULL, NULL, }, "reorganize" },
+ { 'z', key_z_handler, { NULL, NULL }, "toggle key nul-termination" },
+ { 'A', avail_handler, { NULL, NULL, }, "print avail list" },
+ { 'B', print_bucket_handler, { "bucket-number", NULL, }, "print a bucket" },
+ { 'C', print_current_bucket_handler, { NULL, NULL, },
+ "print current bucket" },
+ { 'D', print_dir_handler, { NULL, NULL, }, "print hash directory" },
+ { 'F', print_header_handler, { NULL, NULL, }, "print file header" },
+ { 'H', hash_handler, { "key", NULL, }, "hash value of key" },
+ { 'K', print_cache_handler, { NULL, NULL, }, "print the bucket cache" },
+ { 'S', status_handler, { NULL, NULL }, "print current program status" },
+ { 'V', print_version_handler, { NULL, NULL, }, "print version of gdbm" },
+ { 'Z', data_z_handler, { NULL, NULL }, "toggle data nul-termination" },
+ { '?', help_handler, { NULL, NULL, }, "print this help list" },
+ { 'q', quit_handler, { NULL, NULL, }, "quit the program" },
+ { 0 }
+};
+
+#define CMDCOLS 30
+
+void
+format_help_out (FILE *out, void *data)
+{
+ struct command *cmd;
+
+ for (cmd = command_tab; cmd->abbrev; cmd++)
+ {
+ int i;
+ int n = fprintf (out, " %c", cmd->abbrev);
+
+ for (i = 0; i < NARGS && cmd->args[i]; i++)
+ n += fprintf (out, " %s", cmd->args[i]);
+
+ if (n < CMDCOLS)
+ fprintf (out, "%*.s", CMDCOLS-n, "");
+ fprintf (out, " %s", cmd->doc);
+ fputc ('\n', out);
+ }
+}
+
+void
+help_handler (char *arg[NARGS])
+{
+ page_data (sizeof (command_tab) / sizeof (command_tab[0]) + 1,
+ format_help_out, NULL);
+}
+
+struct command *
+find_command (char *p)
+{
+ struct command *cmd;
+ if (p[1])
+ {
+ printf ("Multicharacter commands are not yet implemented.\n");
+ return NULL;
+ }
+ for (cmd = command_tab; cmd->abbrev; cmd++)
+ if (cmd->abbrev == *p)
+ return cmd;
+ return NULL;
+}
+
+#define SKIPWS(p) while (*(p) && isspace (*(p))) (p)++
+#define SKIPWORD(p) while (*(p) && !isspace (*(p))) (p)++
+
+char *
+getword (char *s, char **endp)
+{
+ char *p;
+ SKIPWS (s);
+ p = s;
+ SKIPWORD (s);
+ if (*s)
+ {
+ *s++ = 0;
+ SKIPWS (s);
+ }
+ *endp = s;
+ return p;
+}
+
+/* The test program allows one to call all the routines plus the hash function.
+ The commands are single letter commands. The user is prompted for all other
+ information. See the help command (?) for a list of all commands. */
+
+int
+main (int argc, char *argv[])
+{
+ char cmd_ch;
+
+ datum key_data;
+ datum data_data;
+ datum return_data;
+
+ char cmdbuf[1000];
+
+ int cache_size = DEFAULT_CACHESIZE;
+ int block_size = 0;
+
+ int opt;
+ char reader = FALSE;
+ char newdb = FALSE;
+ int fast = 0;
+
+ progname = strrchr (argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ /* Argument checking. */
+ opterr = 0;
+ while ((opt = getopt (argc, argv, "srnc:b:g:hv")) != -1)
+ switch (opt)
+ {
+ case 'h':
+ usage ();
+ exit (0);
+
+ case 's':
+ fast = GDBM_SYNC;
+ if (reader)
+ error (2, "-s is incompatible with -r");
+ break;
+
+ case 'r':
+ reader = TRUE;
+ if (newdb)
+ error (2, "-r is incompatible with -n");
+ break;
+
+ case 'n':
+ newdb = TRUE;
+ if (reader)
+ error (2, "-n is incompatible with -r");
+ break;
+
+ case 'c':
+ cache_size = atoi (optarg);
+ break;
+
+ case 'b':
+ block_size = atoi (optarg);
+ break;
+
+ case 'g':
+ file_name = optarg;
+ break;
+
+ case 'v':
+ version ();
+ exit (0);
+
+ default:
+ error (2, "unknown option; try `%s -h' for more info\n", progname);
+ }
+
+ if (file_name == NULL)
+ file_name = "junk.gdbm";
+
+ /* Initialize variables. */
+ interactive = isatty (0);
+
+ if (reader)
+ {
+ gdbm_file = gdbm_open (file_name, block_size, GDBM_READER, 00664, NULL);
+ }
+ else if (newdb)
+ {
+ gdbm_file =
+ gdbm_open (file_name, block_size, GDBM_NEWDB | fast, 00664, NULL);
+ }
+ else
+ {
+ gdbm_file =
+ gdbm_open (file_name, block_size, GDBM_WRCREAT | fast, 00664, NULL);
+ }
+ if (gdbm_file == NULL)
+ error (2, "gdbm_open failed: %s", gdbm_strerror (gdbm_errno));
+
+ if (gdbm_setopt (gdbm_file, GDBM_CACHESIZE, &cache_size, sizeof (int)) ==
+ -1)
+ error (2, "gdbm_setopt failed: %s", gdbm_strerror (gdbm_errno));
+
+ signal (SIGPIPE, SIG_IGN);
+
+ /* Welcome message. */
+ if (interactive)
+ printf ("\nWelcome to the gdbm test program. Type ? for help.\n\n");
+
+ while (1)
+ {
+ int i;
+ char *p, *sp;
+ char argbuf[NARGS][128];
+ char *args[NARGS];
+ struct command *cmd;
+
+ if (interactive)
+ printf ("com -> ");
+
+ if (fgets (cmdbuf, sizeof cmdbuf, stdin) == NULL)
+ {
+ putchar ('\n');
+ break;
+ }
+
+ trimnl (cmdbuf);
+ p = getword (cmdbuf, &sp);
+ if (!*p)
+ continue;
+ cmd = find_command (p);
+ if (!cmd)
+ {
+ printf ("Invalid command. Try ? for help.\n");
+ continue;
+ }
+
+ memset (args, 0, sizeof (args));
+ for (i = 0; i < NARGS && cmd->args[i]; i++)
+ {
+ p = i < NARGS-1 ? getword (sp, &sp) : sp;
+ if (!*p)
+ {
+ char *prompt = cmd->args[i];
+ if (*prompt == '[')
+ /* Optional argument */
+ break;
+ if (!interactive)
+ {
+ printf ("%c: not enough arguments\n", cmd->abbrev);
+ exit (1);
+ }
+
+ printf ("%s -> ", prompt);
+ if (fgets (argbuf[i], sizeof argbuf[i], stdin) == NULL)
+ {
+ printf ("unexpected eof\n");
+ exit (0);
+ }
+ trimnl (argbuf[i]);
+ args[i] = argbuf[i];
+ }
+ else
+ args[i] = p;
+ }
+ cmd->handler (args);
+ printf ("\n");
+ }
+
+ /* Quit normally. */
+ quit_handler (NULL);
+
+}

Return to:

Send suggestions and report system problems to the System administrator.