252 lines
4.3 KiB
C
252 lines
4.3 KiB
C
|
#include <stdio.h>
|
||
|
#include <sys/file.h>
|
||
|
#ifdef SDBM
|
||
|
#include "EXTERN.h"
|
||
|
#include "sdbm.h"
|
||
|
#else
|
||
|
#include <ndbm.h>
|
||
|
#endif
|
||
|
#include <string.h>
|
||
|
|
||
|
#ifdef BSD42
|
||
|
#define strchr index
|
||
|
#endif
|
||
|
|
||
|
extern int getopt();
|
||
|
extern char *strchr();
|
||
|
extern void oops();
|
||
|
|
||
|
char *progname;
|
||
|
|
||
|
static int rflag;
|
||
|
static char *usage = "%s [-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, O_RDONLY,
|
||
|
"get", DLOOK, O_RDONLY,
|
||
|
"look", DLOOK, O_RDONLY,
|
||
|
"add", DINSERT, O_RDWR,
|
||
|
"insert", DINSERT, O_RDWR,
|
||
|
"store", DINSERT, O_RDWR,
|
||
|
"delete", DDELETE, O_RDWR,
|
||
|
"remove", DDELETE, O_RDWR,
|
||
|
"dump", DCAT, O_RDONLY,
|
||
|
"list", DCAT, O_RDONLY,
|
||
|
"cat", DCAT, O_RDONLY,
|
||
|
"creat", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
|
||
|
"new", DCREAT, O_RDWR | O_CREAT | O_TRUNC,
|
||
|
"build", DBUILD, O_RDWR | O_CREAT,
|
||
|
"squash", DPRESS, O_RDWR,
|
||
|
"compact", DPRESS, O_RDWR,
|
||
|
"compress", DPRESS, O_RDWR
|
||
|
};
|
||
|
|
||
|
#define CTABSIZ (sizeof (cmds)/sizeof (cmd))
|
||
|
|
||
|
static cmd *parse();
|
||
|
static void badk(), doit(), prdatum();
|
||
|
|
||
|
int
|
||
|
main(argc, argv)
|
||
|
int argc;
|
||
|
char *argv[];
|
||
|
{
|
||
|
int c;
|
||
|
register cmd *act;
|
||
|
extern int optind;
|
||
|
extern char *optarg;
|
||
|
|
||
|
progname = argv[0];
|
||
|
|
||
|
while ((c = getopt(argc, argv, "R")) != EOF)
|
||
|
switch (c) {
|
||
|
case 'R': /* raw processing */
|
||
|
rflag++;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
oops("usage: %s", usage);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((argc -= optind) < 2)
|
||
|
oops("usage: %s", usage);
|
||
|
|
||
|
if ((act = parse(argv[optind])) == NULL)
|
||
|
badk(argv[optind]);
|
||
|
optind++;
|
||
|
doit(act, argv[optind]);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
doit(act, file)
|
||
|
register 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();
|
||
|
#endif
|
||
|
|
||
|
if ((db = dbm_open(file, act->flags, 0644)) == NULL)
|
||
|
oops("cannot open: %s", file);
|
||
|
|
||
|
if ((line = (char *) malloc(LINEMAX)) == NULL)
|
||
|
oops("%s: cannot get memory", "line alloc");
|
||
|
|
||
|
switch (act->scode) {
|
||
|
|
||
|
case DLOOK:
|
||
|
while (fgets(line, LINEMAX, stdin) != NULL) {
|
||
|
n = strlen(line) - 1;
|
||
|
line[n] = 0;
|
||
|
key.dptr = line;
|
||
|
key.dsize = n;
|
||
|
val = dbm_fetch(db, key);
|
||
|
if (val.dptr != NULL) {
|
||
|
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) != NULL) {
|
||
|
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) != NULL) {
|
||
|
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(word)
|
||
|
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");
|
||
|
exit(1);
|
||
|
/*NOTREACHED*/
|
||
|
}
|
||
|
|
||
|
static cmd *
|
||
|
parse(str)
|
||
|
register char *str;
|
||
|
{
|
||
|
register int i = CTABSIZ;
|
||
|
register cmd *p;
|
||
|
|
||
|
for (p = cmds; i--; p++)
|
||
|
if (strcmp(p->sname, str) == 0)
|
||
|
return p;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
prdatum(stream, d)
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|