11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Mike Olson.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
161573Srgrimes * 4. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
311573Srgrimes */
321573Srgrimes
331573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
341573Srgrimesstatic char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/4/93";
351573Srgrimes#endif /* LIBC_SCCS and not lint */
3692889Sobrien#include <sys/cdefs.h>
3792889Sobrien__FBSDID("$FreeBSD$");
381573Srgrimes
391573Srgrimes#include <sys/param.h>
401573Srgrimes#include <fcntl.h>
411573Srgrimes#include <db.h>
421573Srgrimes#include <errno.h>
431573Srgrimes#include <stdio.h>
441573Srgrimes#include <ctype.h>
451573Srgrimes#include <stdlib.h>
461573Srgrimes#include <string.h>
471573Srgrimes#include "btree.h"
481573Srgrimes
491573Srgrimestypedef struct cmd_table {
501573Srgrimes	char *cmd;
511573Srgrimes	int nargs;
521573Srgrimes	int rconv;
5392905Sobrien	void (*func)(DB *, char **);
541573Srgrimes	char *usage, *descrip;
551573Srgrimes} cmd_table;
561573Srgrimes
571573Srgrimesint stopstop;
581573SrgrimesDB *globaldb;
591573Srgrimes
6092905Sobrienvoid append(DB *, char **);
6192905Sobrienvoid bstat(DB *, char **);
6292905Sobrienvoid cursor(DB *, char **);
6392905Sobrienvoid delcur(DB *, char **);
6492905Sobrienvoid delete(DB *, char **);
6592905Sobrienvoid dump(DB *, char **);
6692905Sobrienvoid first(DB *, char **);
6792905Sobrienvoid get(DB *, char **);
6892905Sobrienvoid help(DB *, char **);
6992905Sobrienvoid iafter(DB *, char **);
7092905Sobrienvoid ibefore(DB *, char **);
7192905Sobrienvoid icursor(DB *, char **);
7292905Sobrienvoid insert(DB *, char **);
7392905Sobrienvoid keydata(DBT *, DBT *);
7492905Sobrienvoid last(DB *, char **);
7592905Sobrienvoid list(DB *, char **);
7692905Sobrienvoid load(DB *, char **);
7792905Sobrienvoid mstat(DB *, char **);
7892905Sobrienvoid next(DB *, char **);
7992905Sobrienint  parse(char *, char **, int);
8092905Sobrienvoid previous(DB *, char **);
8192905Sobrienvoid show(DB *, char **);
8292905Sobrienvoid usage(void);
8392905Sobrienvoid user(DB *);
841573Srgrimes
851573Srgrimescmd_table commands[] = {
861573Srgrimes	"?",	0, 0, help, "help", NULL,
871573Srgrimes	"a",	2, 1, append, "append key def", "append key with data def",
881573Srgrimes	"b",	0, 0, bstat, "bstat", "stat btree",
891573Srgrimes	"c",	1, 1, cursor,  "cursor word", "move cursor to word",
901573Srgrimes	"delc",	0, 0, delcur, "delcur", "delete key the cursor references",
911573Srgrimes	"dele",	1, 1, delete, "delete word", "delete word",
921573Srgrimes	"d",	0, 0, dump, "dump", "dump database",
931573Srgrimes	"f",	0, 0, first, "first", "move cursor to first record",
941573Srgrimes	"g",	1, 1, get, "get key", "locate key",
951573Srgrimes	"h",	0, 0, help, "help", "print command summary",
961573Srgrimes	"ia",	2, 1, iafter, "iafter key data", "insert data after key",
971573Srgrimes	"ib",	2, 1, ibefore, "ibefore key data", "insert data before key",
981573Srgrimes	"ic",	2, 1, icursor, "icursor key data", "replace cursor",
991573Srgrimes	"in",	2, 1, insert, "insert key def", "insert key with data def",
1001573Srgrimes	"la",	0, 0, last, "last", "move cursor to last record",
1011573Srgrimes	"li",	1, 1, list, "list file", "list to a file",
1021573Srgrimes	"loa",	1, 0, load, "load file", NULL,
1031573Srgrimes	"loc",	1, 1, get, "get key", NULL,
1041573Srgrimes	"m",	0, 0, mstat, "mstat", "stat memory pool",
1051573Srgrimes	"n",	0, 0, next, "next", "move cursor forward one record",
1061573Srgrimes	"p",	0, 0, previous, "previous", "move cursor back one record",
1071573Srgrimes	"q",	0, 0, NULL, "quit", "quit",
1081573Srgrimes	"sh",	1, 0, show, "show page", "dump a page",
1091573Srgrimes	{ NULL },
1101573Srgrimes};
1111573Srgrimes
1121573Srgrimesint recno;					/* use record numbers */
1131573Srgrimeschar *dict = "words";				/* default dictionary */
1141573Srgrimeschar *progname;
1151573Srgrimes
1161573Srgrimesint
1171573Srgrimesmain(argc, argv)
1181573Srgrimes	int argc;
1191573Srgrimes	char **argv;
1201573Srgrimes{
1211573Srgrimes	int c;
1221573Srgrimes	DB *db;
1231573Srgrimes	BTREEINFO b;
1241573Srgrimes
1251573Srgrimes	progname = *argv;
1261573Srgrimes
1271573Srgrimes	b.flags = 0;
1281573Srgrimes	b.cachesize = 0;
1291573Srgrimes	b.maxkeypage = 0;
1301573Srgrimes	b.minkeypage = 0;
1311573Srgrimes	b.psize = 0;
1321573Srgrimes	b.compare = NULL;
1331573Srgrimes	b.prefix = NULL;
1341573Srgrimes	b.lorder = 0;
1351573Srgrimes
136176380Skevlo	while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {
1371573Srgrimes		switch (c) {
1381573Srgrimes		case 'b':
1391573Srgrimes			b.lorder = BIG_ENDIAN;
1401573Srgrimes			break;
1411573Srgrimes		case 'c':
1421573Srgrimes			b.cachesize = atoi(optarg);
1431573Srgrimes			break;
1441573Srgrimes		case 'd':
1451573Srgrimes			b.flags |= R_DUP;
1461573Srgrimes			break;
1471573Srgrimes		case 'i':
1481573Srgrimes			dict = optarg;
1491573Srgrimes			break;
1501573Srgrimes		case 'l':
1511573Srgrimes			b.lorder = LITTLE_ENDIAN;
1521573Srgrimes			break;
1531573Srgrimes		case 'p':
1541573Srgrimes			b.psize = atoi(optarg);
1551573Srgrimes			break;
1561573Srgrimes		case 'r':
1571573Srgrimes			recno = 1;
1581573Srgrimes			break;
1591573Srgrimes		case 'u':
1601573Srgrimes			b.flags = 0;
1611573Srgrimes			break;
1621573Srgrimes		default:
1631573Srgrimes			usage();
1641573Srgrimes		}
1651573Srgrimes	}
1661573Srgrimes	argc -= optind;
1671573Srgrimes	argv += optind;
1681573Srgrimes
1691573Srgrimes	if (recno)
1701573Srgrimes		db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,
1711573Srgrimes		    0, DB_RECNO, NULL);
1721573Srgrimes	else
1731573Srgrimes		db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,
1741573Srgrimes		    0600, DB_BTREE, &b);
1751573Srgrimes
1761573Srgrimes	if (db == NULL) {
1771573Srgrimes		(void)fprintf(stderr, "dbopen: %s\n", strerror(errno));
1781573Srgrimes		exit(1);
1791573Srgrimes	}
1801573Srgrimes	globaldb = db;
1811573Srgrimes	user(db);
1821573Srgrimes	exit(0);
1831573Srgrimes	/* NOTREACHED */
1841573Srgrimes}
1851573Srgrimes
1861573Srgrimesvoid
1871573Srgrimesuser(db)
1881573Srgrimes	DB *db;
1891573Srgrimes{
1901573Srgrimes	FILE *ifp;
1911573Srgrimes	int argc, i, last;
1921573Srgrimes	char *lbuf, *argv[4], buf[512];
1931573Srgrimes
1941573Srgrimes	if ((ifp = fopen("/dev/tty", "r")) == NULL) {
1951573Srgrimes		(void)fprintf(stderr,
1961573Srgrimes		    "/dev/tty: %s\n", strerror(errno));
1971573Srgrimes		exit(1);
1981573Srgrimes	}
1991573Srgrimes	for (last = 0;;) {
2001573Srgrimes		(void)printf("> ");
2011573Srgrimes		(void)fflush(stdout);
2021573Srgrimes		if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
2031573Srgrimes			break;
2041573Srgrimes		if (lbuf[0] == '\n') {
2051573Srgrimes			i = last;
2061573Srgrimes			goto uselast;
2071573Srgrimes		}
2081573Srgrimes		lbuf[strlen(lbuf) - 1] = '\0';
2091573Srgrimes
2101573Srgrimes		if (lbuf[0] == 'q')
2111573Srgrimes			break;
2121573Srgrimes
2131573Srgrimes		argc = parse(lbuf, &argv[0], 3);
2141573Srgrimes		if (argc == 0)
2151573Srgrimes			continue;
2161573Srgrimes
2171573Srgrimes		for (i = 0; commands[i].cmd != NULL; i++)
2181573Srgrimes			if (strncmp(commands[i].cmd, argv[0],
2191573Srgrimes			    strlen(commands[i].cmd)) == 0)
2201573Srgrimes				break;
2211573Srgrimes
2221573Srgrimes		if (commands[i].cmd == NULL) {
2231573Srgrimes			(void)fprintf(stderr,
2241573Srgrimes			    "%s: command unknown ('help' for help)\n", lbuf);
2251573Srgrimes			continue;
2261573Srgrimes		}
2271573Srgrimes
2281573Srgrimes		if (commands[i].nargs != argc - 1) {
2291573Srgrimes			(void)fprintf(stderr, "usage: %s\n", commands[i].usage);
2301573Srgrimes			continue;
2311573Srgrimes		}
2321573Srgrimes
2331573Srgrimes		if (recno && commands[i].rconv) {
2341573Srgrimes			static recno_t nlong;
2351573Srgrimes			nlong = atoi(argv[1]);
2361573Srgrimes			argv[1] = (char *)&nlong;
2371573Srgrimes		}
2381573Srgrimesuselast:	last = i;
2391573Srgrimes		(*commands[i].func)(db, argv);
2401573Srgrimes	}
2411573Srgrimes	if ((db->sync)(db) == RET_ERROR)
2421573Srgrimes		perror("dbsync");
2431573Srgrimes	else if ((db->close)(db) == RET_ERROR)
2441573Srgrimes		perror("dbclose");
2451573Srgrimes}
2461573Srgrimes
2471573Srgrimesint
2481573Srgrimesparse(lbuf, argv, maxargc)
2491573Srgrimes	char *lbuf, **argv;
2501573Srgrimes	int maxargc;
2511573Srgrimes{
2521573Srgrimes	int argc = 0;
2531573Srgrimes	char *c;
2541573Srgrimes
2551573Srgrimes	c = lbuf;
2561573Srgrimes	while (isspace(*c))
2571573Srgrimes		c++;
2581573Srgrimes	while (*c != '\0' && argc < maxargc) {
2591573Srgrimes		*argv++ = c;
2601573Srgrimes		argc++;
2611573Srgrimes		while (!isspace(*c) && *c != '\0') {
2621573Srgrimes			c++;
2631573Srgrimes		}
2641573Srgrimes		while (isspace(*c))
2651573Srgrimes			*c++ = '\0';
2661573Srgrimes	}
2671573Srgrimes	return (argc);
2681573Srgrimes}
2691573Srgrimes
2701573Srgrimesvoid
2711573Srgrimesappend(db, argv)
2721573Srgrimes	DB *db;
2731573Srgrimes	char **argv;
2741573Srgrimes{
2751573Srgrimes	DBT key, data;
2761573Srgrimes	int status;
2771573Srgrimes
2781573Srgrimes	if (!recno) {
2791573Srgrimes		(void)fprintf(stderr,
2801573Srgrimes		    "append only available for recno db's.\n");
2811573Srgrimes		return;
2821573Srgrimes	}
2831573Srgrimes	key.data = argv[1];
2841573Srgrimes	key.size = sizeof(recno_t);
2851573Srgrimes	data.data = argv[2];
2861573Srgrimes	data.size = strlen(data.data);
2871573Srgrimes	status = (db->put)(db, &key, &data, R_APPEND);
2881573Srgrimes	switch (status) {
2891573Srgrimes	case RET_ERROR:
2901573Srgrimes		perror("append/put");
2911573Srgrimes		break;
2921573Srgrimes	case RET_SPECIAL:
2931573Srgrimes		(void)printf("%s (duplicate key)\n", argv[1]);
2941573Srgrimes		break;
2951573Srgrimes	case RET_SUCCESS:
2961573Srgrimes		break;
2971573Srgrimes	}
2981573Srgrimes}
2991573Srgrimes
3001573Srgrimesvoid
3011573Srgrimescursor(db, argv)
3021573Srgrimes	DB *db;
3031573Srgrimes	char **argv;
3041573Srgrimes{
3051573Srgrimes	DBT data, key;
3061573Srgrimes	int status;
3071573Srgrimes
3081573Srgrimes	key.data = argv[1];
3091573Srgrimes	if (recno)
3101573Srgrimes		key.size = sizeof(recno_t);
3111573Srgrimes	else
3121573Srgrimes		key.size = strlen(argv[1]) + 1;
3131573Srgrimes	status = (*db->seq)(db, &key, &data, R_CURSOR);
3141573Srgrimes	switch (status) {
3151573Srgrimes	case RET_ERROR:
3161573Srgrimes		perror("cursor/seq");
3171573Srgrimes		break;
3181573Srgrimes	case RET_SPECIAL:
3191573Srgrimes		(void)printf("key not found\n");
3201573Srgrimes		break;
3211573Srgrimes	case RET_SUCCESS:
3221573Srgrimes		keydata(&key, &data);
3231573Srgrimes		break;
3241573Srgrimes	}
3251573Srgrimes}
3261573Srgrimes
3271573Srgrimesvoid
3281573Srgrimesdelcur(db, argv)
3291573Srgrimes	DB *db;
3301573Srgrimes	char **argv;
3311573Srgrimes{
3321573Srgrimes	int status;
3331573Srgrimes
3341573Srgrimes	status = (*db->del)(db, NULL, R_CURSOR);
3351573Srgrimes
3361573Srgrimes	if (status == RET_ERROR)
3371573Srgrimes		perror("delcur/del");
3381573Srgrimes}
3391573Srgrimes
3401573Srgrimesvoid
3411573Srgrimesdelete(db, argv)
3421573Srgrimes	DB *db;
3431573Srgrimes	char **argv;
3441573Srgrimes{
3451573Srgrimes	DBT key;
3461573Srgrimes	int status;
3471573Srgrimes
3481573Srgrimes	key.data = argv[1];
3491573Srgrimes	if (recno)
3501573Srgrimes		key.size = sizeof(recno_t);
3511573Srgrimes	else
3521573Srgrimes		key.size = strlen(argv[1]) + 1;
3531573Srgrimes
3541573Srgrimes	status = (*db->del)(db, &key, 0);
3551573Srgrimes	switch (status) {
3561573Srgrimes	case RET_ERROR:
3571573Srgrimes		perror("delete/del");
3581573Srgrimes		break;
3591573Srgrimes	case RET_SPECIAL:
3601573Srgrimes		(void)printf("key not found\n");
3611573Srgrimes		break;
3621573Srgrimes	case RET_SUCCESS:
3631573Srgrimes		break;
3641573Srgrimes	}
3651573Srgrimes}
3661573Srgrimes
3671573Srgrimesvoid
3681573Srgrimesdump(db, argv)
3691573Srgrimes	DB *db;
3701573Srgrimes	char **argv;
3711573Srgrimes{
3721573Srgrimes	__bt_dump(db);
3731573Srgrimes}
3741573Srgrimes
3751573Srgrimesvoid
3761573Srgrimesfirst(db, argv)
3771573Srgrimes	DB *db;
3781573Srgrimes	char **argv;
3791573Srgrimes{
3801573Srgrimes	DBT data, key;
3811573Srgrimes	int status;
3821573Srgrimes
3831573Srgrimes	status = (*db->seq)(db, &key, &data, R_FIRST);
3841573Srgrimes
3851573Srgrimes	switch (status) {
3861573Srgrimes	case RET_ERROR:
3871573Srgrimes		perror("first/seq");
3881573Srgrimes		break;
3891573Srgrimes	case RET_SPECIAL:
3901573Srgrimes		(void)printf("no more keys\n");
3911573Srgrimes		break;
3921573Srgrimes	case RET_SUCCESS:
3931573Srgrimes		keydata(&key, &data);
3941573Srgrimes		break;
3951573Srgrimes	}
3961573Srgrimes}
3971573Srgrimes
3981573Srgrimesvoid
3991573Srgrimesget(db, argv)
4001573Srgrimes	DB *db;
4011573Srgrimes	char **argv;
4021573Srgrimes{
4031573Srgrimes	DBT data, key;
4041573Srgrimes	int status;
4051573Srgrimes
4061573Srgrimes	key.data = argv[1];
4071573Srgrimes	if (recno)
4081573Srgrimes		key.size = sizeof(recno_t);
4091573Srgrimes	else
4101573Srgrimes		key.size = strlen(argv[1]) + 1;
4111573Srgrimes
4121573Srgrimes	status = (*db->get)(db, &key, &data, 0);
4131573Srgrimes
4141573Srgrimes	switch (status) {
4151573Srgrimes	case RET_ERROR:
4161573Srgrimes		perror("get/get");
4171573Srgrimes		break;
4181573Srgrimes	case RET_SPECIAL:
4191573Srgrimes		(void)printf("key not found\n");
4201573Srgrimes		break;
4211573Srgrimes	case RET_SUCCESS:
4221573Srgrimes		keydata(&key, &data);
4231573Srgrimes		break;
4241573Srgrimes	}
4251573Srgrimes}
4261573Srgrimes
4271573Srgrimesvoid
4281573Srgrimeshelp(db, argv)
4291573Srgrimes	DB *db;
4301573Srgrimes	char **argv;
4311573Srgrimes{
4321573Srgrimes	int i;
4331573Srgrimes
4341573Srgrimes	for (i = 0; commands[i].cmd; i++)
4351573Srgrimes		if (commands[i].descrip)
4361573Srgrimes			(void)printf("%s: %s\n",
4371573Srgrimes			    commands[i].usage, commands[i].descrip);
4381573Srgrimes}
4391573Srgrimes
4401573Srgrimesvoid
4411573Srgrimesiafter(db, argv)
4421573Srgrimes	DB *db;
4431573Srgrimes	char **argv;
4441573Srgrimes{
4451573Srgrimes	DBT key, data;
4461573Srgrimes	int status;
4471573Srgrimes
4481573Srgrimes	if (!recno) {
4491573Srgrimes		(void)fprintf(stderr,
4501573Srgrimes		    "iafter only available for recno db's.\n");
4511573Srgrimes		return;
4521573Srgrimes	}
4531573Srgrimes	key.data = argv[1];
4541573Srgrimes	key.size = sizeof(recno_t);
4551573Srgrimes	data.data = argv[2];
4561573Srgrimes	data.size = strlen(data.data);
4571573Srgrimes	status = (db->put)(db, &key, &data, R_IAFTER);
4581573Srgrimes	switch (status) {
4591573Srgrimes	case RET_ERROR:
4601573Srgrimes		perror("iafter/put");
4611573Srgrimes		break;
4621573Srgrimes	case RET_SPECIAL:
4631573Srgrimes		(void)printf("%s (duplicate key)\n", argv[1]);
4641573Srgrimes		break;
4651573Srgrimes	case RET_SUCCESS:
4661573Srgrimes		break;
4671573Srgrimes	}
4681573Srgrimes}
4691573Srgrimes
4701573Srgrimesvoid
4711573Srgrimesibefore(db, argv)
4721573Srgrimes	DB *db;
4731573Srgrimes	char **argv;
4741573Srgrimes{
4751573Srgrimes	DBT key, data;
4761573Srgrimes	int status;
4771573Srgrimes
4781573Srgrimes	if (!recno) {
4791573Srgrimes		(void)fprintf(stderr,
4801573Srgrimes		    "ibefore only available for recno db's.\n");
4811573Srgrimes		return;
4821573Srgrimes	}
4831573Srgrimes	key.data = argv[1];
4841573Srgrimes	key.size = sizeof(recno_t);
4851573Srgrimes	data.data = argv[2];
4861573Srgrimes	data.size = strlen(data.data);
4871573Srgrimes	status = (db->put)(db, &key, &data, R_IBEFORE);
4881573Srgrimes	switch (status) {
4891573Srgrimes	case RET_ERROR:
4901573Srgrimes		perror("ibefore/put");
4911573Srgrimes		break;
4921573Srgrimes	case RET_SPECIAL:
4931573Srgrimes		(void)printf("%s (duplicate key)\n", argv[1]);
4941573Srgrimes		break;
4951573Srgrimes	case RET_SUCCESS:
4961573Srgrimes		break;
4971573Srgrimes	}
4981573Srgrimes}
4991573Srgrimes
5001573Srgrimesvoid
5011573Srgrimesicursor(db, argv)
5021573Srgrimes	DB *db;
5031573Srgrimes	char **argv;
5041573Srgrimes{
5051573Srgrimes	int status;
5061573Srgrimes	DBT data, key;
5071573Srgrimes
5081573Srgrimes	key.data = argv[1];
5091573Srgrimes	if (recno)
5101573Srgrimes		key.size = sizeof(recno_t);
5111573Srgrimes	else
5121573Srgrimes		key.size = strlen(argv[1]) + 1;
5131573Srgrimes	data.data = argv[2];
5141573Srgrimes	data.size = strlen(argv[2]) + 1;
5151573Srgrimes
5161573Srgrimes	status = (*db->put)(db, &key, &data, R_CURSOR);
5171573Srgrimes	switch (status) {
5181573Srgrimes	case RET_ERROR:
5191573Srgrimes		perror("icursor/put");
5201573Srgrimes		break;
5211573Srgrimes	case RET_SPECIAL:
5221573Srgrimes		(void)printf("%s (duplicate key)\n", argv[1]);
5231573Srgrimes		break;
5241573Srgrimes	case RET_SUCCESS:
5251573Srgrimes		break;
5261573Srgrimes	}
5271573Srgrimes}
5281573Srgrimes
5291573Srgrimesvoid
5301573Srgrimesinsert(db, argv)
5311573Srgrimes	DB *db;
5321573Srgrimes	char **argv;
5331573Srgrimes{
5341573Srgrimes	int status;
5351573Srgrimes	DBT data, key;
5361573Srgrimes
5371573Srgrimes	key.data = argv[1];
5381573Srgrimes	if (recno)
5391573Srgrimes		key.size = sizeof(recno_t);
5401573Srgrimes	else
5411573Srgrimes		key.size = strlen(argv[1]) + 1;
5421573Srgrimes	data.data = argv[2];
5431573Srgrimes	data.size = strlen(argv[2]) + 1;
5441573Srgrimes
5451573Srgrimes	status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
5461573Srgrimes	switch (status) {
5471573Srgrimes	case RET_ERROR:
5481573Srgrimes		perror("insert/put");
5491573Srgrimes		break;
5501573Srgrimes	case RET_SPECIAL:
5511573Srgrimes		(void)printf("%s (duplicate key)\n", argv[1]);
5521573Srgrimes		break;
5531573Srgrimes	case RET_SUCCESS:
5541573Srgrimes		break;
5551573Srgrimes	}
5561573Srgrimes}
5571573Srgrimes
5581573Srgrimesvoid
5591573Srgrimeslast(db, argv)
5601573Srgrimes	DB *db;
5611573Srgrimes	char **argv;
5621573Srgrimes{
5631573Srgrimes	DBT data, key;
5641573Srgrimes	int status;
5651573Srgrimes
5661573Srgrimes	status = (*db->seq)(db, &key, &data, R_LAST);
5671573Srgrimes
5681573Srgrimes	switch (status) {
5691573Srgrimes	case RET_ERROR:
5701573Srgrimes		perror("last/seq");
5711573Srgrimes		break;
5721573Srgrimes	case RET_SPECIAL:
5731573Srgrimes		(void)printf("no more keys\n");
5741573Srgrimes		break;
5751573Srgrimes	case RET_SUCCESS:
5761573Srgrimes		keydata(&key, &data);
5771573Srgrimes		break;
5781573Srgrimes	}
5791573Srgrimes}
5801573Srgrimes
5811573Srgrimesvoid
5821573Srgrimeslist(db, argv)
5831573Srgrimes	DB *db;
5841573Srgrimes	char **argv;
5851573Srgrimes{
5861573Srgrimes	DBT data, key;
5871573Srgrimes	FILE *fp;
5881573Srgrimes	int status;
5891573Srgrimes
5901573Srgrimes	if ((fp = fopen(argv[1], "w")) == NULL) {
5911573Srgrimes		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
5921573Srgrimes		return;
5931573Srgrimes	}
5941573Srgrimes	status = (*db->seq)(db, &key, &data, R_FIRST);
5951573Srgrimes	while (status == RET_SUCCESS) {
5961573Srgrimes		(void)fprintf(fp, "%s\n", key.data);
5971573Srgrimes		status = (*db->seq)(db, &key, &data, R_NEXT);
5981573Srgrimes	}
5991573Srgrimes	if (status == RET_ERROR)
6001573Srgrimes		perror("list/seq");
6011573Srgrimes}
6021573Srgrimes
6031573SrgrimesDB *BUGdb;
6041573Srgrimesvoid
6051573Srgrimesload(db, argv)
6061573Srgrimes	DB *db;
6071573Srgrimes	char **argv;
6081573Srgrimes{
60992889Sobrien	char *p, *t;
6101573Srgrimes	FILE *fp;
6111573Srgrimes	DBT data, key;
6121573Srgrimes	recno_t cnt;
6131573Srgrimes	size_t len;
6141573Srgrimes	int status;
6151573Srgrimes	char *lp, buf[16 * 1024];
6161573Srgrimes
6171573Srgrimes	BUGdb = db;
6181573Srgrimes	if ((fp = fopen(argv[1], "r")) == NULL) {
6191573Srgrimes		(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
6201573Srgrimes		return;
6211573Srgrimes	}
6221573Srgrimes	(void)printf("loading %s...\n", argv[1]);
6231573Srgrimes
6241573Srgrimes	for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
6251573Srgrimes		if (recno) {
6261573Srgrimes			key.data = &cnt;
6271573Srgrimes			key.size = sizeof(recno_t);
6281573Srgrimes			data.data = lp;
6291573Srgrimes			data.size = len + 1;
6308870Srgrimes		} else {
6311573Srgrimes			key.data = lp;
6321573Srgrimes			key.size = len + 1;
6331573Srgrimes			for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
6341573Srgrimes			*t = '\0';
6351573Srgrimes			data.data = buf;
6361573Srgrimes			data.size = len + 1;
6371573Srgrimes		}
6381573Srgrimes
6391573Srgrimes		status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
6401573Srgrimes		switch (status) {
6411573Srgrimes		case RET_ERROR:
6421573Srgrimes			perror("load/put");
6431573Srgrimes			exit(1);
6441573Srgrimes		case RET_SPECIAL:
6451573Srgrimes			if (recno)
6461573Srgrimes				(void)fprintf(stderr,
6471573Srgrimes				    "duplicate: %ld {%s}\n", cnt, data.data);
6481573Srgrimes			else
6491573Srgrimes				(void)fprintf(stderr,
6501573Srgrimes				    "duplicate: %ld {%s}\n", cnt, key.data);
6511573Srgrimes			exit(1);
6521573Srgrimes		case RET_SUCCESS:
6531573Srgrimes			break;
6541573Srgrimes		}
6551573Srgrimes	}
6561573Srgrimes	(void)fclose(fp);
6571573Srgrimes}
6581573Srgrimes
6591573Srgrimesvoid
6601573Srgrimesnext(db, argv)
6611573Srgrimes	DB *db;
6621573Srgrimes	char **argv;
6631573Srgrimes{
6641573Srgrimes	DBT data, key;
6651573Srgrimes	int status;
6661573Srgrimes
6671573Srgrimes	status = (*db->seq)(db, &key, &data, R_NEXT);
6681573Srgrimes
6691573Srgrimes	switch (status) {
6701573Srgrimes	case RET_ERROR:
6711573Srgrimes		perror("next/seq");
6721573Srgrimes		break;
6731573Srgrimes	case RET_SPECIAL:
6741573Srgrimes		(void)printf("no more keys\n");
6751573Srgrimes		break;
6761573Srgrimes	case RET_SUCCESS:
6771573Srgrimes		keydata(&key, &data);
6781573Srgrimes		break;
6791573Srgrimes	}
6801573Srgrimes}
6811573Srgrimes
6821573Srgrimesvoid
6831573Srgrimesprevious(db, argv)
6841573Srgrimes	DB *db;
6851573Srgrimes	char **argv;
6861573Srgrimes{
6871573Srgrimes	DBT data, key;
6881573Srgrimes	int status;
6891573Srgrimes
6901573Srgrimes	status = (*db->seq)(db, &key, &data, R_PREV);
6911573Srgrimes
6921573Srgrimes	switch (status) {
6931573Srgrimes	case RET_ERROR:
6941573Srgrimes		perror("previous/seq");
6951573Srgrimes		break;
6961573Srgrimes	case RET_SPECIAL:
6971573Srgrimes		(void)printf("no more keys\n");
6981573Srgrimes		break;
6991573Srgrimes	case RET_SUCCESS:
7001573Srgrimes		keydata(&key, &data);
7011573Srgrimes		break;
7021573Srgrimes	}
7031573Srgrimes}
7041573Srgrimes
7051573Srgrimesvoid
7061573Srgrimesshow(db, argv)
7071573Srgrimes	DB *db;
7081573Srgrimes	char **argv;
7091573Srgrimes{
7101573Srgrimes	BTREE *t;
7111573Srgrimes	PAGE *h;
7121573Srgrimes	pgno_t pg;
7131573Srgrimes
7141573Srgrimes	pg = atoi(argv[1]);
7151573Srgrimes	t = db->internal;
7161573Srgrimes	if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
7171573Srgrimes		(void)printf("getpage of %ld failed\n", pg);
7181573Srgrimes		return;
7191573Srgrimes	}
7201573Srgrimes	if (pg == 0)
7211573Srgrimes		__bt_dmpage(h);
7221573Srgrimes	else
7231573Srgrimes		__bt_dpage(h);
7241573Srgrimes	mpool_put(t->bt_mp, h, 0);
7251573Srgrimes}
7261573Srgrimes
7271573Srgrimesvoid
7281573Srgrimesbstat(db, argv)
7291573Srgrimes	DB *db;
7301573Srgrimes	char **argv;
7311573Srgrimes{
7321573Srgrimes	(void)printf("BTREE\n");
7331573Srgrimes	__bt_stat(db);
7341573Srgrimes}
7351573Srgrimes
7361573Srgrimesvoid
7371573Srgrimesmstat(db, argv)
7381573Srgrimes	DB *db;
7391573Srgrimes	char **argv;
7401573Srgrimes{
7411573Srgrimes	(void)printf("MPOOL\n");
7421573Srgrimes	mpool_stat(((BTREE *)db->internal)->bt_mp);
7431573Srgrimes}
7441573Srgrimes
7451573Srgrimesvoid
7461573Srgrimeskeydata(key, data)
7471573Srgrimes	DBT *key, *data;
7481573Srgrimes{
7491573Srgrimes	if (!recno && key->size > 0)
7501573Srgrimes		(void)printf("%s/", key->data);
7511573Srgrimes	if (data->size > 0)
7521573Srgrimes		(void)printf("%s", data->data);
7531573Srgrimes	(void)printf("\n");
7541573Srgrimes}
7551573Srgrimes
7561573Srgrimesvoid
7571573Srgrimesusage()
7581573Srgrimes{
7591573Srgrimes	(void)fprintf(stderr,
7601573Srgrimes	    "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
7611573Srgrimes	    progname);
7621573Srgrimes	exit (1);
7631573Srgrimes}
764