xref: /freebsd/contrib/netbsd-tests/lib/libc/db/h_db.c (revision d370fd1cd8fc69e87dc63f4f4a82e5a8b4956c93)
1*cdebaff8SEnji Cooper /*	$NetBSD: h_db.c,v 1.3 2016/09/24 21:18:22 christos Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 1992, 1993, 1994
557718be8SEnji Cooper  *	The Regents of the University of California.  All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
857718be8SEnji Cooper  * modification, are permitted provided that the following conditions
957718be8SEnji Cooper  * are met:
1057718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1157718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1257718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1357718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1457718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1557718be8SEnji Cooper  * 3. Neither the name of the University nor the names of its contributors
1657718be8SEnji Cooper  *    may be used to endorse or promote products derived from this software
1757718be8SEnji Cooper  *    without specific prior written permission.
1857718be8SEnji Cooper  *
1957718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2057718be8SEnji Cooper  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2157718be8SEnji Cooper  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2257718be8SEnji Cooper  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2357718be8SEnji Cooper  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2457718be8SEnji Cooper  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2557718be8SEnji Cooper  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2657718be8SEnji Cooper  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2757718be8SEnji Cooper  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2857718be8SEnji Cooper  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2957718be8SEnji Cooper  * SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper 
3257718be8SEnji Cooper #include <sys/cdefs.h>
3357718be8SEnji Cooper #ifndef lint
3457718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
3557718be8SEnji Cooper 	The Regents of the University of California.  All rights reserved.");
3657718be8SEnji Cooper #endif /* not lint */
3757718be8SEnji Cooper 
3857718be8SEnji Cooper #ifndef lint
3957718be8SEnji Cooper #if 0
4057718be8SEnji Cooper static char sccsid[] = "@(#)dbtest.c	8.17 (Berkeley) 9/1/94";
4157718be8SEnji Cooper #else
42*cdebaff8SEnji Cooper __RCSID("$NetBSD: h_db.c,v 1.3 2016/09/24 21:18:22 christos Exp $");
4357718be8SEnji Cooper #endif
4457718be8SEnji Cooper #endif /* not lint */
4557718be8SEnji Cooper 
4657718be8SEnji Cooper #include <sys/param.h>
4757718be8SEnji Cooper #include <sys/stat.h>
4857718be8SEnji Cooper 
4957718be8SEnji Cooper #include <ctype.h>
5057718be8SEnji Cooper #include <errno.h>
5157718be8SEnji Cooper #include <fcntl.h>
5257718be8SEnji Cooper #include <limits.h>
5357718be8SEnji Cooper #include <stdio.h>
5457718be8SEnji Cooper #include <stdlib.h>
5557718be8SEnji Cooper #include <string.h>
5657718be8SEnji Cooper #include <stdbool.h>
5757718be8SEnji Cooper #include <unistd.h>
5857718be8SEnji Cooper #include <err.h>
5957718be8SEnji Cooper #include <db.h>
60*cdebaff8SEnji Cooper #include "btree.h"
6157718be8SEnji Cooper 
6257718be8SEnji Cooper enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
6357718be8SEnji Cooper 
6457718be8SEnji Cooper static void	 compare(DBT *, DBT *);
6557718be8SEnji Cooper static DBTYPE	 dbtype(const char *);
66*cdebaff8SEnji Cooper static void	 dump(DB *, int, int);
6757718be8SEnji Cooper static void	 get(DB *, DBT *);
6857718be8SEnji Cooper static void	 getdata(DB *, DBT *, DBT *);
6957718be8SEnji Cooper static void	 put(DB *, DBT *, DBT *);
7057718be8SEnji Cooper static void	 rem(DB *, DBT *);
7157718be8SEnji Cooper static const char *sflags(int);
7257718be8SEnji Cooper static void	 synk(DB *);
7357718be8SEnji Cooper static void	*rfile(char *, size_t *);
7457718be8SEnji Cooper static void	 seq(DB *, DBT *);
7557718be8SEnji Cooper static u_int	 setflags(char *);
7657718be8SEnji Cooper static void	*setinfo(DBTYPE, char *);
77*cdebaff8SEnji Cooper #ifdef	__NetBSD__
78*cdebaff8SEnji Cooper static void	 unlinkpg(DB *);
79*cdebaff8SEnji Cooper #endif
8057718be8SEnji Cooper static void	 usage(void) __attribute__((__noreturn__));
8157718be8SEnji Cooper static void	*xcopy(void *, size_t);
8257718be8SEnji Cooper static void	 chkcmd(enum S);
8357718be8SEnji Cooper static void	 chkdata(enum S);
8457718be8SEnji Cooper static void	 chkkey(enum S);
8557718be8SEnji Cooper 
8657718be8SEnji Cooper #ifdef STATISTICS
8757718be8SEnji Cooper extern void __bt_stat(DB *);
8857718be8SEnji Cooper #endif
89*cdebaff8SEnji Cooper #ifdef	__NetBSD__
90*cdebaff8SEnji Cooper extern int __bt_relink(BTREE *, PAGE *);
91*cdebaff8SEnji Cooper #endif
9257718be8SEnji Cooper 
9357718be8SEnji Cooper static DBTYPE type;			/* Database type. */
9457718be8SEnji Cooper static void *infop;			/* Iflags. */
9557718be8SEnji Cooper static size_t lineno;			/* Current line in test script. */
9657718be8SEnji Cooper static u_int flags;				/* Current DB flags. */
9757718be8SEnji Cooper static int ofd = STDOUT_FILENO;		/* Standard output fd. */
9857718be8SEnji Cooper 
9957718be8SEnji Cooper static DB *XXdbp;			/* Global for gdb. */
10057718be8SEnji Cooper static size_t XXlineno;			/* Fast breakpoint for gdb. */
10157718be8SEnji Cooper 
10257718be8SEnji Cooper int
main(int argc,char * argv[])10357718be8SEnji Cooper main(int argc, char *argv[])
10457718be8SEnji Cooper {
10557718be8SEnji Cooper 	extern int optind;
10657718be8SEnji Cooper 	extern char *optarg;
10757718be8SEnji Cooper 	enum S command = COMMAND, state;
10857718be8SEnji Cooper 	DB *dbp;
10957718be8SEnji Cooper 	DBT data, key, keydata;
11057718be8SEnji Cooper 	size_t len;
11157718be8SEnji Cooper 	int ch, oflags, sflag;
11257718be8SEnji Cooper 	char *fname, *infoarg, *p, *t, buf[8 * 1024];
11357718be8SEnji Cooper 	bool unlink_dbfile;
11457718be8SEnji Cooper 
11557718be8SEnji Cooper 	infoarg = NULL;
11657718be8SEnji Cooper 	fname = NULL;
11757718be8SEnji Cooper 	unlink_dbfile = false;
11857718be8SEnji Cooper 	oflags = O_CREAT | O_RDWR;
11957718be8SEnji Cooper 	sflag = 0;
12057718be8SEnji Cooper 	while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1)
12157718be8SEnji Cooper 		switch (ch) {
12257718be8SEnji Cooper 		case 'f':
12357718be8SEnji Cooper 			fname = optarg;
12457718be8SEnji Cooper 			break;
12557718be8SEnji Cooper 		case 'i':
12657718be8SEnji Cooper 			infoarg = optarg;
12757718be8SEnji Cooper 			break;
12857718be8SEnji Cooper 		case 'l':
12957718be8SEnji Cooper 			oflags |= DB_LOCK;
13057718be8SEnji Cooper 			break;
13157718be8SEnji Cooper 		case 'o':
13257718be8SEnji Cooper 			if ((ofd = open(optarg,
13357718be8SEnji Cooper 			    O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
13457718be8SEnji Cooper 				err(1, "Cannot create `%s'", optarg);
13557718be8SEnji Cooper 			break;
13657718be8SEnji Cooper 		case 's':
13757718be8SEnji Cooper 			sflag = 1;
13857718be8SEnji Cooper 			break;
13957718be8SEnji Cooper 		case '?':
14057718be8SEnji Cooper 		default:
14157718be8SEnji Cooper 			usage();
14257718be8SEnji Cooper 		}
14357718be8SEnji Cooper 	argc -= optind;
14457718be8SEnji Cooper 	argv += optind;
14557718be8SEnji Cooper 
14657718be8SEnji Cooper 	if (argc != 2)
14757718be8SEnji Cooper 		usage();
14857718be8SEnji Cooper 
14957718be8SEnji Cooper 	/* Set the type. */
15057718be8SEnji Cooper 	type = dbtype(*argv++);
15157718be8SEnji Cooper 
15257718be8SEnji Cooper 	/* Open the descriptor file. */
15357718be8SEnji Cooper         if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
15457718be8SEnji Cooper 	    err(1, "Cannot reopen `%s'", *argv);
15557718be8SEnji Cooper 
15657718be8SEnji Cooper 	/* Set up the db structure as necessary. */
15757718be8SEnji Cooper 	if (infoarg == NULL)
15857718be8SEnji Cooper 		infop = NULL;
15957718be8SEnji Cooper 	else
16057718be8SEnji Cooper 		for (p = strtok(infoarg, ",\t "); p != NULL;
16157718be8SEnji Cooper 		    p = strtok(0, ",\t "))
16257718be8SEnji Cooper 			if (*p != '\0')
16357718be8SEnji Cooper 				infop = setinfo(type, p);
16457718be8SEnji Cooper 
16557718be8SEnji Cooper 	/*
16657718be8SEnji Cooper 	 * Open the DB.  Delete any preexisting copy, you almost never
16757718be8SEnji Cooper 	 * want it around, and it often screws up tests.
16857718be8SEnji Cooper 	 */
16957718be8SEnji Cooper 	if (fname == NULL) {
17057718be8SEnji Cooper 		const char *q = getenv("TMPDIR");
17157718be8SEnji Cooper 		if (q == NULL)
17257718be8SEnji Cooper 			q = "/var/tmp";
17357718be8SEnji Cooper 		(void)snprintf(buf, sizeof(buf), "%s/__dbtest", q);
17457718be8SEnji Cooper 		fname = buf;
17557718be8SEnji Cooper 		(void)unlink(buf);
17657718be8SEnji Cooper 		unlink_dbfile = true;
17757718be8SEnji Cooper 	} else  if (!sflag)
17857718be8SEnji Cooper 		(void)unlink(fname);
17957718be8SEnji Cooper 
18057718be8SEnji Cooper 	if ((dbp = dbopen(fname,
18157718be8SEnji Cooper 	    oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
18257718be8SEnji Cooper 		err(1, "Cannot dbopen `%s'", fname);
18357718be8SEnji Cooper 	XXdbp = dbp;
18457718be8SEnji Cooper 	if (unlink_dbfile)
18557718be8SEnji Cooper 		(void)unlink(fname);
18657718be8SEnji Cooper 
18757718be8SEnji Cooper 	state = COMMAND;
18857718be8SEnji Cooper 	for (lineno = 1;
18957718be8SEnji Cooper 	    (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
19057718be8SEnji Cooper 		/* Delete the newline, displaying the key/data is easier. */
19157718be8SEnji Cooper 		if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
19257718be8SEnji Cooper 			*t = '\0';
19357718be8SEnji Cooper 		if ((len = strlen(buf)) == 0 || isspace((unsigned char)*p) ||
19457718be8SEnji Cooper 		    *p == '#')
19557718be8SEnji Cooper 			continue;
19657718be8SEnji Cooper 
19757718be8SEnji Cooper 		/* Convenient gdb break point. */
19857718be8SEnji Cooper 		if (XXlineno == lineno)
19957718be8SEnji Cooper 			XXlineno = 1;
20057718be8SEnji Cooper 		switch (*p) {
20157718be8SEnji Cooper 		case 'c':			/* compare */
20257718be8SEnji Cooper 			chkcmd(state);
20357718be8SEnji Cooper 			state = KEY;
20457718be8SEnji Cooper 			command = COMPARE;
20557718be8SEnji Cooper 			break;
20657718be8SEnji Cooper 		case 'e':			/* echo */
20757718be8SEnji Cooper 			chkcmd(state);
20857718be8SEnji Cooper 			/* Don't display the newline, if CR at EOL. */
20957718be8SEnji Cooper 			if (p[len - 2] == '\r')
21057718be8SEnji Cooper 				--len;
21157718be8SEnji Cooper 			if (write(ofd, p + 1, len - 1) != (ssize_t)len - 1 ||
21257718be8SEnji Cooper 			    write(ofd, "\n", 1) != 1)
21357718be8SEnji Cooper 				err(1, "write failed");
21457718be8SEnji Cooper 			break;
21557718be8SEnji Cooper 		case 'g':			/* get */
21657718be8SEnji Cooper 			chkcmd(state);
21757718be8SEnji Cooper 			state = KEY;
21857718be8SEnji Cooper 			command = GET;
21957718be8SEnji Cooper 			break;
22057718be8SEnji Cooper 		case 'p':			/* put */
22157718be8SEnji Cooper 			chkcmd(state);
22257718be8SEnji Cooper 			state = KEY;
22357718be8SEnji Cooper 			command = PUT;
22457718be8SEnji Cooper 			break;
22557718be8SEnji Cooper 		case 'r':			/* remove */
22657718be8SEnji Cooper 			chkcmd(state);
22757718be8SEnji Cooper                         if (flags == R_CURSOR) {
22857718be8SEnji Cooper 				rem(dbp, &key);
22957718be8SEnji Cooper 				state = COMMAND;
23057718be8SEnji Cooper                         } else {
23157718be8SEnji Cooper 				state = KEY;
23257718be8SEnji Cooper 				command = REMOVE;
23357718be8SEnji Cooper 			}
23457718be8SEnji Cooper 			break;
23557718be8SEnji Cooper 		case 'S':			/* sync */
23657718be8SEnji Cooper 			chkcmd(state);
23757718be8SEnji Cooper 			synk(dbp);
23857718be8SEnji Cooper 			state = COMMAND;
23957718be8SEnji Cooper 			break;
24057718be8SEnji Cooper 		case 's':			/* seq */
24157718be8SEnji Cooper 			chkcmd(state);
24257718be8SEnji Cooper 			if (flags == R_CURSOR) {
24357718be8SEnji Cooper 				state = KEY;
24457718be8SEnji Cooper 				command = SEQ;
24557718be8SEnji Cooper 			} else
24657718be8SEnji Cooper 				seq(dbp, &key);
24757718be8SEnji Cooper 			break;
24857718be8SEnji Cooper 		case 'f':
24957718be8SEnji Cooper 			flags = setflags(p + 1);
25057718be8SEnji Cooper 			break;
25157718be8SEnji Cooper 		case 'D':			/* data file */
25257718be8SEnji Cooper 			chkdata(state);
25357718be8SEnji Cooper 			data.data = rfile(p + 1, &data.size);
25457718be8SEnji Cooper 			goto ldata;
25557718be8SEnji Cooper 		case 'd':			/* data */
25657718be8SEnji Cooper 			chkdata(state);
25757718be8SEnji Cooper 			data.data = xcopy(p + 1, len - 1);
25857718be8SEnji Cooper 			data.size = len - 1;
25957718be8SEnji Cooper ldata:			switch (command) {
26057718be8SEnji Cooper 			case COMPARE:
26157718be8SEnji Cooper 				compare(&keydata, &data);
26257718be8SEnji Cooper 				break;
26357718be8SEnji Cooper 			case PUT:
26457718be8SEnji Cooper 				put(dbp, &key, &data);
26557718be8SEnji Cooper 				break;
26657718be8SEnji Cooper 			default:
26757718be8SEnji Cooper 				errx(1, "line %zu: command doesn't take data",
26857718be8SEnji Cooper 				    lineno);
26957718be8SEnji Cooper 			}
27057718be8SEnji Cooper 			if (type != DB_RECNO)
27157718be8SEnji Cooper 				free(key.data);
27257718be8SEnji Cooper 			free(data.data);
27357718be8SEnji Cooper 			state = COMMAND;
27457718be8SEnji Cooper 			break;
27557718be8SEnji Cooper 		case 'K':			/* key file */
27657718be8SEnji Cooper 			chkkey(state);
27757718be8SEnji Cooper 			if (type == DB_RECNO)
27857718be8SEnji Cooper 				errx(1, "line %zu: 'K' not available for recno",
27957718be8SEnji Cooper 				    lineno);
28057718be8SEnji Cooper 			key.data = rfile(p + 1, &key.size);
28157718be8SEnji Cooper 			goto lkey;
28257718be8SEnji Cooper 		case 'k':			/* key */
28357718be8SEnji Cooper 			chkkey(state);
28457718be8SEnji Cooper 			if (type == DB_RECNO) {
28557718be8SEnji Cooper 				static recno_t recno;
28657718be8SEnji Cooper 				recno = atoi(p + 1);
28757718be8SEnji Cooper 				key.data = &recno;
28857718be8SEnji Cooper 				key.size = sizeof(recno);
28957718be8SEnji Cooper 			} else {
29057718be8SEnji Cooper 				key.data = xcopy(p + 1, len - 1);
29157718be8SEnji Cooper 				key.size = len - 1;
29257718be8SEnji Cooper 			}
29357718be8SEnji Cooper lkey:			switch (command) {
29457718be8SEnji Cooper 			case COMPARE:
29557718be8SEnji Cooper 				getdata(dbp, &key, &keydata);
29657718be8SEnji Cooper 				state = DATA;
29757718be8SEnji Cooper 				break;
29857718be8SEnji Cooper 			case GET:
29957718be8SEnji Cooper 				get(dbp, &key);
30057718be8SEnji Cooper 				if (type != DB_RECNO)
30157718be8SEnji Cooper 					free(key.data);
30257718be8SEnji Cooper 				state = COMMAND;
30357718be8SEnji Cooper 				break;
30457718be8SEnji Cooper 			case PUT:
30557718be8SEnji Cooper 				state = DATA;
30657718be8SEnji Cooper 				break;
30757718be8SEnji Cooper 			case REMOVE:
30857718be8SEnji Cooper 				rem(dbp, &key);
30957718be8SEnji Cooper 				if ((type != DB_RECNO) && (flags != R_CURSOR))
31057718be8SEnji Cooper 					free(key.data);
31157718be8SEnji Cooper 				state = COMMAND;
31257718be8SEnji Cooper 				break;
31357718be8SEnji Cooper 			case SEQ:
31457718be8SEnji Cooper 				seq(dbp, &key);
31557718be8SEnji Cooper 				if ((type != DB_RECNO) && (flags != R_CURSOR))
31657718be8SEnji Cooper 					free(key.data);
31757718be8SEnji Cooper 				state = COMMAND;
31857718be8SEnji Cooper 				break;
31957718be8SEnji Cooper 			default:
32057718be8SEnji Cooper 				errx(1, "line %zu: command doesn't take a key",
32157718be8SEnji Cooper 				    lineno);
32257718be8SEnji Cooper 			}
32357718be8SEnji Cooper 			break;
32457718be8SEnji Cooper 		case 'o':
325*cdebaff8SEnji Cooper 			dump(dbp, p[1] == 'r', 0);
32657718be8SEnji Cooper 			break;
327*cdebaff8SEnji Cooper #ifdef	__NetBSD__
328*cdebaff8SEnji Cooper 		case 'O':
329*cdebaff8SEnji Cooper 			dump(dbp, p[1] == 'r', 1);
330*cdebaff8SEnji Cooper 			break;
331*cdebaff8SEnji Cooper 		case 'u':
332*cdebaff8SEnji Cooper 			unlinkpg(dbp);
333*cdebaff8SEnji Cooper 			break;
334*cdebaff8SEnji Cooper #endif
33557718be8SEnji Cooper 		default:
33657718be8SEnji Cooper 			errx(1, "line %zu: %s: unknown command character",
33757718be8SEnji Cooper 			    lineno, p);
33857718be8SEnji Cooper 		}
33957718be8SEnji Cooper 	}
34057718be8SEnji Cooper #ifdef STATISTICS
34157718be8SEnji Cooper 	/*
34257718be8SEnji Cooper 	 * -l must be used (DB_LOCK must be set) for this to be
34357718be8SEnji Cooper 	 * used, otherwise a page will be locked and it will fail.
34457718be8SEnji Cooper 	 */
34557718be8SEnji Cooper 	if (type == DB_BTREE && oflags & DB_LOCK)
34657718be8SEnji Cooper 		__bt_stat(dbp);
34757718be8SEnji Cooper #endif
34857718be8SEnji Cooper 	if ((*dbp->close)(dbp))
34957718be8SEnji Cooper 		err(1, "db->close failed");
35057718be8SEnji Cooper 	(void)close(ofd);
35157718be8SEnji Cooper 	return 0;
35257718be8SEnji Cooper }
35357718be8SEnji Cooper 
35457718be8SEnji Cooper #define	NOOVERWRITE	"put failed, would overwrite key\n"
35557718be8SEnji Cooper 
35657718be8SEnji Cooper static void
compare(DBT * db1,DBT * db2)35757718be8SEnji Cooper compare(DBT *db1, DBT *db2)
35857718be8SEnji Cooper {
35957718be8SEnji Cooper 	size_t len;
36057718be8SEnji Cooper 	u_char *p1, *p2;
36157718be8SEnji Cooper 
36257718be8SEnji Cooper 	if (db1->size != db2->size)
36357718be8SEnji Cooper 		printf("compare failed: key->data len %zu != data len %zu\n",
36457718be8SEnji Cooper 		    db1->size, db2->size);
36557718be8SEnji Cooper 
36657718be8SEnji Cooper 	len = MIN(db1->size, db2->size);
36757718be8SEnji Cooper 	for (p1 = db1->data, p2 = db2->data; len--;)
36857718be8SEnji Cooper 		if (*p1++ != *p2++) {
36957718be8SEnji Cooper 			printf("compare failed at offset %lu\n",
37057718be8SEnji Cooper 			    (unsigned long)(p1 - (u_char *)db1->data));
37157718be8SEnji Cooper 			break;
37257718be8SEnji Cooper 		}
37357718be8SEnji Cooper }
37457718be8SEnji Cooper 
37557718be8SEnji Cooper static void
get(DB * dbp,DBT * kp)37657718be8SEnji Cooper get(DB *dbp, DBT *kp)
37757718be8SEnji Cooper {
37857718be8SEnji Cooper 	DBT data;
37957718be8SEnji Cooper 
38057718be8SEnji Cooper 	switch ((*dbp->get)(dbp, kp, &data, flags)) {
38157718be8SEnji Cooper 	case 0:
38257718be8SEnji Cooper 		(void)write(ofd, data.data, data.size);
38357718be8SEnji Cooper 		if (ofd == STDOUT_FILENO)
38457718be8SEnji Cooper 			(void)write(ofd, "\n", 1);
38557718be8SEnji Cooper 		break;
38657718be8SEnji Cooper 	case -1:
38757718be8SEnji Cooper 		err(1, "line %zu: get failed", lineno);
38857718be8SEnji Cooper 		/* NOTREACHED */
38957718be8SEnji Cooper 	case 1:
39057718be8SEnji Cooper #define	NOSUCHKEY	"get failed, no such key\n"
39157718be8SEnji Cooper 		if (ofd != STDOUT_FILENO)
39257718be8SEnji Cooper 			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
39357718be8SEnji Cooper 		else
39457718be8SEnji Cooper 			(void)fprintf(stderr, "%zu: %.*s: %s",
39557718be8SEnji Cooper 			    lineno, (int)MIN(kp->size, 20),
39657718be8SEnji Cooper 			    (const char *)kp->data,
39757718be8SEnji Cooper 			    NOSUCHKEY);
39857718be8SEnji Cooper #undef	NOSUCHKEY
39957718be8SEnji Cooper 		break;
40057718be8SEnji Cooper 	}
40157718be8SEnji Cooper }
40257718be8SEnji Cooper 
40357718be8SEnji Cooper static void
getdata(DB * dbp,DBT * kp,DBT * dp)40457718be8SEnji Cooper getdata(DB *dbp, DBT *kp, DBT *dp)
40557718be8SEnji Cooper {
40657718be8SEnji Cooper 	switch ((*dbp->get)(dbp, kp, dp, flags)) {
40757718be8SEnji Cooper 	case 0:
40857718be8SEnji Cooper 		return;
40957718be8SEnji Cooper 	case -1:
41057718be8SEnji Cooper 		err(1, "line %zu: getdata failed", lineno);
41157718be8SEnji Cooper 		/* NOTREACHED */
41257718be8SEnji Cooper 	case 1:
41357718be8SEnji Cooper 		errx(1, "line %zu: getdata failed, no such key", lineno);
41457718be8SEnji Cooper 		/* NOTREACHED */
41557718be8SEnji Cooper 	}
41657718be8SEnji Cooper }
41757718be8SEnji Cooper 
41857718be8SEnji Cooper static void
put(DB * dbp,DBT * kp,DBT * dp)41957718be8SEnji Cooper put(DB *dbp, DBT *kp, DBT *dp)
42057718be8SEnji Cooper {
42157718be8SEnji Cooper 	switch ((*dbp->put)(dbp, kp, dp, flags)) {
42257718be8SEnji Cooper 	case 0:
42357718be8SEnji Cooper 		break;
42457718be8SEnji Cooper 	case -1:
42557718be8SEnji Cooper 		err(1, "line %zu: put failed", lineno);
42657718be8SEnji Cooper 		/* NOTREACHED */
42757718be8SEnji Cooper 	case 1:
42857718be8SEnji Cooper 		(void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
42957718be8SEnji Cooper 		break;
43057718be8SEnji Cooper 	}
43157718be8SEnji Cooper }
43257718be8SEnji Cooper 
43357718be8SEnji Cooper static void
rem(DB * dbp,DBT * kp)43457718be8SEnji Cooper rem(DB *dbp, DBT *kp)
43557718be8SEnji Cooper {
43657718be8SEnji Cooper 	switch ((*dbp->del)(dbp, kp, flags)) {
43757718be8SEnji Cooper 	case 0:
43857718be8SEnji Cooper 		break;
43957718be8SEnji Cooper 	case -1:
44057718be8SEnji Cooper 		err(1, "line %zu: rem failed", lineno);
44157718be8SEnji Cooper 		/* NOTREACHED */
44257718be8SEnji Cooper 	case 1:
44357718be8SEnji Cooper #define	NOSUCHKEY	"rem failed, no such key\n"
44457718be8SEnji Cooper 		if (ofd != STDOUT_FILENO)
44557718be8SEnji Cooper 			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
44657718be8SEnji Cooper 		else if (flags != R_CURSOR)
44757718be8SEnji Cooper 			(void)fprintf(stderr, "%zu: %.*s: %s",
44857718be8SEnji Cooper 			    lineno, (int)MIN(kp->size, 20),
44957718be8SEnji Cooper 			    (const char *)kp->data, NOSUCHKEY);
45057718be8SEnji Cooper 		else
45157718be8SEnji Cooper 			(void)fprintf(stderr,
45257718be8SEnji Cooper 			    "%zu: rem of cursor failed\n", lineno);
45357718be8SEnji Cooper #undef	NOSUCHKEY
45457718be8SEnji Cooper 		break;
45557718be8SEnji Cooper 	}
45657718be8SEnji Cooper }
45757718be8SEnji Cooper 
45857718be8SEnji Cooper static void
synk(DB * dbp)45957718be8SEnji Cooper synk(DB *dbp)
46057718be8SEnji Cooper {
46157718be8SEnji Cooper 	switch ((*dbp->sync)(dbp, flags)) {
46257718be8SEnji Cooper 	case 0:
46357718be8SEnji Cooper 		break;
46457718be8SEnji Cooper 	case -1:
46557718be8SEnji Cooper 		err(1, "line %zu: synk failed", lineno);
46657718be8SEnji Cooper 		/* NOTREACHED */
46757718be8SEnji Cooper 	}
46857718be8SEnji Cooper }
46957718be8SEnji Cooper 
47057718be8SEnji Cooper static void
seq(DB * dbp,DBT * kp)47157718be8SEnji Cooper seq(DB *dbp, DBT *kp)
47257718be8SEnji Cooper {
47357718be8SEnji Cooper 	DBT data;
47457718be8SEnji Cooper 
47557718be8SEnji Cooper 	switch (dbp->seq(dbp, kp, &data, flags)) {
47657718be8SEnji Cooper 	case 0:
47757718be8SEnji Cooper 		(void)write(ofd, data.data, data.size);
47857718be8SEnji Cooper 		if (ofd == STDOUT_FILENO)
47957718be8SEnji Cooper 			(void)write(ofd, "\n", 1);
48057718be8SEnji Cooper 		break;
48157718be8SEnji Cooper 	case -1:
48257718be8SEnji Cooper 		err(1, "line %zu: seq failed", lineno);
48357718be8SEnji Cooper 		/* NOTREACHED */
48457718be8SEnji Cooper 	case 1:
48557718be8SEnji Cooper #define	NOSUCHKEY	"seq failed, no such key\n"
48657718be8SEnji Cooper 		if (ofd != STDOUT_FILENO)
48757718be8SEnji Cooper 			(void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
48857718be8SEnji Cooper 		else if (flags == R_CURSOR)
48957718be8SEnji Cooper 			(void)fprintf(stderr, "%zu: %.*s: %s",
49057718be8SEnji Cooper 			    lineno, (int)MIN(kp->size, 20),
49157718be8SEnji Cooper 			    (const char *)kp->data, NOSUCHKEY);
49257718be8SEnji Cooper 		else
49357718be8SEnji Cooper 			(void)fprintf(stderr,
49457718be8SEnji Cooper 			    "%zu: seq (%s) failed\n", lineno, sflags(flags));
49557718be8SEnji Cooper #undef	NOSUCHKEY
49657718be8SEnji Cooper 		break;
49757718be8SEnji Cooper 	}
49857718be8SEnji Cooper }
49957718be8SEnji Cooper 
50057718be8SEnji Cooper static void
dump(DB * dbp,int rev,int recurse)501*cdebaff8SEnji Cooper dump(DB *dbp, int rev, int recurse)
50257718be8SEnji Cooper {
50357718be8SEnji Cooper 	DBT key, data;
50457718be8SEnji Cooper 	int xflags, nflags;
50557718be8SEnji Cooper 
50657718be8SEnji Cooper 	if (rev) {
50757718be8SEnji Cooper 		xflags = R_LAST;
508*cdebaff8SEnji Cooper #ifdef __NetBSD__
509*cdebaff8SEnji Cooper 		nflags = recurse ? R_RPREV : R_PREV;
510*cdebaff8SEnji Cooper #else
51157718be8SEnji Cooper 		nflags = R_PREV;
512*cdebaff8SEnji Cooper #endif
51357718be8SEnji Cooper 	} else {
51457718be8SEnji Cooper 		xflags = R_FIRST;
515*cdebaff8SEnji Cooper #ifdef __NetBSD__
516*cdebaff8SEnji Cooper 		nflags = recurse ? R_RNEXT : R_NEXT;
517*cdebaff8SEnji Cooper #else
51857718be8SEnji Cooper 		nflags = R_NEXT;
519*cdebaff8SEnji Cooper #endif
52057718be8SEnji Cooper 	}
52157718be8SEnji Cooper 	for (;; xflags = nflags)
52257718be8SEnji Cooper 		switch (dbp->seq(dbp, &key, &data, xflags)) {
52357718be8SEnji Cooper 		case 0:
52457718be8SEnji Cooper 			(void)write(ofd, data.data, data.size);
52557718be8SEnji Cooper 			if (ofd == STDOUT_FILENO)
52657718be8SEnji Cooper 				(void)write(ofd, "\n", 1);
52757718be8SEnji Cooper 			break;
52857718be8SEnji Cooper 		case 1:
52957718be8SEnji Cooper 			goto done;
53057718be8SEnji Cooper 		case -1:
53157718be8SEnji Cooper 			err(1, "line %zu: (dump) seq failed", lineno);
53257718be8SEnji Cooper 			/* NOTREACHED */
53357718be8SEnji Cooper 		}
53457718be8SEnji Cooper done:	return;
53557718be8SEnji Cooper }
53657718be8SEnji Cooper 
537*cdebaff8SEnji Cooper #ifdef __NetBSD__
538*cdebaff8SEnji Cooper void
unlinkpg(DB * dbp)539*cdebaff8SEnji Cooper unlinkpg(DB *dbp)
540*cdebaff8SEnji Cooper {
541*cdebaff8SEnji Cooper 	BTREE *t = dbp->internal;
542*cdebaff8SEnji Cooper 	PAGE *h = NULL;
543*cdebaff8SEnji Cooper 	pgno_t pg;
544*cdebaff8SEnji Cooper 
545*cdebaff8SEnji Cooper 	for (pg = P_ROOT; pg < t->bt_mp->npages;
546*cdebaff8SEnji Cooper 	     mpool_put(t->bt_mp, h, 0), pg++) {
547*cdebaff8SEnji Cooper 		if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
548*cdebaff8SEnji Cooper 			break;
549*cdebaff8SEnji Cooper 		/* Look for a nonempty leaf page that has both left
550*cdebaff8SEnji Cooper 		 * and right siblings. */
551*cdebaff8SEnji Cooper 		if (h->prevpg == P_INVALID || h->nextpg == P_INVALID)
552*cdebaff8SEnji Cooper 			continue;
553*cdebaff8SEnji Cooper 		if (NEXTINDEX(h) == 0)
554*cdebaff8SEnji Cooper 			continue;
555*cdebaff8SEnji Cooper 		if ((h->flags & (P_BLEAF | P_RLEAF)))
556*cdebaff8SEnji Cooper 			break;
557*cdebaff8SEnji Cooper 	}
558*cdebaff8SEnji Cooper 	if (h == NULL || pg == t->bt_mp->npages) {
559*cdebaff8SEnji Cooper 		errx(1, "%s: no appropriate page found", __func__);
560*cdebaff8SEnji Cooper 		return;
561*cdebaff8SEnji Cooper 	}
562*cdebaff8SEnji Cooper 	if (__bt_relink(t, h) != 0) {
563*cdebaff8SEnji Cooper 		perror("unlinkpg");
564*cdebaff8SEnji Cooper 		goto cleanup;
565*cdebaff8SEnji Cooper 	}
566*cdebaff8SEnji Cooper 	h->prevpg = P_INVALID;
567*cdebaff8SEnji Cooper 	h->nextpg = P_INVALID;
568*cdebaff8SEnji Cooper cleanup:
569*cdebaff8SEnji Cooper 	mpool_put(t->bt_mp, h, MPOOL_DIRTY);
570*cdebaff8SEnji Cooper }
571*cdebaff8SEnji Cooper #endif
572*cdebaff8SEnji Cooper 
57357718be8SEnji Cooper static u_int
setflags(char * s)57457718be8SEnji Cooper setflags(char *s)
57557718be8SEnji Cooper {
57657718be8SEnji Cooper 	char *p;
57757718be8SEnji Cooper 
57857718be8SEnji Cooper 	for (; isspace((unsigned char)*s); ++s);
57957718be8SEnji Cooper 	if (*s == '\n' || *s == '\0')
58057718be8SEnji Cooper 		return 0;
58157718be8SEnji Cooper 	if ((p = strchr(s, '\n')) != NULL)
58257718be8SEnji Cooper 		*p = '\0';
58357718be8SEnji Cooper 	if (!strcmp(s, "R_CURSOR"))		return R_CURSOR;
58457718be8SEnji Cooper 	if (!strcmp(s, "R_FIRST"))		return R_FIRST;
58557718be8SEnji Cooper 	if (!strcmp(s, "R_IAFTER")) 		return R_IAFTER;
58657718be8SEnji Cooper 	if (!strcmp(s, "R_IBEFORE")) 		return R_IBEFORE;
58757718be8SEnji Cooper 	if (!strcmp(s, "R_LAST")) 		return R_LAST;
58857718be8SEnji Cooper 	if (!strcmp(s, "R_NEXT")) 		return R_NEXT;
58957718be8SEnji Cooper 	if (!strcmp(s, "R_NOOVERWRITE"))	return R_NOOVERWRITE;
59057718be8SEnji Cooper 	if (!strcmp(s, "R_PREV"))		return R_PREV;
59157718be8SEnji Cooper 	if (!strcmp(s, "R_SETCURSOR"))		return R_SETCURSOR;
59257718be8SEnji Cooper 
59357718be8SEnji Cooper 	errx(1, "line %zu: %s: unknown flag", lineno, s);
59457718be8SEnji Cooper 	/* NOTREACHED */
59557718be8SEnji Cooper }
59657718be8SEnji Cooper 
59757718be8SEnji Cooper static const char *
sflags(int xflags)59857718be8SEnji Cooper sflags(int xflags)
59957718be8SEnji Cooper {
60057718be8SEnji Cooper 	switch (xflags) {
60157718be8SEnji Cooper 	case R_CURSOR:		return "R_CURSOR";
60257718be8SEnji Cooper 	case R_FIRST:		return "R_FIRST";
60357718be8SEnji Cooper 	case R_IAFTER:		return "R_IAFTER";
60457718be8SEnji Cooper 	case R_IBEFORE:		return "R_IBEFORE";
60557718be8SEnji Cooper 	case R_LAST:		return "R_LAST";
60657718be8SEnji Cooper 	case R_NEXT:		return "R_NEXT";
60757718be8SEnji Cooper 	case R_NOOVERWRITE:	return "R_NOOVERWRITE";
60857718be8SEnji Cooper 	case R_PREV:		return "R_PREV";
60957718be8SEnji Cooper 	case R_SETCURSOR:	return "R_SETCURSOR";
61057718be8SEnji Cooper 	}
61157718be8SEnji Cooper 
61257718be8SEnji Cooper 	return "UNKNOWN!";
61357718be8SEnji Cooper }
61457718be8SEnji Cooper 
61557718be8SEnji Cooper static DBTYPE
dbtype(const char * s)61657718be8SEnji Cooper dbtype(const char *s)
61757718be8SEnji Cooper {
61857718be8SEnji Cooper 	if (!strcmp(s, "btree"))
61957718be8SEnji Cooper 		return DB_BTREE;
62057718be8SEnji Cooper 	if (!strcmp(s, "hash"))
62157718be8SEnji Cooper 		return DB_HASH;
62257718be8SEnji Cooper 	if (!strcmp(s, "recno"))
62357718be8SEnji Cooper 		return DB_RECNO;
62457718be8SEnji Cooper 	errx(1, "%s: unknown type (use btree, hash or recno)", s);
62557718be8SEnji Cooper 	/* NOTREACHED */
62657718be8SEnji Cooper }
62757718be8SEnji Cooper 
62857718be8SEnji Cooper static void *
setinfo(DBTYPE dtype,char * s)62957718be8SEnji Cooper setinfo(DBTYPE dtype, char *s)
63057718be8SEnji Cooper {
63157718be8SEnji Cooper 	static BTREEINFO ib;
63257718be8SEnji Cooper 	static HASHINFO ih;
63357718be8SEnji Cooper 	static RECNOINFO rh;
63457718be8SEnji Cooper 	char *eq;
63557718be8SEnji Cooper 
63657718be8SEnji Cooper 	if ((eq = strchr(s, '=')) == NULL)
63757718be8SEnji Cooper 		errx(1, "%s: illegal structure set statement", s);
63857718be8SEnji Cooper 	*eq++ = '\0';
63957718be8SEnji Cooper 	if (!isdigit((unsigned char)*eq))
64057718be8SEnji Cooper 		errx(1, "%s: structure set statement must be a number", s);
64157718be8SEnji Cooper 
64257718be8SEnji Cooper 	switch (dtype) {
64357718be8SEnji Cooper 	case DB_BTREE:
64457718be8SEnji Cooper 		if (!strcmp("flags", s)) {
64557718be8SEnji Cooper 			ib.flags = atoi(eq);
64657718be8SEnji Cooper 			return &ib;
64757718be8SEnji Cooper 		}
64857718be8SEnji Cooper 		if (!strcmp("cachesize", s)) {
64957718be8SEnji Cooper 			ib.cachesize = atoi(eq);
65057718be8SEnji Cooper 			return &ib;
65157718be8SEnji Cooper 		}
65257718be8SEnji Cooper 		if (!strcmp("maxkeypage", s)) {
65357718be8SEnji Cooper 			ib.maxkeypage = atoi(eq);
65457718be8SEnji Cooper 			return &ib;
65557718be8SEnji Cooper 		}
65657718be8SEnji Cooper 		if (!strcmp("minkeypage", s)) {
65757718be8SEnji Cooper 			ib.minkeypage = atoi(eq);
65857718be8SEnji Cooper 			return &ib;
65957718be8SEnji Cooper 		}
66057718be8SEnji Cooper 		if (!strcmp("lorder", s)) {
66157718be8SEnji Cooper 			ib.lorder = atoi(eq);
66257718be8SEnji Cooper 			return &ib;
66357718be8SEnji Cooper 		}
66457718be8SEnji Cooper 		if (!strcmp("psize", s)) {
66557718be8SEnji Cooper 			ib.psize = atoi(eq);
66657718be8SEnji Cooper 			return &ib;
66757718be8SEnji Cooper 		}
66857718be8SEnji Cooper 		break;
66957718be8SEnji Cooper 	case DB_HASH:
67057718be8SEnji Cooper 		if (!strcmp("bsize", s)) {
67157718be8SEnji Cooper 			ih.bsize = atoi(eq);
67257718be8SEnji Cooper 			return &ih;
67357718be8SEnji Cooper 		}
67457718be8SEnji Cooper 		if (!strcmp("ffactor", s)) {
67557718be8SEnji Cooper 			ih.ffactor = atoi(eq);
67657718be8SEnji Cooper 			return &ih;
67757718be8SEnji Cooper 		}
67857718be8SEnji Cooper 		if (!strcmp("nelem", s)) {
67957718be8SEnji Cooper 			ih.nelem = atoi(eq);
68057718be8SEnji Cooper 			return &ih;
68157718be8SEnji Cooper 		}
68257718be8SEnji Cooper 		if (!strcmp("cachesize", s)) {
68357718be8SEnji Cooper 			ih.cachesize = atoi(eq);
68457718be8SEnji Cooper 			return &ih;
68557718be8SEnji Cooper 		}
68657718be8SEnji Cooper 		if (!strcmp("lorder", s)) {
68757718be8SEnji Cooper 			ih.lorder = atoi(eq);
68857718be8SEnji Cooper 			return &ih;
68957718be8SEnji Cooper 		}
69057718be8SEnji Cooper 		break;
69157718be8SEnji Cooper 	case DB_RECNO:
69257718be8SEnji Cooper 		if (!strcmp("flags", s)) {
69357718be8SEnji Cooper 			rh.flags = atoi(eq);
69457718be8SEnji Cooper 			return &rh;
69557718be8SEnji Cooper 		}
69657718be8SEnji Cooper 		if (!strcmp("cachesize", s)) {
69757718be8SEnji Cooper 			rh.cachesize = atoi(eq);
69857718be8SEnji Cooper 			return &rh;
69957718be8SEnji Cooper 		}
70057718be8SEnji Cooper 		if (!strcmp("lorder", s)) {
70157718be8SEnji Cooper 			rh.lorder = atoi(eq);
70257718be8SEnji Cooper 			return &rh;
70357718be8SEnji Cooper 		}
70457718be8SEnji Cooper 		if (!strcmp("reclen", s)) {
70557718be8SEnji Cooper 			rh.reclen = atoi(eq);
70657718be8SEnji Cooper 			return &rh;
70757718be8SEnji Cooper 		}
70857718be8SEnji Cooper 		if (!strcmp("bval", s)) {
70957718be8SEnji Cooper 			rh.bval = atoi(eq);
71057718be8SEnji Cooper 			return &rh;
71157718be8SEnji Cooper 		}
71257718be8SEnji Cooper 		if (!strcmp("psize", s)) {
71357718be8SEnji Cooper 			rh.psize = atoi(eq);
71457718be8SEnji Cooper 			return &rh;
71557718be8SEnji Cooper 		}
71657718be8SEnji Cooper 		break;
71757718be8SEnji Cooper 	}
71857718be8SEnji Cooper 	errx(1, "%s: unknown structure value", s);
71957718be8SEnji Cooper 	/* NOTREACHED */
72057718be8SEnji Cooper }
72157718be8SEnji Cooper 
72257718be8SEnji Cooper static void *
rfile(char * name,size_t * lenp)72357718be8SEnji Cooper rfile(char *name, size_t *lenp)
72457718be8SEnji Cooper {
72557718be8SEnji Cooper 	struct stat sb;
72657718be8SEnji Cooper 	void *p;
72757718be8SEnji Cooper 	int fd;
72857718be8SEnji Cooper 	char *np;
72957718be8SEnji Cooper 
73057718be8SEnji Cooper 	for (; isspace((unsigned char)*name); ++name)
73157718be8SEnji Cooper 		continue;
73257718be8SEnji Cooper 	if ((np = strchr(name, '\n')) != NULL)
73357718be8SEnji Cooper 		*np = '\0';
73457718be8SEnji Cooper 	if ((fd = open(name, O_RDONLY, 0)) == -1 || fstat(fd, &sb) == -1)
73557718be8SEnji Cooper 		err(1, "Cannot open `%s'", name);
73657718be8SEnji Cooper #ifdef NOT_PORTABLE
73757718be8SEnji Cooper 	if (sb.st_size > (off_t)SIZE_T_MAX) {
73857718be8SEnji Cooper 		errno = E2BIG;
73957718be8SEnji Cooper 		err("Cannot process `%s'", name);
74057718be8SEnji Cooper 	}
74157718be8SEnji Cooper #endif
74257718be8SEnji Cooper 	if ((p = malloc((size_t)sb.st_size)) == NULL)
74357718be8SEnji Cooper 		err(1, "Cannot allocate %zu bytes", (size_t)sb.st_size);
74457718be8SEnji Cooper 	if (read(fd, p, (ssize_t)sb.st_size) != (ssize_t)sb.st_size)
74557718be8SEnji Cooper 		err(1, "read failed");
74657718be8SEnji Cooper 	*lenp = (size_t)sb.st_size;
74757718be8SEnji Cooper 	(void)close(fd);
74857718be8SEnji Cooper 	return p;
74957718be8SEnji Cooper }
75057718be8SEnji Cooper 
75157718be8SEnji Cooper static void *
xcopy(void * text,size_t len)75257718be8SEnji Cooper xcopy(void *text, size_t len)
75357718be8SEnji Cooper {
75457718be8SEnji Cooper 	void *p;
75557718be8SEnji Cooper 
75657718be8SEnji Cooper 	if ((p = malloc(len)) == NULL)
75757718be8SEnji Cooper 		err(1, "Cannot allocate %zu bytes", len);
75857718be8SEnji Cooper 	(void)memmove(p, text, len);
75957718be8SEnji Cooper 	return p;
76057718be8SEnji Cooper }
76157718be8SEnji Cooper 
76257718be8SEnji Cooper static void
chkcmd(enum S state)76357718be8SEnji Cooper chkcmd(enum S state)
76457718be8SEnji Cooper {
76557718be8SEnji Cooper 	if (state != COMMAND)
76657718be8SEnji Cooper 		errx(1, "line %zu: not expecting command", lineno);
76757718be8SEnji Cooper }
76857718be8SEnji Cooper 
76957718be8SEnji Cooper static void
chkdata(enum S state)77057718be8SEnji Cooper chkdata(enum S state)
77157718be8SEnji Cooper {
77257718be8SEnji Cooper 	if (state != DATA)
77357718be8SEnji Cooper 		errx(1, "line %zu: not expecting data", lineno);
77457718be8SEnji Cooper }
77557718be8SEnji Cooper 
77657718be8SEnji Cooper static void
chkkey(enum S state)77757718be8SEnji Cooper chkkey(enum S state)
77857718be8SEnji Cooper {
77957718be8SEnji Cooper 	if (state != KEY)
78057718be8SEnji Cooper 		errx(1, "line %zu: not expecting a key", lineno);
78157718be8SEnji Cooper }
78257718be8SEnji Cooper 
78357718be8SEnji Cooper static void
usage(void)78457718be8SEnji Cooper usage(void)
78557718be8SEnji Cooper {
78657718be8SEnji Cooper 	(void)fprintf(stderr,
787*cdebaff8SEnji Cooper #ifdef __NetBSD__
788*cdebaff8SEnji Cooper 	    "Usage: %s [-lu] [-f file] [-i info] [-o file] [-O file] "
789*cdebaff8SEnji Cooper #else
790*cdebaff8SEnji Cooper 	    "Usage: %s [-l] [-f file] [-i info] [-o file] "
791*cdebaff8SEnji Cooper #endif
792*cdebaff8SEnji Cooper 		"type script\n", getprogname());
79357718be8SEnji Cooper 	exit(1);
79457718be8SEnji Cooper }
795