shithub: sdbm

ref: 64e312636599ea2c86f21dc1176dca7da77bd74a
dir: /dbu.c/

View raw version
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include "sdbm.h"

extern void	oops(char *, char *);
extern char getopt(int, char *[], char *);


char *progname;

static int rflag;
static char *usage = "[-R] cat | look |... dbmname";

#define DERROR	0
#define DLOOK	1
#define DINSERT	2
#define DDELETE 3
#define	DCAT	4
#define DBUILD	5
#define DPRESS	6
#define DCREAT	7

#define LINEMAX	8192

typedef struct {
	char *sname;
	int scode;
	int flags;
} cmd;

static cmd cmds[] = {

	"fetch", DLOOK, 	OREAD,
	"get", DLOOK,		OREAD,
	"look", DLOOK,		OREAD,
	"add", DINSERT,		ORDWR,
	"insert", DINSERT,	ORDWR,
	"store", DINSERT,	ORDWR,
	"delete", DDELETE,	ORDWR,
	"remove", DDELETE,	ORDWR,
	"dump", DCAT,		OREAD,
	"list", DCAT, 		OREAD,
	"cat", DCAT,		OREAD,
	"creat", DCREAT,	ORDWR | OTRUNC, 
	"new", DCREAT,		ORDWR | OTRUNC,
	"build", DBUILD,	ORDWR,
	"squash", DPRESS,	ORDWR,
	"compact", DPRESS,	ORDWR,
	"compress", DPRESS,	ORDWR
};

#define CTABSIZ (sizeof (cmds)/sizeof (cmd))

static cmd *parse(char *);
static void badk(char *), doit(cmd *, char *), prdatum(FILE *, datum);

int
main(int argc, char *argv[])
{
 	cmd *act;
	
	progname = argv[0];

	ARGBEGIN {
	case 'R':
		rflag++;
		break;

	default:
		oops("usage %s", usage);
		break;
	} ARGEND

	if (argc < 2) oops("usage %s", usage);
	
	if ((act = parse(argv[0])) == nil) badk(argv[0]);

	doit(act, argv[1]);
 	exits(0);
}

static void
doit(cmd *act, char* file)
{
	datum key;
	datum val;
	register DBM *db;
	register char *op;
	register int n;
	char *line;
#ifdef TIME
	long start;
	extern long time(long *);
#endif
	int dbcreate;
	Dir *dstat;

	if ((dstat = dirstat(file)) == nil)
		dbcreate = 1;
	else {
		dbcreate = 0;
		free(dstat);
	}

	if ((db = dbm_open(file, act->flags, 0644, dbcreate)) == nil)
		oops("cannot open: %s", file);

	if ((line = (char *) malloc(LINEMAX)) == nil)
		oops("%s: cannot get memory", "line alloc");

	switch (act->scode) {

	case DLOOK:
		while (fgets(line, LINEMAX, stdin) != nil) {
			n = strlen(line) - 1;
			line[n] = 0;
			key.dptr = line;
			key.dsize = n;
			val = dbm_fetch(db, key);
			if (val.dptr != nil) {
				prdatum(stdout, val);
				putchar('\n');
				continue;
			}
			prdatum(stderr, key);
			fprintf(stderr, ": not found.\n");
		}
		break;
	case DINSERT:
		break;
	case DDELETE:
		while (fgets(line, LINEMAX, stdin) != nil) {
			n = strlen(line) - 1;
			line[n] = 0;
			key.dptr = line;
			key.dsize = n;
			if (dbm_delete(db, key) == -1) {
				prdatum(stderr, key);
				fprintf(stderr, ": not found.\n");
			}
		}
		break;
	case DCAT:
		for (key = dbm_firstkey(db); key.dptr != 0; 
		     key = dbm_nextkey(db)) {
			prdatum(stdout, key);
			putchar('\t');
			prdatum(stdout, dbm_fetch(db, key));
			putchar('\n');
		}
		break;
	case DBUILD:
#ifdef TIME
		start = time(0);
#endif
		while (fgets(line, LINEMAX, stdin) != nil) {
			n = strlen(line) - 1;
			line[n] = 0;
			key.dptr = line;
			if ((op = strchr(line, '\t')) != 0) {
				key.dsize = op - line;
				*op++ = 0;
				val.dptr = op;
				val.dsize = line + n - op;
			}
			else
				oops("bad input; %s", line);
	
			if (dbm_store(db, key, val, DBM_REPLACE) < 0) {
				prdatum(stderr, key);
				fprintf(stderr, ": ");
				oops("store: %s", "failed");
			}
		}
#ifdef TIME
		printf("done: %d seconds.\n", time(0) - start);
#endif
		break;
	case DPRESS:
		break;
	case DCREAT:
		break;
	}

	dbm_close(db);
}

static void
badk(char *word)
{
	register int i;

	if (progname)
		fprintf(stderr, "%s: ", progname);
	fprintf(stderr, "bad keywd %s. use one of\n", word);
	for (i = 0; i < (int)CTABSIZ; i++)
		fprintf(stderr, "%-8s%c", cmds[i].sname,
			((i + 1) % 6 == 0) ? '\n' : ' ');
	fprintf(stderr, "\n");
	exits("bad keyword");
	/*NOTREACHED*/
}

static cmd *
parse(char *str)
{
	register int i = CTABSIZ;
	register cmd *p;
	
	for (p = cmds; i--; p++)
		if (strcmp(p->sname, str) == 0)
			return p;
	return nil;
}

static void
prdatum(FILE *stream, datum d)
{
	register int c;
	register char *p = d.dptr;
	register int n = d.dsize;

	while (n--) {
		c = *p++ & 0377;
		if (c & 0200) {
			fprintf(stream, "M-");
			c &= 0177;
		}
		if (c == 0177 || c < ' ') 
			fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
		else
			putc(c, stream);
	}
}