about summary refs log tree commit diff
path: root/db2/progs
diff options
context:
space:
mode:
Diffstat (limited to 'db2/progs')
-rw-r--r--db2/progs/db_archive/db_archive.c165
-rw-r--r--db2/progs/db_checkpoint/db_checkpoint.c246
-rw-r--r--db2/progs/db_deadlock/db_deadlock.c236
-rw-r--r--db2/progs/db_dump/db_dump.c280
-rw-r--r--db2/progs/db_dump185/db_dump185.c322
-rw-r--r--db2/progs/db_load/db_load.c457
-rw-r--r--db2/progs/db_printlog/db_printlog.c160
-rw-r--r--db2/progs/db_recover/db_recover.c122
-rw-r--r--db2/progs/db_stat/db_stat.c434
9 files changed, 2422 insertions, 0 deletions
diff --git a/db2/progs/db_archive/db_archive.c b/db2/progs/db_archive/db_archive.c
new file mode 100644
index 0000000000..136cf2c360
--- /dev/null
+++ b/db2/progs/db_archive/db_archive.c
@@ -0,0 +1,165 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_archive.c	10.12 (Sleepycat) 7/25/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "shqueue.h"
+#include "log.h"
+#include "db_dispatch.h"
+#include "clib_ext.h"
+#include "common_ext.h"
+
+DB_ENV	*db_init __P((char *, int));
+void	 onint __P((int));
+void	 siginit __P((void));
+void	 usage __P((void));
+int	 main __P((int, char *[]));
+
+int	 interrupted;
+const char *progname = "db_archive";			/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB_ENV *dbenv;
+	int ch, flags, verbose;
+	char *home, **list;
+
+	flags = verbose = 0;
+	home = NULL;
+	while ((ch = getopt(argc, argv, "ah:lsv")) != EOF)
+		switch (ch) {
+		case 'a':
+			flags |= DB_ARCH_ABS;
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'l':
+			flags |= DB_ARCH_LOG;
+			break;
+		case 's':
+			flags |= DB_ARCH_DATA;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		usage();
+
+	/* Initialize the environment. */
+	dbenv = db_init(home, verbose);
+
+	/* Get the list of names. */
+	if ((errno = log_archive(dbenv->lg_info, &list, flags, NULL)) != 0) {
+		(void)db_appexit(dbenv);
+		err(1, "log_archive");
+	}
+
+	/* Print the names. */
+	if (list != NULL)
+		for (; *list != NULL; ++list)
+			printf("%s\n", *list);
+
+	return (db_appexit(dbenv) ? 1 : 0);
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home, verbose)
+	char *home;
+	int verbose;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+	dbenv->db_verbose = verbose;
+
+	if ((errno = db_appinit(home, NULL, dbenv,
+	    DB_CREATE | DB_INIT_LOG | DB_INIT_TXN | DB_USE_ENVIRON)) != 0)
+		err(1, "db_appinit");
+
+	siginit();
+
+	return (dbenv);
+}
+
+/*
+ * siginit --
+ *	Initialize the set of signals for which we want to clean up.
+ *	Generally, we try not to leave the shared regions locked if
+ *	we can.
+ */
+void
+siginit()
+{
+#ifdef SIGHUP
+	(void)signal(SIGHUP, onint);
+#endif
+	(void)signal(SIGINT, onint);
+#ifdef SIGKILL
+	(void)signal(SIGKILL, onint);
+#endif
+	(void)signal(SIGTERM, onint);
+}
+
+/*
+ * oninit --
+ *	Interrupt signal handler.
+ */
+void
+onint(signo)
+	int signo;
+{
+	if ((interrupted = signo) == 0)
+		interrupted = SIGINT;
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr, "usage: db_archive [-alsv] [-h home]\n");
+	exit(1);
+}
diff --git a/db2/progs/db_checkpoint/db_checkpoint.c b/db2/progs/db_checkpoint/db_checkpoint.c
new file mode 100644
index 0000000000..586b4b9686
--- /dev/null
+++ b/db2/progs/db_checkpoint/db_checkpoint.c
@@ -0,0 +1,246 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_checkpoint.c	10.9 (Sleepycat) 7/4/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "shqueue.h"
+#include "db_page.h"
+#include "log.h"
+#include "btree.h"
+#include "hash.h"
+#include "clib_ext.h"
+#include "common_ext.h"
+
+char	*check __P((DB_ENV *, long, long));
+int	 checkpoint __P((DB_ENV *, char *, int));
+DB_ENV	*db_init __P((char *));
+int	 logpid __P((char *, int));
+void	 onint __P((int));
+void	 siginit __P((void));
+void	 usage __P((void));
+int	 main __P((int, char *[]));
+
+int	 interrupted;
+time_t	 now;					/* Checkpoint time. */
+const char *progname = "db_checkpoint";		/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB_ENV *dbenv;
+	time_t now;
+	long kbytes, minutes, seconds;
+	int ch, rval, verbose;
+	char *home, *logfile;
+
+	home = logfile = NULL;
+	kbytes = minutes = 0;
+	verbose = 0;
+	while ((ch = getopt(argc, argv, "h:k:L:p:v")) != EOF)
+		switch (ch) {
+		case 'h':
+			home = optarg;
+			break;
+		case 'k':
+			get_long(optarg, 1, LONG_MAX, &kbytes);
+			break;
+		case 'L':
+			logfile = optarg;
+			break;
+		case 'p':
+			get_long(optarg, 1, LONG_MAX, &minutes);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		usage();
+
+	if (kbytes == 0 && minutes == 0) {
+		warnx("at least one of -k and -p must be specified");
+		usage();
+	}
+
+	/* Initialize the environment. */
+	dbenv = db_init(home);
+
+	if (logfile != NULL && logpid(logfile, 1)) {
+		(void)db_appexit(dbenv);
+		return (1);
+	}
+
+	/*
+	 * If we have only a time delay, then we'll sleep the right amount
+	 * to wake up when a checkpoint is necessary.  If we have a "kbytes"
+	 * field set, then we'll check every 30 seconds.
+	 */
+	rval = 0;
+	seconds = kbytes != 0 ? 30 : minutes * 60;
+	while (!interrupted) {
+		(void)__db_sleep(seconds, 0);
+
+		if (verbose) {
+			(void)time(&now);
+			printf("checkpoint: %s", ctime(&now));
+		}
+		rval = txn_checkpoint(dbenv->tx_info, kbytes, minutes);
+		if (rval < 0)
+			break;
+
+		while (rval > 0) {
+			if (verbose)
+				__db_err(dbenv,
+				    "checkpoint did not finish, retrying");
+			(void)__db_sleep(2, 0);
+			rval = txn_checkpoint(dbenv->tx_info, 0, 0);
+		}
+		if (rval < 0)
+			break;
+	}
+
+	if (logfile != NULL && logpid(logfile, 0))
+		rval = 1;
+
+	if (interrupted) {
+		(void)signal(interrupted, SIG_DFL);
+		(void)raise(interrupted);
+		/* NOTREACHED */
+	}
+
+	return (db_appexit(dbenv) || rval ? 1 : 0);
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home)
+	char *home;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+
+	if ((errno = db_appinit(home, NULL, dbenv,
+	   DB_INIT_LOG | DB_INIT_TXN | DB_INIT_MPOOL | DB_USE_ENVIRON)) != 0)
+		err(1, "db_appinit");
+
+	if (memp_register(dbenv->mp_info,
+	    DB_FTYPE_BTREE, __bam_pgin, __bam_pgout) ||
+	    memp_register(dbenv->mp_info,
+	    DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) {
+		(void)db_appexit(dbenv);
+		errx(1,
+		    "db_appinit: failed to register access method functions");
+	}
+
+	siginit();
+
+	return (dbenv);
+}
+
+/*
+ * logpid --
+ *	Log that we're running.
+ */
+int
+logpid(fname, is_open)
+	char *fname;
+	int is_open;
+{
+	FILE *fp;
+	time_t now;
+
+	if (is_open) {
+		if ((fp = fopen(fname, "w")) == NULL) {
+			warn("%s", fname);
+			return (1);
+		}
+		(void)time(&now);
+		fprintf(fp,
+		    "%s: %lu %s", progname, (u_long)getpid(), ctime(&now));
+		fclose(fp);
+	} else
+		(void)remove(fname);
+	return (0);
+}
+
+/*
+ * siginit --
+ *	Initialize the set of signals for which we want to clean up.
+ *	Generally, we try not to leave the shared regions locked if
+ *	we can.
+ */
+void
+siginit()
+{
+#ifdef SIGHUP
+	(void)signal(SIGHUP, onint);
+#endif
+	(void)signal(SIGINT, onint);
+#ifdef SIGKILL
+	(void)signal(SIGKILL, onint);
+#endif
+	(void)signal(SIGTERM, onint);
+}
+
+/*
+ * oninit --
+ *	Interrupt signal handler.
+ */
+void
+onint(signo)
+	int signo;
+{
+	if ((interrupted = signo) == 0)
+		interrupted = SIGINT;
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+    "usage: db_checkpoint [-v] [-h home] [-k kbytes] [-L file] [-p min]\n");
+	exit(1);
+}
diff --git a/db2/progs/db_deadlock/db_deadlock.c b/db2/progs/db_deadlock/db_deadlock.c
new file mode 100644
index 0000000000..9437e3552d
--- /dev/null
+++ b/db2/progs/db_deadlock/db_deadlock.c
@@ -0,0 +1,236 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_deadlock.c	10.13 (Sleepycat) 7/20/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "clib_ext.h"
+#include "common_ext.h"
+
+#define	BAD_KILLID	0xffffffff
+
+DB_ENV	*db_init __P((char *, int));
+void	 onint __P((int));
+void	 siginit __P((void));
+void	 usage __P((void));
+int	 logpid __P((char *, int));
+int	 main __P((int, char *[]));
+
+int	 interrupted;
+const char *progname = "db_deadlock";			/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB_ENV *dbenv;
+	u_int32_t atype;
+	time_t now;
+	long seconds;
+	int ch, flags, verbose;
+	char *home, *logfile;
+
+	atype = DB_LOCK_DEFAULT;
+	home = logfile = NULL;
+	seconds = 0;
+	flags = verbose = 0;
+	while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF)
+		switch (ch) {
+		case 'a':
+			switch (optarg[0]) {
+			case 'o':
+				atype = DB_LOCK_OLDEST;
+				break;
+			case 'y':
+				atype = DB_LOCK_YOUNGEST;
+				break;
+			default:
+				usage();
+				/* NOTREACHED */
+			}
+			if (optarg[1] != '\0')
+				usage();
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'L':
+			logfile = optarg;
+			break;
+		case 't':
+			get_long(optarg, 1, LONG_MAX, &seconds);
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'w':
+			LF_SET(DB_LOCK_CONFLICT);
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		usage();
+
+	if (seconds == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
+		warnx("at least one of -t and -w must be specified");
+		usage();
+	}
+
+	/*
+	 * We detect every second when we're running in DB_LOCK_CONFLICT mode.
+	 */
+	if (seconds == 0)
+		seconds = 1;
+
+	/* Initialize the deadlock detector by opening the lock manager. */
+	dbenv = db_init(home, verbose);
+
+	if (logfile != NULL && logpid(logfile, 1)) {
+		(void)db_appexit(dbenv);
+		return (1);
+	}
+
+	while (!interrupted) {
+		if (dbenv->db_verbose != 0) {
+			time(&now);
+			__db_err(dbenv, "Running at %s", ctime(&now));
+		}
+
+		if ((errno = lock_detect(dbenv->lk_info, flags, atype)) != 0)
+			break;
+
+		/* Make a pass every "seconds" seconds. */
+		(void)__db_sleep(seconds, 0);
+	}
+
+	if (logfile != NULL)
+		(void)logpid(logfile, 0);
+
+	if (interrupted) {
+		(void)signal(interrupted, SIG_DFL);
+		(void)raise(interrupted);
+		/* NOTREACHED */
+	}
+
+	return (db_appexit(dbenv));
+}
+
+DB_ENV *
+db_init(home, verbose)
+	char *home;
+	int verbose;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+	dbenv->db_verbose = verbose;
+
+	if ((errno = db_appinit(home,
+	    NULL, dbenv, DB_INIT_LOCK | DB_USE_ENVIRON)) != 0)
+		err(1, "db_appinit");
+
+	siginit();
+
+	return (dbenv);
+}
+
+/*
+ * logpid --
+ *	Log that we're running.
+ */
+int
+logpid(fname, is_open)
+	char *fname;
+	int is_open;
+{
+	FILE *fp;
+	time_t now;
+
+	if (is_open) {
+		if ((fp = fopen(fname, "w")) == NULL) {
+			warn("%s", fname);
+			return (1);
+		}
+		(void)time(&now);
+		fprintf(fp,
+		    "%s: %lu %s", progname, (u_long)getpid(), ctime(&now));
+		fclose(fp);
+	} else
+		(void)remove(fname);
+	return (0);
+}
+
+/*
+ * siginit --
+ *	Initialize the set of signals for which we want to clean up.
+ *	Generally, we try not to leave the shared regions locked if
+ *	we can.
+ */
+void
+siginit()
+{
+#ifdef SIGHUP
+	(void)signal(SIGHUP, onint);
+#endif
+	(void)signal(SIGINT, onint);
+#ifdef SIGKILL
+	(void)signal(SIGKILL, onint);
+#endif
+	(void)signal(SIGTERM, onint);
+}
+
+/*
+ * oninit --
+ *	Interrupt signal handler.
+ */
+void
+onint(signo)
+	int signo;
+{
+	if ((interrupted = signo) == 0)
+		interrupted = SIGINT;
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr,
+    "usage: db_deadlock [-vw] [-a m | o | y] [-h home] [-L file] [-t sec]\n");
+	exit(1);
+}
diff --git a/db2/progs/db_dump/db_dump.c b/db2/progs/db_dump/db_dump.c
new file mode 100644
index 0000000000..d60aa9b5c9
--- /dev/null
+++ b/db2/progs/db_dump/db_dump.c
@@ -0,0 +1,280 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_dump.c	10.13 (Sleepycat) 8/19/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "db_page.h"
+#include "btree.h"
+#include "hash.h"
+#include "clib_ext.h"
+
+void	configure __P((char *));
+DB_ENV *db_init __P((char *));
+void	dbt_dump __P((DBT *));
+void	dbt_print __P((DBT *));
+void	pheader __P((DB *, int));
+void	usage __P((void));
+int	main __P((int, char *[]));
+
+const char *progname = "db_dump";		/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB *dbp;
+	DBC *dbcp;
+	DBT key, data;
+	DB_ENV *dbenv;
+	int ch, dflag, pflag;
+	char *home;
+
+	home = NULL;
+	dflag = pflag = 0;
+	while ((ch = getopt(argc, argv, "df:h:p")) != EOF)
+		switch (ch) {
+		case 'd':
+			dflag = 1;
+			break;
+		case 'f':
+			if (freopen(optarg, "w", stdout) == NULL)
+				err(1, "%s", optarg);
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'p':
+			pflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 1)
+		usage();
+
+	if (dflag) {
+		if (home != NULL)
+			errx(1,
+			    "the -d and -h options may not both be specified");
+		if (pflag)
+			errx(1,
+			    "the -d and -p options may not both be specified");
+	}
+	/* Initialize the environment. */
+	dbenv = dflag ? NULL : db_init(home);
+
+	/* Open the DB file. */
+	if ((errno =
+	    db_open(argv[0], DB_UNKNOWN, DB_RDONLY, 0, dbenv, NULL, &dbp)) != 0)
+		err(1, "%s", argv[0]);
+
+	/* DB dump. */
+	if (dflag) {
+		(void)__db_dump(dbp, NULL, 1);
+		if ((errno = dbp->close(dbp, 0)) != 0)
+			err(1, "close");
+		exit (0);
+	}
+
+	/* Get a cursor and step through the database. */
+	if ((errno = dbp->cursor(dbp, NULL, &dbcp)) != 0) {
+		(void)dbp->close(dbp, 0);
+		err(1, "cursor");
+	}
+
+	/* Print out the header. */
+	pheader(dbp, pflag);
+
+	/* Print out the key/data pairs. */
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	if (pflag)
+		while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
+			if (dbp->type != DB_RECNO)
+				dbt_print(&key);
+			dbt_print(&data);
+		}
+	else
+		while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) {
+			if (dbp->type != DB_RECNO)
+				dbt_dump(&key);
+			dbt_dump(&data);
+		}
+	if (errno != DB_NOTFOUND)
+		err(1, "cursor get");
+
+	if ((errno = dbp->close(dbp, 0)) != 0)
+		err(1, "close");
+	return (0);
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home)
+	char *home;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+
+	if ((errno =
+	    db_appinit(home, NULL, dbenv, DB_CREATE | DB_USE_ENVIRON)) != 0)
+		err(1, "db_appinit");
+	return (dbenv);
+}
+
+/*
+ * pheader --
+ *	Write out the header information.
+ */
+void
+pheader(dbp, pflag)
+	DB *dbp;
+	int pflag;
+{
+	DB_BTREE_STAT *btsp;
+	HTAB *hashp;
+	HASHHDR *hdr;
+	db_pgno_t pgno;
+
+	printf("format=%s\n", pflag ? "print" : "bytevalue");
+	switch (dbp->type) {
+	case DB_BTREE:
+		printf("type=btree\n");
+		if ((errno = dbp->stat(dbp, &btsp, NULL, 0)) != 0)
+			err(1, "dbp->stat");
+		if (F_ISSET(dbp, DB_BT_RECNUM))
+			printf("recnum=1\n");
+		if (btsp->bt_maxkey != 0)
+			printf("bt_maxkey=%lu\n", (u_long)btsp->bt_maxkey);
+		if (btsp->bt_minkey != 0)
+			printf("bt_minkey=%lu\n", (u_long)btsp->bt_minkey);
+		break;
+	case DB_HASH:
+		printf("type=hash\n");
+		hashp = dbp->internal;
+		pgno = PGNO_METADATA;
+		if (memp_fget(dbp->mpf, &pgno, 0, &hdr) == 0) {
+			if (hdr->ffactor != 0)
+				printf("h_ffactor=%lu\n", (u_long)hdr->ffactor);
+			if (hdr->nelem != 0)
+				printf("h_nelem=%lu\n", (u_long)hdr->nelem);
+			(void)memp_fput(dbp->mpf, hdr, 0);
+		}
+		break;
+	case DB_RECNO:
+		printf("type=recno\n");
+		if (F_ISSET(dbp, DB_RE_RENUMBER))
+			printf("renumber=1\n");
+		if (F_ISSET(dbp, DB_RE_FIXEDLEN))
+			printf("re_len=%lu\n", (u_long)btsp->bt_re_len);
+		if (F_ISSET(dbp, DB_RE_PAD))
+			printf("re_pad=%#x\n", btsp->bt_re_pad);
+		break;
+	case DB_UNKNOWN:
+		abort();
+		/* NOTREACHED */
+	}
+
+	if (F_ISSET(dbp, DB_AM_DUP))
+		printf("duplicates=1\n");
+
+	if (dbp->dbenv->db_lorder != 0)
+		printf("db_lorder=%lu\n", (u_long)dbp->dbenv->db_lorder);
+
+	if (!F_ISSET(dbp, DB_AM_PGDEF))
+		printf("db_pagesize=%lu\n", (u_long)dbp->pgsize);
+
+	printf("HEADER=END\n");
+}
+
+static char hex[] = "0123456789abcdef";
+
+/*
+ * dbt_dump --
+ *	Write out a key or data item using byte values.
+ */
+void
+dbt_dump(dbtp)
+	DBT *dbtp;
+{
+	u_int32_t len;
+	u_int8_t *p;
+
+	for (len = dbtp->size, p = dbtp->data; len--; ++p)
+		(void)printf("%c%c",
+		    hex[(u_int8_t)(*p & 0xf0) >> 4], hex[*p & 0x0f]);
+	printf("\n");
+}
+
+/*
+ * dbt_print --
+ *	Write out a key or data item using printable characters.
+ */
+void
+dbt_print(dbtp)
+	DBT *dbtp;
+{
+	u_int32_t len;
+	u_int8_t *p;
+
+	for (len = dbtp->size, p = dbtp->data; len--; ++p)
+		if (isprint(*p)) {
+			if (*p == '\\')
+				(void)printf("\\");
+			(void)printf("%c", *p);
+		} else
+			(void)printf("\\%c%c",
+			    hex[(u_int8_t)(*p & 0xf0) >> 4], hex[*p & 0x0f]);
+	printf("\n");
+}
+
+/*
+ * usage --
+ *	Display the usage message.
+ */
+void
+usage()
+{
+	(void)fprintf(stderr,
+	    "usage: db_dump [-dp] [-f file] [-h home] db_file\n");
+	exit(1);
+}
diff --git a/db2/progs/db_dump185/db_dump185.c b/db2/progs/db_dump185/db_dump185.c
new file mode 100644
index 0000000000..f3c1187e45
--- /dev/null
+++ b/db2/progs/db_dump185/db_dump185.c
@@ -0,0 +1,322 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_dump185.c	10.5 (Sleepycat) 7/2/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "db_185.h"
+#include "clib_ext.h"
+
+/* Hash Table Information */
+typedef struct hashhdr {		/* Disk resident portion */
+	int		magic;		/* Magic NO for hash tables */
+	int		version;	/* Version ID */
+	u_int32_t	lorder;		/* Byte Order */
+	int		bsize;		/* Bucket/Page Size */
+	int		bshift;		/* Bucket shift */
+	int		dsize;		/* Directory Size */
+	int		ssize;		/* Segment Size */
+	int		sshift;		/* Segment shift */
+	int		ovfl_point;	/* Where overflow pages are being
+					 * allocated */
+	int		last_freed;	/* Last overflow page freed */
+	int		max_bucket;	/* ID of Maximum bucket in use */
+	int		high_mask;	/* Mask to modulo into entire table */
+	int		low_mask;	/* Mask to modulo into lower half of
+					 * table */
+	int		ffactor;	/* Fill factor */
+	int		nkeys;		/* Number of keys in hash table */
+} HASHHDR;
+
+typedef struct htab	 {		/* Memory resident data structure */
+	HASHHDR 	hdr;		/* Header */
+} HTAB;
+
+typedef struct _epgno {
+	u_int32_t pgno;			/* the page number */
+	u_int16_t index;		/* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+	void	*page;			/* the (pinned) page */
+	u_int16_t index;		/* the index on the page */
+} EPG;
+
+typedef struct _cursor {
+	EPGNO	 pg;			/* B: Saved tree reference. */
+	DBT	 key;			/* B: Saved key, or key.data == NULL. */
+	u_int32_t rcursor;		/* R: recno cursor (1-based) */
+
+#define	CURS_ACQUIRE	0x01		/*  B: Cursor needs to be reacquired. */
+#define	CURS_AFTER	0x02		/*  B: Unreturned cursor after key. */
+#define	CURS_BEFORE	0x04		/*  B: Unreturned cursor before key. */
+#define	CURS_INIT	0x08		/* RB: Cursor initialized. */
+	u_int8_t flags;
+} CURSOR;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+	void	 *bt_mp;		/* memory pool cookie */
+
+	void	 *bt_dbp;		/* pointer to enclosing DB */
+
+	EPG	  bt_cur;		/* current (pinned) page */
+	void	 *bt_pinned;		/* page pinned across calls */
+
+	CURSOR	  bt_cursor;		/* cursor */
+
+	EPGNO	  bt_stack[50];		/* stack of parent pages */
+	EPGNO	 *bt_sp;		/* current stack pointer */
+
+	DBT	  bt_rkey;		/* returned key */
+	DBT	  bt_rdata;		/* returned data */
+
+	int	  bt_fd;		/* tree file descriptor */
+
+	u_int32_t bt_free;		/* next free page */
+	u_int32_t bt_psize;		/* page size */
+	u_int16_t bt_ovflsize;		/* cut-off for key/data overflow */
+	int	  bt_lorder;		/* byte order */
+					/* sorted order */
+	enum { NOT, BACK, FORWARD } bt_order;
+	EPGNO	  bt_last;		/* last insert */
+
+					/* B: key comparison function */
+	int	(*bt_cmp) __P((const DBT *, const DBT *));
+					/* B: prefix comparison function */
+	size_t	(*bt_pfx) __P((const DBT *, const DBT *));
+					/* R: recno input function */
+	int	(*bt_irec) __P((struct _btree *, u_int32_t));
+
+	FILE	 *bt_rfp;		/* R: record FILE pointer */
+	int	  bt_rfd;		/* R: record file descriptor */
+
+	void	 *bt_cmap;		/* R: current point in mapped space */
+	void	 *bt_smap;		/* R: start of mapped space */
+	void	 *bt_emap;		/* R: end of mapped space */
+	size_t	  bt_msize;		/* R: size of mapped region. */
+
+	u_int32_t bt_nrecs;		/* R: number of records */
+	size_t	  bt_reclen;		/* R: fixed record length */
+	u_char	  bt_bval;		/* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define	B_INMEM		0x00001		/* in-memory tree */
+#define	B_METADIRTY	0x00002		/* need to write metadata */
+#define	B_MODIFIED	0x00004		/* tree modified */
+#define	B_NEEDSWAP	0x00008		/* if byte order requires swapping */
+#define	B_RDONLY	0x00010		/* read-only tree */
+
+#define	B_NODUPS	0x00020		/* no duplicate keys permitted */
+#define	R_RECNO		0x00080		/* record oriented tree */
+
+#define	R_CLOSEFP	0x00040		/* opened a file pointer */
+#define	R_EOF		0x00100		/* end of input file reached. */
+#define	R_FIXLEN	0x00200		/* fixed length records */
+#define	R_MEMMAPPED	0x00400		/* memory mapped file. */
+#define	R_INMEM		0x00800		/* in-memory file */
+#define	R_MODIFIED	0x01000		/* modified file */
+#define	R_RDONLY	0x02000		/* read-only file */
+
+#define	B_DB_LOCK	0x04000		/* DB_LOCK specified. */
+#define	B_DB_SHMEM	0x08000		/* DB_SHMEM specified. */
+#define	B_DB_TXN	0x10000		/* DB_TXN specified. */
+	u_int32_t flags;
+} BTREE;
+
+void db_185_btree __P((DB *, int));
+void db_185_hash __P((DB *, int));
+void dbt_dump __P((DBT *));
+void dbt_print __P((DBT *));
+void usage __P((void));
+int main __P((int, char *[]));
+
+const char *progname = "db_dump185";		/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB *dbp;
+	DBT key, data;
+	int ch, pflag, rval;
+
+	pflag = 0;
+	while ((ch = getopt(argc, argv, "f:p")) != EOF)
+		switch (ch) {
+		case 'f':
+			if (freopen(optarg, "w", stdout) == NULL)
+				err(1, "%s", optarg);
+			break;
+		case 'p':
+			pflag = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 1)
+		usage();
+
+	if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
+		if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+			return (1);
+		db_185_hash(dbp, pflag);
+	} else
+		db_185_btree(dbp, pflag);
+
+	/*
+	 * !!!
+	 * DB 1.85 DBTs are a subset of DB 2.0 DBTs, so we just use the
+	 * new dump/print routines.
+	 */
+	if (pflag)
+		while (!(rval = dbp->seq(dbp, &key, &data, R_NEXT))) {
+			dbt_print(&key);
+			dbt_print(&data);
+		}
+	else
+		while (!(rval = dbp->seq(dbp, &key, &data, R_NEXT))) {
+			dbt_dump(&key);
+			dbt_dump(&data);
+		}
+
+	if (rval == -1)
+		err(1, "seq");
+	return (0);
+}
+
+/*
+ * db_185_hash --
+ *	Dump out hash header information.
+ */
+void
+db_185_hash(dbp, pflag)
+	DB *dbp;
+	int pflag;
+{
+	HTAB *hashp;
+
+	hashp = dbp->internal;
+
+	printf("format=%s\n", pflag ? "print" : "bytevalue");
+	printf("type=hash\n");
+	printf("h_ffactor=%lu\n", (u_long)hashp->hdr.ffactor);
+#ifdef NOT_AVAILABLE_IN_DB_185
+	printf("h_nelem=%lu\n", (u_long)hashp->hdr.nelem);
+#endif
+	if (hashp->hdr.lorder != 0)
+		printf("db_lorder=%lu\n", (u_long)hashp->hdr.lorder);
+	printf("db_pagesize=%lu\n", (u_long)hashp->hdr.bsize);
+	printf("HEADER=END\n");
+}
+
+/*
+ * db_185_btree --
+ *	Dump out btree header information.
+ */
+void
+db_185_btree(dbp, pflag)
+	DB *dbp;
+	int pflag;
+{
+	BTREE *btp;
+
+	btp = dbp->internal;
+
+	printf("format=%s\n", pflag ? "print" : "bytevalue");
+	printf("type=btree\n");
+#ifdef NOT_AVAILABLE_IN_185
+	printf("bt_minkey=%lu\n", (u_long)XXX);
+	printf("bt_maxkey=%lu\n", (u_long)XXX);
+#endif
+	if (btp->bt_lorder != 0)
+		printf("db_lorder=%lu\n", (u_long)btp->bt_lorder);
+	printf("db_pagesize=%lu\n", (u_long)btp->bt_psize);
+	if (!(btp->flags & B_NODUPS))
+		printf("duplicates=1\n");
+	printf("HEADER=END\n");
+}
+
+static char hex[] = "0123456789abcdef";
+
+/*
+ * dbt_dump --
+ *	Write out a key or data item using byte values.
+ */
+void
+dbt_dump(dbtp)
+	DBT *dbtp;
+{
+	size_t len;
+	u_int8_t *p;
+
+	for (len = dbtp->size, p = dbtp->data; len--; ++p)
+		(void)printf("%c%c",
+		    hex[(*p & 0xf0) >> 4], hex[*p & 0x0f]);
+	printf("\n");
+}
+
+/*
+ * dbt_print --
+ *	Write out a key or data item using printable characters.
+ */
+void
+dbt_print(dbtp)
+	DBT *dbtp;
+{
+	size_t len;
+	u_int8_t *p;
+
+	for (len = dbtp->size, p = dbtp->data; len--; ++p)
+		if (isprint(*p)) {
+			if (*p == '\\')
+				(void)printf("\\");
+			(void)printf("%c", *p);
+		} else
+			(void)printf("\\%c%c",
+			    hex[(*p & 0xf0) >> 4], hex[*p & 0x0f]);
+	printf("\n");
+}
+
+/*
+ * usage --
+ *	Display the usage message.
+ */
+void
+usage()
+{
+	(void)fprintf(stderr, "usage: db_dump [-p] [-f file] db_file\n");
+	exit(1);
+}
diff --git a/db2/progs/db_load/db_load.c b/db2/progs/db_load/db_load.c
new file mode 100644
index 0000000000..cc90e7bd27
--- /dev/null
+++ b/db2/progs/db_load/db_load.c
@@ -0,0 +1,457 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_load.c	10.9 (Sleepycat) 8/19/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "db_int.h"
+#include "clib_ext.h"
+
+void	badnum __P((void));
+void	configure __P((DB_INFO *, char **));
+DB_ENV *db_init __P((char *));
+int	dbt_rdump __P((DBT *));
+int	dbt_rprint __P((DBT *));
+int	digitize __P((int));
+void	rheader __P((DBTYPE *, int *, DB_INFO *));
+void	usage __P((void));
+int	main __P((int, char *[]));
+
+const char *progname = "db_load";		/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB *dbp;
+	DBT key, data;
+	DBTYPE argtype, headertype;
+	DB_ENV *dbenv;
+	DB_INFO dbinfo;
+	db_recno_t recno;
+	int ch, pflag;
+	char **clist, **clp, *home;
+
+	/* Allocate enough room for configuration arguments. */
+	if ((clp = clist = calloc(argc + 1, sizeof(char *))) == NULL)
+		err(1, NULL);
+
+	home = NULL;
+	argtype = DB_UNKNOWN;
+	while ((ch = getopt(argc, argv, "c:f:h:t:")) != EOF)
+		switch (ch) {
+		case 'c':
+			*clp++ = optarg;
+			break;
+		case 'f':
+			if (freopen(optarg, "r", stdin) == NULL)
+				err(1, "%s", optarg);
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 't':
+			if (strcmp(optarg, "btree") == 0) {
+				argtype = DB_BTREE;
+				break;
+			}
+			if (strcmp(optarg, "hash") == 0) {
+				argtype = DB_HASH;
+				break;
+			}
+			usage();
+			/* NOTREACHED */
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 1)
+		usage();
+
+	/* Initialize the environment. */
+	dbenv = db_init(home);
+	memset(&dbinfo, 0, sizeof(DB_INFO));
+
+	/* Read the header. */
+	rheader(&headertype, &pflag, &dbinfo);
+
+	/* Apply command-line configuration changes. */
+	configure(&dbinfo, clist);
+
+	/* Conversion to/from recno is prohibited. */
+	if (argtype != DB_UNKNOWN) {
+		if (headertype == DB_RECNO)
+			errx(1, "databases of type recno may not be converted");
+		headertype = argtype;
+	}
+
+	/* Open the DB file. */
+	if ((errno = db_open(argv[0], headertype, DB_CREATE | DB_TRUNCATE,
+	    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
+	    dbenv, &dbinfo, &dbp)) != 0)
+		err(1, "%s", argv[0]);
+
+	/* Initialize the key/data pair. */
+	memset(&key, 0, sizeof(DBT));
+	if ((key.data = (void *)malloc(key.ulen = 1024)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	memset(&data, 0, sizeof(DBT));
+	if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+
+	/* Get each key/data pair and add them to the database. */
+	if (headertype == DB_RECNO) {
+		key.data = &recno;
+		key.size = sizeof(recno);
+		for (recno = 1;; ++recno) {
+			if (pflag) {
+				if (dbt_rprint(&data))
+					break;
+			} else
+				if (dbt_rdump(&data))
+					break;
+			if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
+				err(1, "%s", argv[0]);
+		}
+	} else
+		for (;;) {
+			if (pflag) {
+				if (dbt_rprint(&key))
+					break;
+				if (dbt_rprint(&data))
+					goto fmt;
+			} else {
+				if (dbt_rdump(&key))
+					break;
+				if (dbt_rdump(&data))
+fmt:					err(1, "odd number of key/data pairs");
+			}
+			if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
+				err(1, "%s", argv[0]);
+		}
+
+	if ((errno = dbp->close(dbp, 0)) != 0)
+		err(1, "%s", argv[0]);
+	return (0);
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home)
+	char *home;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+
+	if ((errno =
+	    db_appinit(home, NULL, dbenv, DB_CREATE | DB_USE_ENVIRON)) != 0)
+		err(1, "db_appinit");
+	return (dbenv);
+}
+
+#define	FLAG(name, value, keyword, flag)				\
+	if (strcmp(name, keyword) == 0) {				\
+		switch (*value) {					\
+		case '1':						\
+			dbinfop->flags |= (flag);			\
+			break;						\
+		case '0':						\
+			dbinfop->flags &= ~(flag);			\
+			break;						\
+		default:						\
+			badnum();					\
+			/* NOTREACHED */				\
+		}							\
+		continue;						\
+	}
+#define	NUMBER(name, value, keyword, field, flag)			\
+	if (strcmp(name, keyword) == 0) {				\
+		get_long(value, 1, LONG_MAX, &val);			\
+		dbinfop->field = val;					\
+		if (flag != 0)						\
+			dbinfop->flags |= (flag);			\
+		continue;						\
+	}
+#define	STRING(name, value, keyword, field, flag)			\
+	if (strcmp(name, keyword) == 0) {				\
+		dbinfop->field = value[0];				\
+		if (flag != 0)						\
+			dbinfop->flags |= (flag);			\
+		continue;						\
+	}
+
+/*
+ * configure --
+ *	Handle command-line configuration options.
+ */
+void
+configure(dbinfop, clp)
+	DB_INFO *dbinfop;
+	char **clp;
+{
+	long val;
+	char *name, *value;
+
+	for (; (name = *clp) != NULL; ++clp) {
+		if ((value = strchr(name, '=')) == NULL)
+			errx(1,
+		    "command-line configuration uses name=value format");
+		*value++ = '\0';
+
+		NUMBER(name, value, "bt_maxkey", bt_maxkey, 0);
+		NUMBER(name, value, "bt_minkey", bt_minkey, 0);
+		NUMBER(name, value, "db_lorder", db_lorder, 0);
+		NUMBER(name, value, "db_pagesize", db_pagesize, 0);
+		FLAG(name, value, "duplicates", DB_DUP);
+		NUMBER(name, value, "h_ffactor", h_ffactor, 0);
+		NUMBER(name, value, "h_nelem", h_nelem, 0);
+		NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN);
+		STRING(name, value, "re_pad", re_pad, DB_PAD);
+		FLAG(name, value, "recnum", DB_RECNUM);
+		FLAG(name, value, "renumber", DB_RENUMBER);
+
+		errx(1, "unknown command-line configuration keyword");
+	}
+}
+
+/*
+ * rheader --
+ *	Read the header message.
+ */
+void
+rheader(dbtypep, pflagp, dbinfop)
+	DBTYPE *dbtypep;
+	int *pflagp;
+	DB_INFO *dbinfop;
+{
+	long lineno, val;
+	char name[256], value[256];
+
+	*dbtypep = DB_UNKNOWN;
+	*pflagp = 0;
+
+	for (lineno = 1;; ++lineno) {
+		if (fscanf(stdin, "%[^=]=%s\n", name, value) != 2)
+			errx(1, "line %lu: unexpected line", lineno);
+		if (strcmp(name, "HEADER") == 0)
+			break;
+
+		if (strcmp(name, "format") == 0) {
+			if (strcmp(value, "bytevalue") == 0) {
+				*pflagp = 0;
+				continue;
+			}
+			if (strcmp(value, "print") == 0) {
+				*pflagp = 1;
+				continue;
+			}
+			errx(1, "line %d: unknown format", lineno);
+		}
+		if (strcmp(name, "type") == 0) {
+			if (strcmp(value, "btree") == 0) {
+				*dbtypep = DB_BTREE;
+				continue;
+			}
+			if (strcmp(value, "hash") == 0) {
+				*dbtypep = DB_HASH;
+				continue;
+			}
+			if (strcmp(value, "recno") == 0) {
+				*dbtypep = DB_RECNO;
+				continue;
+			}
+			errx(1, "line %d: unknown type", lineno);
+		}
+		NUMBER(name, value, "bt_maxkey", bt_maxkey, 0);
+		NUMBER(name, value, "bt_minkey", bt_minkey, 0);
+		NUMBER(name, value, "db_lorder", db_lorder, 0);
+		NUMBER(name, value, "db_pagesize", db_pagesize, 0);
+		FLAG(name, value, "duplicates", DB_DUP);
+		NUMBER(name, value, "h_ffactor", h_ffactor, 0);
+		NUMBER(name, value, "h_nelem", h_nelem, 0);
+		NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN);
+		STRING(name, value, "re_pad", re_pad, DB_PAD);
+		FLAG(name, value, "recnum", DB_RECNUM);
+		FLAG(name, value, "renumber", DB_RENUMBER);
+
+		errx(1, "unknown input-file header configuration keyword");
+	}
+}
+
+/*
+ * dbt_rprint --
+ *	Read a printable line into a DBT structure.
+ */
+int
+dbt_rprint(dbtp)
+	DBT *dbtp;
+{
+	u_int32_t len;
+	u_int8_t *p;
+	int c1, c2, escape;
+
+	escape = 0;
+	for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
+		if (c1 == EOF) {
+			if (len == 0)
+				return (1);
+			err(1, "unexpected end of key/data pair");
+		}
+		if (escape) {
+			if (c1 != '\\') {
+				if ((c2 = getchar()) == EOF)
+					err(1,
+					    "unexpected end of key/data pair");
+				c1 = digitize(c1) << 4 | digitize(c2);
+			}
+			escape = 0;
+		} else
+			if (c1 == '\\') {
+				escape = 1;
+				continue;
+			}
+		if (++len >= dbtp->ulen - 10) {
+			dbtp->ulen *= 2;
+			if ((dbtp->data =
+			    (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
+				errno = ENOMEM;
+				err(1, NULL);
+			}
+			p = (u_int8_t *)dbtp->data + len;
+		}
+		*p++ = c1;
+	}
+	dbtp->size = len;
+	return (0);
+}
+
+/*
+ * digitize --
+ *	Convert a character to an integer.
+ */
+int
+digitize(c)
+	int c;
+{
+	switch (c) {			/* Don't depend on ASCII ordering. */
+	case '0': return (0);
+	case '1': return (1);
+	case '2': return (2);
+	case '3': return (3);
+	case '4': return (4);
+	case '5': return (5);
+	case '6': return (6);
+	case '7': return (7);
+	case '8': return (8);
+	case '9': return (9);
+	case 'a': return (10);
+	case 'b': return (11);
+	case 'c': return (12);
+	case 'd': return (13);
+	case 'e': return (14);
+	case 'f': return (15);
+	}
+
+	err(1, "unexpected hexadecimal value");
+	/* NOTREACHED */
+
+	return (0);
+}
+
+/*
+ * dbt_rdump --
+ *	Read a byte dump line into a DBT structure.
+ */
+int
+dbt_rdump(dbtp)
+	DBT *dbtp;
+{
+	u_int32_t len;
+	u_int8_t *p;
+	int c1, c2;
+
+	for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) {
+		if (c1 == EOF) {
+			if (len == 0)
+				return (1);
+			err(1, "unexpected end of key/data pair");
+		}
+		if ((c2 = getchar()) == EOF)
+			err(1, "unexpected end of key/data pair");
+		if (++len >= dbtp->ulen - 10) {
+			dbtp->ulen *= 2;
+			if ((dbtp->data =
+			    (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) {
+				errno = ENOMEM;
+				err(1, NULL);
+			}
+			p = (u_int8_t *)dbtp->data + len;
+		}
+		*p++ = digitize(c1) << 4 | digitize(c2);
+	}
+	dbtp->size = len;
+	return (0);
+}
+
+/*
+ * badnum --
+ *	Display the bad number message.
+ */
+void
+badnum()
+{
+	err(1, "boolean name=value pairs require a value of 0 or 1");
+}
+
+/*
+ * usage --
+ *	Display the usage message.
+ */
+void
+usage()
+{
+	(void)fprintf(stderr,
+"usage: db_load [-c name=value] [-f file] [-h home] [-t btree | hash] db_file\n");
+	exit(1);
+}
diff --git a/db2/progs/db_printlog/db_printlog.c b/db2/progs/db_printlog/db_printlog.c
new file mode 100644
index 0000000000..12c365524f
--- /dev/null
+++ b/db2/progs/db_printlog/db_printlog.c
@@ -0,0 +1,160 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_printlog.c	10.8 (Sleepycat) 7/15/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "shqueue.h"
+#include "db_page.h"
+#include "btree.h"
+#include "hash.h"
+#include "log.h"
+#include "txn.h"
+#include "db_am.h"
+#include "clib_ext.h"
+
+DB_ENV *db_init __P((char *));
+void	onint __P((int));
+void	usage __P((void));
+
+int	 interrupted;
+char	*progname = "db_printlog";			/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB_ENV *dbenv;
+	DBT data;
+	DB_LSN key;
+	int ch, eval;
+	char *home;
+
+	home = NULL;
+	while ((ch = getopt(argc, argv, "h:")) != EOF)
+		switch (ch) {
+		case 'h':
+			home = optarg;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if ((home != NULL && argc > 0) || argc > 1)
+		usage();
+
+	/* XXX: backward compatibility, first argument is home. */
+	if (argc == 1)
+		home = argv[0];
+
+	dbenv = db_init(home);
+
+	eval = 0;
+	if ((errno = __bam_init_print(dbenv)) != 0 ||
+	    (errno = __db_init_print(dbenv)) != 0 ||
+	    (errno = __ham_init_print(dbenv)) != 0 ||
+	    (errno = __log_init_print(dbenv)) != 0 ||
+	    (errno = __txn_init_print(dbenv)) != 0) {
+		warn("initialization");
+		eval = 1;
+		(void)db_appexit(dbenv);
+	}
+
+	(void)signal(SIGINT, onint);
+
+	memset(&data, 0, sizeof(data));
+	while (!interrupted) {
+		if ((errno =
+		    log_get(dbenv->lg_info, &key, &data, DB_NEXT)) != 0) {
+			if (errno == DB_NOTFOUND)
+				break;
+			eval = 1;
+			warn("log_get");
+			break;
+		}
+		if ((errno =
+		    __db_dispatch(dbenv->lg_info, &data, &key, 0, NULL)) != 0) {
+			eval = 1;
+			warn("dispatch");
+			break;
+		}
+	}
+
+	(void)db_appexit(dbenv);
+
+	if (interrupted) {
+		(void)signal(SIGINT, SIG_DFL);
+		(void)raise(SIGINT);
+		/* NOTREACHED */
+	}
+	exit (eval);
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home)
+	char *home;
+{
+	DB_ENV *dbenv;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+
+	if ((errno =
+	    db_appinit(home, NULL, dbenv, DB_CREATE | DB_INIT_LOG)) != 0)
+		err(1, "db_appinit");
+	return (dbenv);
+}
+
+/*
+ * oninit --
+ *	Interrupt signal handler.
+ */
+void
+onint(signo)
+	int signo;
+{
+	signo = 1;			/* XXX: Shut the compiler up. */
+	interrupted = 1;
+}
+
+void
+usage()
+{
+	fprintf(stderr, "usage: db_printlog [-h home]\n");
+	exit (1);
+}
diff --git a/db2/progs/db_recover/db_recover.c b/db2/progs/db_recover/db_recover.c
new file mode 100644
index 0000000000..4ac5925f79
--- /dev/null
+++ b/db2/progs/db_recover/db_recover.c
@@ -0,0 +1,122 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_recover.c	10.12 (Sleepycat) 7/27/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <time.h>
+#endif
+
+#include "db_int.h"
+#include "txn.h"
+#include "common_ext.h"
+#include "clib_ext.h"
+
+DB_ENV	*db_init __P((char *, int, int));
+void	 usage __P((void));
+int	 main __P((int, char *[]));
+
+const char *progname = "db_recover";			/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB_ENV *dbenv;
+	time_t now;
+	int ch, flags, verbose;
+	char *home;
+
+	home = NULL;
+	flags = verbose = 0;
+	while ((ch = getopt(argc, argv, "ch:v")) != EOF)
+		switch (ch) {
+		case 'c':
+			LF_SET(DB_RECOVER_FATAL);
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0)
+		usage();
+
+	dbenv = db_init(home, flags, verbose);
+	if (verbose) {
+		__db_err(dbenv, "Recovery complete at %s", ctime(&now));
+		__db_err(dbenv, "%s %lu %s [%lu][%lu]",
+		    "Maximum transaction id",
+		    (u_long)dbenv->tx_info->region->last_txnid,
+		    "Recovery checkpoint",
+		    (u_long)dbenv->tx_info->region->last_ckp.file,
+		    (u_long)dbenv->tx_info->region->last_ckp.offset);
+	}
+
+	exit (db_appexit(dbenv));
+}
+
+DB_ENV *
+db_init(home, flags, verbose)
+	char *home;
+	int flags, verbose;
+{
+	DB_ENV *dbenv;
+	int local_flags;
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = "db_recover";
+	dbenv->db_verbose = verbose;
+
+	/* Initialize environment for pathnames only. */
+	local_flags = DB_CREATE | DB_INIT_LOG |
+	    DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_USE_ENVIRON;
+
+	if (LF_ISSET(DB_RECOVER_FATAL))
+		local_flags |= DB_RECOVER_FATAL;
+	else
+		local_flags |= DB_RECOVER;
+
+	if ((errno = db_appinit(home, NULL, dbenv, local_flags)) != 0)
+		err(1, "appinit failed");
+
+	return (dbenv);
+}
+
+void
+usage()
+{
+	(void)fprintf(stderr, "usage: db_recover [-cv] [-h home]\n");
+	exit(1);
+}
diff --git a/db2/progs/db_stat/db_stat.c b/db2/progs/db_stat/db_stat.c
new file mode 100644
index 0000000000..5c7044dbce
--- /dev/null
+++ b/db2/progs/db_stat/db_stat.c
@@ -0,0 +1,434 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 1997
+ *	Sleepycat Software.  All rights reserved.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1997\n\
+	Sleepycat Software Inc.  All rights reserved.\n";
+static const char sccsid[] = "@(#)db_stat.c	8.17 (Sleepycat) 8/24/97";
+#endif
+
+#ifndef NO_SYSTEM_INCLUDES
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#endif
+
+#include "db_int.h"
+#include "clib_ext.h"
+
+#define	DIVIDER	"=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
+
+typedef enum { T_NOTSET, T_DB, T_MPOOL, T_TXN } test_t;
+
+void	bstat __P((DB *));
+DB_ENV *db_init __P((char *, test_t));
+void	hstat __P((DB *));
+void	mstat __P((DB_ENV *));
+void	prflags __P((u_int32_t, const FN *));
+void	onint __P((int));
+void	tstat __P((DB_ENV *));
+int	txn_compare __P((const void *, const void *));
+void	usage __P((void));
+int	main __P((int, char *[]));
+
+int	 interrupted;
+const char *progname = "db_stat";			/* Program name. */
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	extern char *optarg;
+	extern int optind;
+	DB *dbp;
+	DB_ENV *dbenv;
+	test_t ttype;
+	int ch;
+	char *db, *home;
+
+	ttype = T_NOTSET;
+	db = home = NULL;
+	while ((ch = getopt(argc, argv, "d:h:mt")) != EOF)
+		switch (ch) {
+		case 'd':
+			db = optarg;
+			ttype = T_DB;
+			break;
+		case 'h':
+			home = optarg;
+			break;
+		case 'm':
+			ttype = T_MPOOL;
+			break;
+		case 't':
+			ttype = T_TXN;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	argc -= optind;
+	argv += optind;
+
+	if (argc != 0 || ttype == T_NOTSET)
+		usage();
+
+	dbenv = db_init(home, ttype);
+
+	(void)signal(SIGINT, onint);
+
+	switch (ttype) {
+	case T_DB:
+		if ((errno = db_open(db, DB_UNKNOWN,
+		    DB_RDONLY, 0, dbenv, NULL, &dbp)) != 0)
+			return (1);
+		switch (dbp->type) {
+		case DB_BTREE:
+		case DB_RECNO:
+			bstat(dbp);
+			break;
+		case DB_HASH:
+			hstat(dbp);
+			break;
+		case DB_UNKNOWN:
+			abort();		/* Impossible. */
+			/* NOTREACHED */
+		}
+		(void)dbp->close(dbp, 0);
+		break;
+	case T_MPOOL:
+		mstat(dbenv);
+		break;
+	case T_TXN:
+		tstat(dbenv);
+		break;
+	case T_NOTSET:
+		abort();			/* Impossible. */
+		/* NOTREACHED */
+	}
+
+	(void)db_appexit(dbenv);
+
+	if (interrupted) {
+		(void)signal(SIGINT, SIG_DFL);
+		(void)raise(SIGINT);
+		/* NOTREACHED */
+	}
+	return (0);
+}
+
+/*
+ * bstat --
+ *	Display btree/recno statistics.
+ */
+void
+bstat(dbp)
+	DB *dbp;
+{
+	static const FN fn[] = {
+		{ DB_DUP,	"DB_DUP" },
+		{ DB_FIXEDLEN,	"DB_FIXEDLEN" },
+		{ DB_RECNUM,	"DB_RECNUM" },
+		{ DB_RENUMBER,	"DB_RENUMBER" },
+		{ 0 }
+	};
+	DB_BTREE_STAT *sp;
+
+	if (dbp->stat(dbp, &sp, NULL, 0))
+		err(1, "dbp->stat");
+
+#define	PCT(f, t)							\
+    (t == 0 ? 0 :							\
+    (((double)((t * sp->bt_pagesize) - f) / (t * sp->bt_pagesize)) * 100))
+
+	prflags(sp->bt_flags, fn);
+	if (dbp->type == DB_BTREE) {
+#ifdef NOT_IMPLEMENTED
+		printf("%lu\tMaximum keys per-page.\n", (u_long)sp->bt_maxkey);
+#endif
+		printf("%lu\tMinimum keys per-page.\n", (u_long)sp->bt_minkey);
+	}
+	if (dbp->type == DB_RECNO) {
+		printf("%lu\tFixed-length record size.\n",
+		    (u_long)sp->bt_re_len);
+		if (isprint(sp->bt_re_pad))
+			printf("%c\tFixed-length record pad.\n",
+			    (int)sp->bt_re_pad);
+		else
+			printf("0x%x\tFixed-length record pad.\n",
+			    (int)sp->bt_re_pad);
+	}
+	printf("%lu\tUnderlying tree page size.\n", (u_long)sp->bt_pagesize);
+	printf("%lu\tNumber of levels in the tree.\n", (u_long)sp->bt_levels);
+	printf("%lu\tNumber of keys in the tree.\n", (u_long)sp->bt_nrecs);
+	printf("%lu\tNumber of tree internal pages.\n", (u_long)sp->bt_int_pg);
+	printf("%lu\tNumber of tree leaf pages.\n", (u_long)sp->bt_leaf_pg);
+	printf("%lu\tNumber of tree duplicate pages.\n",
+	    (u_long)sp->bt_dup_pg);
+	printf("%lu\tNumber of tree overflow pages.\n",
+	    (u_long)sp->bt_over_pg);
+	printf("%lu\tNumber of pages on the free list.\n",
+	    (u_long)sp->bt_free);
+	printf("%lu\tNumber of pages freed for reuse.\n",
+	    (u_long)sp->bt_freed);
+	printf("%lu\tNumber of bytes free in tree internal pages (%.0f%% ff)\n",
+	    (u_long)sp->bt_int_pgfree,
+	    PCT(sp->bt_int_pgfree, sp->bt_int_pg));
+	printf("%lu\tNumber of bytes free in tree leaf pages (%.0f%% ff).\n",
+	    (u_long)sp->bt_leaf_pgfree,
+	    PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg));
+printf("%lu\tNumber of bytes free in tree duplicate pages (%.0f%% ff).\n",
+	    (u_long)sp->bt_dup_pgfree,
+	    PCT(sp->bt_dup_pgfree, sp->bt_dup_pg));
+printf("%lu\tNumber of bytes free in tree overflow pages (%.0f%% ff).\n",
+	    (u_long)sp->bt_over_pgfree,
+	    PCT(sp->bt_over_pgfree, sp->bt_over_pg));
+	printf("%lu\tNumber of bytes saved by prefix compression.\n",
+	    (u_long)sp->bt_pfxsaved);
+	printf("%lu\tTotal number of tree page splits.\n",
+	    (u_long)sp->bt_split);
+	printf("%lu\tNumber of root page splits.\n", (u_long)sp->bt_rootsplit);
+	printf("%lu\tNumber of fast splits.\n", (u_long)sp->bt_fastsplit);
+	printf("%lu\tNumber of hits in tree fast-insert code.\n",
+	    (u_long)sp->bt_cache_hit);
+	printf("%lu\tNumber of misses in tree fast-insert code.\n",
+	    (u_long)sp->bt_cache_miss);
+	printf("%lu\tNumber of keys added.\n", (u_long)sp->bt_added);
+	printf("%lu\tNumber of keys deleted.\n", (u_long)sp->bt_deleted);
+}
+
+/*
+ * hstat --
+ *	Display hash statistics.
+ */
+void
+hstat(dbp)
+	DB *dbp;
+{
+	return;
+}
+
+/*
+ * mstat --
+ *	Display mpool statistics.
+ */
+void
+mstat(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_MPOOL_FSTAT **fsp;
+	DB_MPOOL_STAT *gsp;
+
+	if (memp_stat(dbenv->mp_info, &gsp, &fsp, NULL))
+		err(1, NULL);
+
+	printf("%lu\tCache size (%luK).\n",
+	    (u_long)gsp->st_cachesize, (u_long)gsp->st_cachesize / 1024);
+	printf("%lu\tRequested pages found in the cache", gsp->st_cache_hit);
+	if (gsp->st_cache_hit + gsp->st_cache_miss != 0)
+		printf(" (%.0f%%)", ((double)gsp->st_cache_hit /
+		    (gsp->st_cache_hit + gsp->st_cache_miss)) * 100);
+	printf(".\n");
+	printf("%lu\tRequested pages mapped into the process' address space.\n",
+	    gsp->st_map);
+	printf("%lu\tRequested pages not found in the cache.\n",
+	    gsp->st_cache_miss);
+	printf("%lu\tPages created in the cache.\n", gsp->st_page_create);
+	printf("%lu\tPages read into the cache.\n", gsp->st_page_in);
+	printf("%lu\tPages written from the cache to the backing file.\n",
+	    gsp->st_page_out);
+	printf("%lu\tRead-only pages forced from the cache.\n",
+	    gsp->st_ro_evict);
+	printf("%lu\tRead-write pages forced from the cache.\n",
+	    gsp->st_rw_evict);
+	printf("%lu\tNumber of hash buckets used for page location.\n",
+	    gsp->st_hash_buckets);
+	printf("%lu\tTotal number of times hash chains searched for a page.\n",
+	    gsp->st_hash_searches);
+	printf("%lu\tThe longest hash chain searched for a page.\n",
+	    gsp->st_hash_longest);
+	printf(
+	    "%lu\tTotal number of hash buckets examined for page location.\n",
+	    gsp->st_hash_examined);
+
+	for (; fsp != NULL && *fsp != NULL; ++fsp) {
+		printf("%s\n", DIVIDER);
+		printf("%s\n", (*fsp)->file_name);
+		printf("%lu\tPage size.\n", (u_long)(*fsp)->st_pagesize);
+		printf("%lu\tRequested pages found in the cache",
+		    (*fsp)->st_cache_hit);
+		if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0)
+			printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit /
+			    ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) *
+			    100);
+		printf(".\n");
+	printf("%lu\tRequested pages mapped into the process' address space.\n",
+		    (*fsp)->st_map);
+		printf("%lu\tRequested pages not found in the cache.\n",
+		    (*fsp)->st_cache_miss);
+		printf("%lu\tPages created in the cache.\n",
+		    (*fsp)->st_page_create);
+		printf("%lu\tPages read into the cache.\n", (*fsp)->st_page_in);
+	printf("%lu\tPages written from the cache to the backing file.\n",
+		    (*fsp)->st_page_out);
+	}
+}
+
+/*
+ * tstat --
+ *	Display transaction statistics.
+ */
+void
+tstat(dbenv)
+	DB_ENV *dbenv;
+{
+	DB_TXN_STAT *tstat;
+	unsigned int i;
+	const char *p;
+
+	if (txn_stat(dbenv->tx_info, &tstat, NULL))
+		err(1, NULL);
+
+	p = tstat->st_last_ckp.file == 0 ?
+	    "No checkpoint LSN." : "File/offset for last checkpoint LSN.";
+	printf("%lu/%lu\t%s\n", (u_long)tstat->st_last_ckp.file,
+	    (u_long)tstat->st_last_ckp.offset, p);
+	p = tstat->st_pending_ckp.file == 0 ?
+	    "No pending checkpoint LSN." :
+	    "File/offset for last pending checkpoint LSN.";
+	printf("%lu/%lu\t%s.\n",
+	    (u_long)tstat->st_pending_ckp.file,
+	    (u_long)tstat->st_pending_ckp.offset, p);
+	if (tstat->st_time_ckp == 0)
+		printf("0\tNo checkpoint timestamp.\n");
+	else
+		printf("%.24s\tCheckpoint timestamp.\n",
+		    ctime(&tstat->st_time_ckp));
+	printf("%lx\tLast transaction ID allocated.\n",
+	    (u_long)tstat->st_last_txnid);
+	printf("%lu\tMaximum number of active transactions.\n",
+	    (u_long)tstat->st_maxtxns);
+	printf("%lu\tNumber of transactions begun.\n",
+	    (u_long)tstat->st_nbegins);
+	printf("%lu\tNumber of transactions aborted.\n",
+	    (u_long)tstat->st_naborts);
+	printf("%lu\tNumber of transactions committed.\n",
+	    (u_long)tstat->st_ncommits);
+	printf("%lu\tActive transactions.\n", (u_long)tstat->st_nactive);
+	qsort(tstat->st_txnarray,
+	    tstat->st_nactive, sizeof(tstat->st_txnarray[0]), txn_compare);
+	for (i = 0; i < tstat->st_nactive; ++i)
+		printf("\tid: %lx; initial LSN file/offest %lu/%lu\n",
+		    (u_long)tstat->st_txnarray[i].txnid,
+		    (u_long)tstat->st_txnarray[i].lsn.file,
+		    (u_long)tstat->st_txnarray[i].lsn.offset);
+}
+
+int
+txn_compare(a1, b1)
+	const void *a1, *b1;
+{
+	const DB_TXN_ACTIVE *a, *b;
+
+	a = a1;
+	b = b1;
+
+	if (a->txnid > b->txnid)
+		return (1);
+	if (a->txnid < b->txnid)
+		return (-1);
+	return (0);
+}
+
+/*
+ * prflags --
+ *	Print out flag values.
+ */
+void
+prflags(flags, fn)
+	u_int32_t flags;
+	FN const *fn;
+{
+	const FN *fnp;
+	int found;
+	const char *sep;
+
+	sep = " ";
+	printf("Flags:");
+	for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
+		if (fnp->mask & flags) {
+			printf("%s%s", sep, fnp->name);
+			sep = ", ";
+			found = 1;
+		}
+	printf("\n");
+}
+
+/*
+ * db_init --
+ *	Initialize the environment.
+ */
+DB_ENV *
+db_init(home, ttype)
+	char *home;
+	test_t ttype;
+{
+	DB_ENV *dbenv;
+	int flags;
+
+	flags = DB_USE_ENVIRON;
+	switch (ttype) {
+	case T_MPOOL:
+		flags |= DB_INIT_MPOOL;
+		break;
+	case T_TXN:
+		flags |= DB_INIT_TXN;
+		break;
+	default:
+		break;
+	}
+
+	if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
+		errno = ENOMEM;
+		err(1, NULL);
+	}
+	dbenv->db_errfile = stderr;
+	dbenv->db_errpfx = progname;
+
+	if ((errno = db_appinit(home, NULL, dbenv, flags)) != 0)
+		err(1, "db_appinit");
+	return (dbenv);
+}
+
+/*
+ * oninit --
+ *	Interrupt signal handler.
+ */
+void
+onint(signo)
+	int signo;
+{
+	signo = 1;			/* XXX: Shut the compiler up. */
+	interrupted = 1;
+}
+
+void
+usage()
+{
+	fprintf(stderr, "usage: db_stat [-mt] [-d file] [-h home]\n");
+	exit (1);
+}