1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1997,2008 Oracle.  All rights reserved.
5 *
6 * $Id: ex_access.c,v 12.7 2008/01/08 20:58:23 bostic Exp $
7 */
8
9#include <sys/types.h>
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#ifdef _WIN32
16extern int getopt(int, char * const *, const char *);
17#else
18#include <unistd.h>
19#endif
20
21#include <db.h>
22
23#define	DATABASE	"access.db"
24int main __P((int, char *[]));
25int usage __P((void));
26
27int
28main(argc, argv)
29	int argc;
30	char *argv[];
31{
32	extern int optind;
33	DB *dbp;
34	DBC *dbcp;
35	DBT key, data;
36	size_t len;
37	int ch, ret, rflag;
38	char *database, *p, *t, buf[1024], rbuf[1024];
39	const char *progname = "ex_access";		/* Program name. */
40
41	rflag = 0;
42	while ((ch = getopt(argc, argv, "r")) != EOF)
43		switch (ch) {
44		case 'r':
45			rflag = 1;
46			break;
47		case '?':
48		default:
49			return (usage());
50		}
51	argc -= optind;
52	argv += optind;
53
54	/* Accept optional database name. */
55	database = *argv == NULL ? DATABASE : argv[0];
56
57	/* Optionally discard the database. */
58	if (rflag)
59		(void)remove(database);
60
61	/* Create and initialize database object, open the database. */
62	if ((ret = db_create(&dbp, NULL, 0)) != 0) {
63		fprintf(stderr,
64		    "%s: db_create: %s\n", progname, db_strerror(ret));
65		return (EXIT_FAILURE);
66	}
67	dbp->set_errfile(dbp, stderr);
68	dbp->set_errpfx(dbp, progname);
69	if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
70		dbp->err(dbp, ret, "set_pagesize");
71		goto err1;
72	}
73	if ((ret = dbp->set_cachesize(dbp, 0, 32 * 1024, 0)) != 0) {
74		dbp->err(dbp, ret, "set_cachesize");
75		goto err1;
76	}
77	if ((ret = dbp->open(dbp,
78	    NULL, database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
79		dbp->err(dbp, ret, "%s: open", database);
80		goto err1;
81	}
82
83	/*
84	 * Insert records into the database, where the key is the user
85	 * input and the data is the user input in reverse order.
86	 */
87	memset(&key, 0, sizeof(DBT));
88	memset(&data, 0, sizeof(DBT));
89	for (;;) {
90		printf("input> ");
91		fflush(stdout);
92		if (fgets(buf, sizeof(buf), stdin) == NULL)
93			break;
94		if (strcmp(buf, "exit\n") == 0 || strcmp(buf, "quit\n") == 0)
95			break;
96		if ((len = strlen(buf)) <= 1)
97			continue;
98		for (t = rbuf, p = buf + (len - 2); p >= buf;)
99			*t++ = *p--;
100		*t++ = '\0';
101
102		key.data = buf;
103		data.data = rbuf;
104		data.size = key.size = (u_int32_t)len - 1;
105
106		switch (ret =
107		    dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) {
108		case 0:
109			break;
110		default:
111			dbp->err(dbp, ret, "DB->put");
112			if (ret != DB_KEYEXIST)
113				goto err1;
114			break;
115		}
116	}
117	printf("\n");
118
119	/* Acquire a cursor for the database. */
120	if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
121		dbp->err(dbp, ret, "DB->cursor");
122		goto err1;
123	}
124
125	/* Initialize the key/data pair so the flags aren't set. */
126	memset(&key, 0, sizeof(key));
127	memset(&data, 0, sizeof(data));
128
129	/* Walk through the database and print out the key/data pairs. */
130	while ((ret = dbcp->get(dbcp, &key, &data, DB_NEXT)) == 0)
131		printf("%.*s : %.*s\n",
132		    (int)key.size, (char *)key.data,
133		    (int)data.size, (char *)data.data);
134	if (ret != DB_NOTFOUND) {
135		dbp->err(dbp, ret, "DBcursor->get");
136		goto err2;
137	}
138
139	/* Close everything down. */
140	if ((ret = dbcp->close(dbcp)) != 0) {
141		dbp->err(dbp, ret, "DBcursor->close");
142		goto err1;
143	}
144	if ((ret = dbp->close(dbp, 0)) != 0) {
145		fprintf(stderr,
146		    "%s: DB->close: %s\n", progname, db_strerror(ret));
147		return (EXIT_FAILURE);
148	}
149	return (EXIT_SUCCESS);
150
151err2:	(void)dbcp->close(dbcp);
152err1:	(void)dbp->close(dbp, 0);
153	return (EXIT_FAILURE);
154}
155
156int
157usage()
158{
159	(void)fprintf(stderr, "usage: ex_access [-r] [database]\n");
160	return (EXIT_FAILURE);
161}
162