freebsd-dev/contrib/global/btreeop/btreeop.c

370 lines
7.8 KiB
C
Raw Normal View History

/*
* Copyright (c) 1996, 1997, 1998 Shigio Yamaguchi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Shigio Yamaguchi.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* btreeop.c 12-Nov-98
*
*/
#include <sys/types.h>
1997-12-15 23:13:53 +00:00
#include <sys/stat.h>
#include <ctype.h>
1997-12-15 23:13:53 +00:00
#include <signal.h>
#include <stdlib.h>
#include <string.h>
1997-12-15 23:13:53 +00:00
#include "global.h"
const char *dbdefault = "btree"; /* default database name */
const char *progname = "btreeop"; /* command name */
static void usage __P((void));
1997-12-15 23:13:53 +00:00
void signal_setup __P((void));
void onintr __P((int));
int main __P((int, char **));
void dbwrite __P((DBOP *));
void dbkey __P((DBOP *, char *, int));
void dbscan __P((DBOP *, char *, int));
void dbdel __P((DBOP *, char *, int));
void dbbysecondkey __P((DBOP *, int, char *, int));
1997-12-15 23:13:53 +00:00
#define F_KEY 0
#define F_DEL 1
static void
usage()
{
1997-12-15 23:13:53 +00:00
fprintf(stderr, "%s\n",
"usage: btreeop [-A][-C][-D[n] key][-K[n] key][-L[2]][-k prefix][dbname]");
exit(1);
}
/*
1997-12-15 23:13:53 +00:00
* Btreeop catch signal even if the parent ignore it.
*/
1997-12-15 23:13:53 +00:00
int exitflag = 0;
void
1997-12-15 23:13:53 +00:00
onintr(signo)
int signo;
{
1997-12-15 23:13:53 +00:00
exitflag = 1;
}
1997-12-15 23:13:53 +00:00
void
1997-12-15 23:13:53 +00:00
signal_setup()
{
1997-12-15 23:13:53 +00:00
signal(SIGHUP, onintr);
signal(SIGINT, onintr);
signal(SIGQUIT, onintr);
signal(SIGTERM, onintr);
}
int
main(argc, argv)
int argc;
char *argv[];
{
char command = 'R';
char *key = NULL;
int mode = 0;
const char *db_name;
DBOP *dbop;
1997-12-15 23:13:53 +00:00
int i, c;
int secondkey = 0;
int keylist = 0;
char *prefix = NULL;
1997-12-15 23:13:53 +00:00
for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
switch (c = argv[i][1]) {
case 'D':
1997-12-15 23:13:53 +00:00
case 'K':
if (argv[i][2] && isdigit(argv[i][2]))
secondkey = atoi(&argv[i][2]);
if (++i < argc)
key = argv[i];
else
usage();
/* FALLTHROUGH */
case 'A':
case 'C':
case 'L':
if (command != 'R')
usage();
command = c;
if (command == 'L') {
keylist = 1;
if (argv[i][2] == '2')
keylist = 2;
}
break;
1997-12-15 23:13:53 +00:00
case 'k':
if (++i < argc)
prefix = argv[i];
else
usage();
break;
default:
usage();
}
}
db_name = (i < argc) ? argv[i] : dbdefault;
switch (command) {
case 'A':
case 'D':
1997-12-15 23:13:53 +00:00
mode = 2;
break;
case 'C':
1997-12-15 23:13:53 +00:00
mode = 1;
break;
case 'K':
case 'L':
case 'R':
1997-12-15 23:13:53 +00:00
mode = 0;
break;
}
dbop = dbop_open(db_name, mode, 0644, DBOP_DUP);
if (dbop == NULL) {
switch (mode) {
case 0:
case 2:
die1("cannot open '%s'.", db_name);
break;
case 1:
die1("cannot create '%s'.", db_name);
break;
}
}
switch (command) {
case 'A': /* Append records */
case 'C': /* Create database */
dbwrite(dbop);
break;
case 'D': /* Delete records */
dbdel(dbop, key, secondkey);
break;
case 'K': /* Keyed (indexed) read */
dbkey(dbop, key, secondkey);
break;
case 'R': /* sequencial Read */
1997-12-15 23:13:53 +00:00
case 'L': /* primary key List */
dbscan(dbop, prefix, keylist);
break;
}
dbop_close(dbop);
1997-12-15 23:13:53 +00:00
if (exitflag)
exit(1);
exit(0);
}
/*
* dbwrite: write to database
*
* i) dbop database
*/
void
dbwrite(dbop)
DBOP *dbop;
{
1997-12-15 23:13:53 +00:00
char *p;
char keybuf[MAXKEYLEN+1];
char *c;
1997-12-15 23:13:53 +00:00
signal_setup();
/*
* Input file format:
1997-12-15 23:13:53 +00:00
* +--------------------------------------------------
* |Primary-key secondary-key-1 secondary-key-2 Data\n
* |Primary-key secondary-key-1 secondary-key-2 Data\n
* .
* .
1997-12-15 23:13:53 +00:00
* - Keys and Data are separated by blank('\t' or ' ').
* - Keys cannot include blank.
* - Data can include blank.
1997-12-15 23:13:53 +00:00
* - Null record not allowed.
* - Secondary-key is assumed as a part of data by db(3).
*
* META record:
* You can write meta record by making key start with a ' '.
* You can read this record only by indexed read ('-K' option).
* +------------------
* | __.VERSION 2
*/
while ((p = mgets(stdin, NULL, 0)) != NULL) {
1997-12-15 23:13:53 +00:00
if (exitflag)
break;
c = p;
if (*c == ' ') { /* META record */
if (*++c == ' ')
1997-12-15 23:13:53 +00:00
die("key cannot include blanks.");
}
for (; *c && !isspace(*c); c++) /* skip key part */
;
if (*c == 0)
die("data part not found.");
1997-12-15 23:13:53 +00:00
if (c - p > MAXKEYLEN)
die("primary key too long.");
strncpy(keybuf, p, c - p); /* make key string */
keybuf[c - p] = 0;
for (; *c && isspace(*c); c++) /* skip blanks */
;
if (*c == 0)
die("data part is null.");
1997-12-15 23:13:53 +00:00
entab(p);
dbop_put(dbop, keybuf, p);
}
}
/*
* dbkey: Keyed search
*
* i) dbop database
1997-12-15 23:13:53 +00:00
* i) skey key for search
* i) secondkey 0: primary key, >0: secondary key
*/
void
dbkey(dbop, skey, secondkey)
DBOP *dbop;
char *skey;
1997-12-15 23:13:53 +00:00
int secondkey;
{
1997-12-15 23:13:53 +00:00
char *p;
1997-12-15 23:13:53 +00:00
if (!secondkey) {
for (p = dbop_first(dbop, skey, 0); p; p = dbop_next(dbop))
1997-12-15 23:13:53 +00:00
detab(stdout, p);
return;
}
dbbysecondkey(dbop, F_KEY, skey, secondkey);
}
/*
1997-12-15 23:13:53 +00:00
* dbscan: Scan records
*
* i) dbop database
1997-12-15 23:13:53 +00:00
* i) prefix prefix of primary key
* i) keylist 0: data, 1: key, 2: key and data
*/
void
dbscan(dbop, prefix, keylist)
DBOP *dbop;
1997-12-15 23:13:53 +00:00
char *prefix;
int keylist;
{
1997-12-15 23:13:53 +00:00
char *p;
int flags = 0;
1997-12-15 23:13:53 +00:00
if (prefix)
flags |= DBOP_PREFIX;
1997-12-15 23:13:53 +00:00
if (keylist)
flags |= DBOP_KEY;
1997-12-15 23:13:53 +00:00
for (p = dbop_first(dbop, prefix, flags); p; p = dbop_next(dbop)) {
if (keylist == 2)
fprintf(stdout, "%s %s\n", p, dbop->lastdat);
else
detab(stdout, p);
}
}
/*
* dbdel: Delete records
*
* i) dbop database
1997-12-15 23:13:53 +00:00
* i) skey key for search
* i) secondkey 0: primary key, >0: secondary key
*/
void
dbdel(dbop, skey, secondkey)
DBOP *dbop;
char *skey;
1997-12-15 23:13:53 +00:00
int secondkey;
{
1997-12-15 23:13:53 +00:00
signal_setup();
if (!secondkey) {
dbop_del(dbop, skey);
1997-12-15 23:13:53 +00:00
return;
}
dbbysecondkey(dbop, F_DEL, skey, secondkey);
1997-12-15 23:13:53 +00:00
}
/*
* dbbysecondkey: proc by second key
*
* i) dbop database
1997-12-15 23:13:53 +00:00
* i) func F_KEY, F_DEL
* i) skey
* i) secondkey
*/
void
dbbysecondkey(dbop, func, skey, secondkey)
DBOP *dbop;
1997-12-15 23:13:53 +00:00
int func;
char *skey;
int secondkey;
{
char *c, *p;
int i;
1997-12-15 23:13:53 +00:00
/* trim skey */
for (c = skey; *c && isspace(*c); c++)
;
skey = c;
for (c = skey+strlen(skey)-1; *c && isspace(*c); c--)
*c = 0;
for (p = dbop_first(dbop, NULL, 0); p; p = dbop_next(dbop)) {
1997-12-15 23:13:53 +00:00
if (exitflag)
break;
c = p;
/* reach to specified key */
for (i = secondkey; i; i--) {
for (; *c && !isspace(*c); c++)
;
if (*c == 0)
die("specified key not found.");
for (; *c && isspace(*c); c++)
;
if (*c == 0)
die("specified key not found.");
}
i = strlen(skey);
if (!strncmp(c, skey, i) && (*(c+i) == 0 || isspace(*(c+i)))) {
switch (func) {
case F_KEY:
detab(stdout, p);
break;
case F_DEL:
dbop_del(dbop, NULL);
1997-12-15 23:13:53 +00:00
break;
}
}
if (exitflag)
break;
}
}