new
This commit is contained in:
parent
ad017cfbf5
commit
d957951b75
27 changed files with 2521 additions and 0 deletions
13
src/cmd/ndb/mkfile
Normal file
13
src/cmd/ndb/mkfile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=\
|
||||
ndbmkdb\
|
||||
ndbquery\
|
||||
ndbmkhash\
|
||||
ndbmkhosts\
|
||||
ndbipquery\
|
||||
|
||||
LIB=$PLAN9/lib/libndb.a
|
||||
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
54
src/cmd/ndb/ndbipquery.c
Normal file
54
src/cmd/ndb/ndbipquery.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
#include <ip.h>
|
||||
|
||||
/*
|
||||
* search the database for matches
|
||||
*/
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: ipquery attr value rattribute\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
void
|
||||
search(Ndb *db, char *attr, char *val, char **rattr, int nrattr)
|
||||
{
|
||||
Ndbtuple *t;
|
||||
|
||||
t = ndbipinfo(db, attr, val, rattr, nrattr);
|
||||
for(; t; t = t->entry)
|
||||
print("%s=%s ", t->attr, t->val);
|
||||
print("\n");
|
||||
ndbfree(t);
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Ndb *db;
|
||||
char *dbfile = 0;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'f':
|
||||
dbfile = ARGF();
|
||||
break;
|
||||
}ARGEND;
|
||||
|
||||
if(argc < 3)
|
||||
usage();
|
||||
|
||||
db = ndbopen(dbfile);
|
||||
if(db == 0){
|
||||
fprint(2, "no db files\n");
|
||||
exits("no db");
|
||||
}
|
||||
search(db, argv[0], argv[1], argv+2, argc-2);
|
||||
ndbclose(db);
|
||||
|
||||
exits(0);
|
||||
}
|
||||
203
src/cmd/ndb/ndbmkdb.c
Normal file
203
src/cmd/ndb/ndbmkdb.c
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
Biobuf in;
|
||||
Biobuf out;
|
||||
|
||||
enum
|
||||
{
|
||||
Empty,
|
||||
Sys,
|
||||
Dk,
|
||||
Ip,
|
||||
Domain,
|
||||
};
|
||||
|
||||
int
|
||||
iscomment(char *name)
|
||||
{
|
||||
return *name == '#';
|
||||
}
|
||||
|
||||
/*
|
||||
* is this a fully specified datakit name?
|
||||
*/
|
||||
int
|
||||
isdk(char *name)
|
||||
{
|
||||
int slash;
|
||||
|
||||
slash = 0;
|
||||
for(; *name; name++){
|
||||
if(isalnum(*name))
|
||||
continue;
|
||||
if(*name == '/'){
|
||||
slash = 1;
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return slash;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this an internet domain name?
|
||||
*/
|
||||
int
|
||||
isdomain(char *name)
|
||||
{
|
||||
int dot = 0;
|
||||
int alpha = 0;
|
||||
|
||||
for(; *name; name++){
|
||||
if(isalpha(*name) || *name == '-'){
|
||||
alpha = 1;
|
||||
continue;
|
||||
}
|
||||
if(*name == '.'){
|
||||
dot = 1;
|
||||
continue;
|
||||
}
|
||||
if(isdigit(*name))
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
return dot && alpha;
|
||||
}
|
||||
|
||||
/*
|
||||
* is this an ip address?
|
||||
*/
|
||||
int
|
||||
isip(char *name)
|
||||
{
|
||||
int dot = 0;
|
||||
|
||||
for(; *name; name++){
|
||||
if(*name == '.'){
|
||||
dot = 1;
|
||||
continue;
|
||||
}
|
||||
if(isdigit(*name))
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
return dot;
|
||||
}
|
||||
|
||||
char tup[64][64];
|
||||
int ttype[64];
|
||||
int ntup;
|
||||
|
||||
void
|
||||
tprint(void)
|
||||
{
|
||||
int i, tab;
|
||||
char *p;
|
||||
|
||||
tab = 0;
|
||||
for(i = 0; i < ntup; i++){
|
||||
if(ttype[i] == Sys){
|
||||
Bprint(&out, "sys = %s\n", tup[i]);
|
||||
tab = 1;
|
||||
ttype[i] = Empty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < ntup; i++){
|
||||
if(ttype[i] == Empty)
|
||||
continue;
|
||||
if(tab)
|
||||
Bprint(&out, "\t");
|
||||
tab = 1;
|
||||
|
||||
switch(ttype[i]){
|
||||
case Domain:
|
||||
Bprint(&out, "dom=%s\n", tup[i]);
|
||||
break;
|
||||
case Ip:
|
||||
Bprint(&out, "ip=%s\n", tup[i]);
|
||||
break;
|
||||
case Dk:
|
||||
p = strrchr(tup[i], '/');
|
||||
if(p){
|
||||
p++;
|
||||
if((*p == 'C' || *p == 'R')
|
||||
&& strncmp(tup[i], "nj/astro/", p-tup[i]) == 0)
|
||||
Bprint(&out, "flavor=console ");
|
||||
}
|
||||
Bprint(&out, "dk=%s\n", tup[i]);
|
||||
break;
|
||||
case Sys:
|
||||
Bprint(&out, "sys=%s\n", tup[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define NFIELDS 64
|
||||
|
||||
/*
|
||||
* make a database file from a merged uucp/inet database
|
||||
*/
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
int n, i, j;
|
||||
char *l;
|
||||
char *fields[NFIELDS];
|
||||
int ftype[NFIELDS];
|
||||
int same, match;
|
||||
|
||||
Binit(&in, 0, OREAD);
|
||||
Binit(&out, 1, OWRITE);
|
||||
ntup = 0;
|
||||
while(l = Brdline(&in, '\n')){
|
||||
l[Blinelen(&in)-1] = 0;
|
||||
n = getfields(l, fields, NFIELDS, 1, " \t");
|
||||
same = 0;
|
||||
for(i = 0; i < n; i++){
|
||||
if(iscomment(fields[i])){
|
||||
n = i;
|
||||
break;
|
||||
}
|
||||
if(isdomain(fields[i])){
|
||||
ftype[i] = Domain;
|
||||
for(j = 0; j < ntup; j++)
|
||||
if(ttype[j] == Domain && strcmp(fields[i], tup[j]) == 0){
|
||||
same = 1;
|
||||
ftype[i] = Empty;
|
||||
break;
|
||||
}
|
||||
} else if(isip(fields[i]))
|
||||
ftype[i] = Ip;
|
||||
else if(isdk(fields[i]))
|
||||
ftype[i] = Dk;
|
||||
else
|
||||
ftype[i] = Sys;
|
||||
}
|
||||
if(!same && ntup){
|
||||
tprint();
|
||||
ntup = 0;
|
||||
}
|
||||
for(i = 0; i < n; i++){
|
||||
match = 0;
|
||||
for(j = 0; j < ntup; j++){
|
||||
if(ftype[i] == ttype[j] && strcmp(fields[i], tup[j]) == 0){
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!match){
|
||||
ttype[ntup] = ftype[i];
|
||||
strcpy(tup[ntup], fields[i]);
|
||||
ntup++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ntup)
|
||||
tprint();
|
||||
exits(0);
|
||||
}
|
||||
155
src/cmd/ndb/ndbmkhash.c
Normal file
155
src/cmd/ndb/ndbmkhash.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
|
||||
/*
|
||||
* make the hash table completely in memory and then write as a file
|
||||
*/
|
||||
|
||||
uchar *ht;
|
||||
ulong hlen;
|
||||
Ndb *db;
|
||||
ulong nextchain;
|
||||
|
||||
char*
|
||||
syserr(void)
|
||||
{
|
||||
static char buf[ERRMAX];
|
||||
|
||||
errstr(buf, sizeof buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
enter(char *val, ulong dboff)
|
||||
{
|
||||
ulong h;
|
||||
uchar *last;
|
||||
ulong ptr;
|
||||
|
||||
h = ndbhash(val, hlen);
|
||||
h *= NDBPLEN;
|
||||
last = &ht[h];
|
||||
ptr = NDBGETP(last);
|
||||
if(ptr == NDBNAP){
|
||||
NDBPUTP(dboff, last);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ptr & NDBCHAIN){
|
||||
/* walk the chain to the last entry */
|
||||
for(;;){
|
||||
ptr &= ~NDBCHAIN;
|
||||
last = &ht[ptr+NDBPLEN];
|
||||
ptr = NDBGETP(last);
|
||||
if(ptr == NDBNAP){
|
||||
NDBPUTP(dboff, last);
|
||||
return;
|
||||
}
|
||||
if(!(ptr & NDBCHAIN)){
|
||||
NDBPUTP(nextchain|NDBCHAIN, last);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
NDBPUTP(nextchain|NDBCHAIN, last);
|
||||
|
||||
/* add a chained entry */
|
||||
NDBPUTP(ptr, &ht[nextchain]);
|
||||
NDBPUTP(dboff, &ht[nextchain + NDBPLEN]);
|
||||
nextchain += 2*NDBPLEN;
|
||||
}
|
||||
|
||||
uchar nbuf[16*1024];
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Ndbtuple *t, *nt;
|
||||
int n;
|
||||
Dir *d;
|
||||
uchar buf[8];
|
||||
char file[128];
|
||||
int fd;
|
||||
ulong off;
|
||||
uchar *p;
|
||||
|
||||
if(argc != 3){
|
||||
fprint(2, "mkhash: usage file attribute\n");
|
||||
exits("usage");
|
||||
}
|
||||
db = ndbopen(argv[1]);
|
||||
if(db == 0){
|
||||
fprint(2, "mkhash: can't open %s\n", argv[1]);
|
||||
exits(syserr());
|
||||
}
|
||||
|
||||
/* try a bigger than normal buffer */
|
||||
Binits(&db->b, Bfildes(&db->b), OREAD, nbuf, sizeof(nbuf));
|
||||
|
||||
/* count entries to calculate hash size */
|
||||
n = 0;
|
||||
|
||||
while(nt = ndbparse(db)){
|
||||
for(t = nt; t; t = t->entry){
|
||||
if(strcmp(t->attr, argv[2]) == 0)
|
||||
n++;
|
||||
}
|
||||
ndbfree(nt);
|
||||
}
|
||||
|
||||
/* allocate an array large enough for worst case */
|
||||
hlen = 2*n+1;
|
||||
n = hlen*NDBPLEN + hlen*2*NDBPLEN;
|
||||
ht = mallocz(n, 1);
|
||||
if(ht == 0){
|
||||
fprint(2, "mkhash: not enough memory\n");
|
||||
exits(syserr());
|
||||
}
|
||||
for(p = ht; p < &ht[n]; p += NDBPLEN)
|
||||
NDBPUTP(NDBNAP, p);
|
||||
nextchain = hlen*NDBPLEN;
|
||||
|
||||
/* create the in core hash table */
|
||||
Bseek(&db->b, 0, 0);
|
||||
off = 0;
|
||||
while(nt = ndbparse(db)){
|
||||
for(t = nt; t; t = t->entry){
|
||||
if(strcmp(t->attr, argv[2]) == 0)
|
||||
enter(t->val, off);
|
||||
}
|
||||
ndbfree(nt);
|
||||
off = Boffset(&db->b);
|
||||
}
|
||||
|
||||
/* create the hash file */
|
||||
snprint(file, sizeof(file), "%s.%s", argv[1], argv[2]);
|
||||
fd = create(file, ORDWR, 0664);
|
||||
if(fd < 0){
|
||||
fprint(2, "mkhash: can't create %s\n", file);
|
||||
exits(syserr());
|
||||
}
|
||||
NDBPUTUL(db->mtime, buf);
|
||||
NDBPUTUL(hlen, buf+NDBULLEN);
|
||||
if(write(fd, buf, NDBHLEN) != NDBHLEN){
|
||||
fprint(2, "mkhash: writing %s\n", file);
|
||||
exits(syserr());
|
||||
}
|
||||
if(write(fd, ht, nextchain) != nextchain){
|
||||
fprint(2, "mkhash: writing %s\n", file);
|
||||
exits(syserr());
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* make sure file didn't change while we were making the hash */
|
||||
d = dirstat(argv[1]);
|
||||
if(d == nil || d->qid.path != db->qid.path
|
||||
|| d->qid.vers != db->qid.vers){
|
||||
fprint(2, "mkhash: %s changed underfoot\n", argv[1]);
|
||||
remove(file);
|
||||
exits("changed");
|
||||
}
|
||||
|
||||
exits(0);
|
||||
}
|
||||
233
src/cmd/ndb/ndbmkhosts.c
Normal file
233
src/cmd/ndb/ndbmkhosts.c
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
#include <ip.h>
|
||||
|
||||
typedef struct x
|
||||
{
|
||||
Ndbtuple *t;
|
||||
Ndbtuple *it;
|
||||
Ndbtuple *nt;
|
||||
} X;
|
||||
|
||||
X x[4096];
|
||||
int nx;
|
||||
char *domname = "research.att.com";
|
||||
int domnamlen;
|
||||
|
||||
char*
|
||||
upper(char *x)
|
||||
{
|
||||
char *p;
|
||||
int c;
|
||||
|
||||
for(p = x; c = *p; p++)
|
||||
*p = toupper(c);
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
printArecord(int fd, X *p)
|
||||
{
|
||||
Ndbtuple *nt;
|
||||
char *c;
|
||||
char *dom = 0;
|
||||
char *curdom = 0;
|
||||
int i, cdlen = 0;
|
||||
int mxweight = 0;
|
||||
|
||||
if(p->nt) {
|
||||
return;
|
||||
}
|
||||
for(nt=p->t; nt; nt = nt->entry) {
|
||||
/* we are only going to handle things in the specified domain */
|
||||
c = strchr(nt->val, '.');
|
||||
if (c==0 || strcmp(++c, domname)!=0)
|
||||
continue;
|
||||
i = c - nt->val - 1;
|
||||
if(strcmp(nt->attr, "dom") == 0) {
|
||||
curdom = nt->val;
|
||||
cdlen = i;
|
||||
if (dom == 0) {
|
||||
dom = curdom;
|
||||
fprint(fd, "%-.*s%.*s IN A %s\n", i, nt->val, 15-i, " ", p->it->val);
|
||||
} else
|
||||
fprint(fd, "%-.*s%.*s IN CNAME %s.\n", i, nt->val, 15-i, " ", dom);
|
||||
} else if(strcmp(nt->attr, "mx") == 0) {
|
||||
if (curdom != 0)
|
||||
fprint(fd, "%-.*s%.*s MX %d %s.\n", cdlen, curdom, 15-cdlen, " ", mxweight++, nt->val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printentry(int fd, X *p)
|
||||
{
|
||||
Ndbtuple *nt;
|
||||
|
||||
if(p->nt)
|
||||
return;
|
||||
fprint(fd, "%s ", p->it->val);
|
||||
for(nt = p->t; nt; nt = nt->entry)
|
||||
if(strcmp(nt->attr, "dom") == 0)
|
||||
fprint(fd, " %s", nt->val);
|
||||
for(nt = p->t; nt; nt = nt->entry)
|
||||
if(strcmp(nt->attr, "sys") == 0)
|
||||
fprint(fd, " %s", nt->val);
|
||||
fprint(fd, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
printsys(int fd, X *p)
|
||||
{
|
||||
Ndbtuple *nt;
|
||||
|
||||
for(nt = p->t; nt; nt = nt->entry)
|
||||
if(strcmp(nt->attr, "dom") == 0)
|
||||
fprint(fd, "%s\n", nt->val);
|
||||
}
|
||||
|
||||
void
|
||||
printtxt(int fd, X *p)
|
||||
{
|
||||
int i;
|
||||
Ndbtuple *nt;
|
||||
|
||||
if(p->nt){
|
||||
for(;;){
|
||||
i = strlen(p->it->val);
|
||||
if(strcmp(p->it->val+i-2, ".0") == 0)
|
||||
p->it->val[i-2] = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
fprint(fd, "\nNET : %s : %s\n", p->it->val, upper(p->nt->val));
|
||||
return;
|
||||
}
|
||||
fprint(fd, "HOST : %s :", p->it->val);
|
||||
i = 0;
|
||||
for(nt = p->t; nt; nt = nt->entry)
|
||||
if(strcmp(nt->attr, "dom") == 0){
|
||||
if(i++ == 0)
|
||||
fprint(fd, " %s", upper(nt->val));
|
||||
else
|
||||
fprint(fd, ", %s", upper(nt->val));
|
||||
}
|
||||
fprint(fd, "\n");
|
||||
}
|
||||
|
||||
void
|
||||
parse(char *file)
|
||||
{
|
||||
int i;
|
||||
Ndb *db;
|
||||
Ndbtuple *t, *nt, *tt, *ipnett;
|
||||
char *p;
|
||||
|
||||
db = ndbopen(file);
|
||||
if(db == 0)
|
||||
exits("no database");
|
||||
while(t = ndbparse(db)){
|
||||
for(nt = t; nt; nt = nt->entry){
|
||||
if(strcmp(nt->attr, "ip") == 0)
|
||||
break;
|
||||
if(strcmp(nt->attr, "flavor") == 0
|
||||
&& strcmp(nt->val, "console") == 0)
|
||||
return;
|
||||
}
|
||||
if(nt == 0){
|
||||
ndbfree(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* dump anything not on our nets */
|
||||
ipnett = 0;
|
||||
for(tt = t; tt; tt = tt->entry){
|
||||
if(strcmp(tt->attr, "ipnet") == 0){
|
||||
ipnett = tt;
|
||||
break;
|
||||
}
|
||||
if(strcmp(tt->attr, "dom") == 0){
|
||||
i = strlen(tt->val);
|
||||
p = tt->val+i-domnamlen;
|
||||
if(p >= tt->val && strcmp(p, domname) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tt == 0){
|
||||
ndbfree(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(; nt; nt = nt->entry){
|
||||
if(strcmp(nt->attr, "ip") != 0)
|
||||
continue;
|
||||
x[nx].it = nt;
|
||||
x[nx].nt = ipnett;
|
||||
x[nx++].t = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, fd;
|
||||
char fn[128];
|
||||
|
||||
if (argc>1)
|
||||
domname = argv[1];
|
||||
domnamlen = strlen(domname);
|
||||
if(argc > 2){
|
||||
for(i = 2; i < argc; i++)
|
||||
parse(argv[i]);
|
||||
} else {
|
||||
parse(unsharp("#9/ndb/local"));
|
||||
parse(unsharp("#9/ndb/friends"));
|
||||
}
|
||||
|
||||
// sprint(fn, "/lib/ndb/hosts.%-.21s", domname);
|
||||
// fd = create(fn, OWRITE, 0664);
|
||||
// if(fd < 0){
|
||||
// fprint(2, "can't create %s: %r\n", fn);
|
||||
// exits("boom");
|
||||
// }
|
||||
// for(i = 0; i < nx; i++)
|
||||
// printentry(fd, &x[i]);
|
||||
// close(fd);
|
||||
//
|
||||
|
||||
sprint(fn, "/lib/ndb/db.%-.24s", domname);
|
||||
fd = create(fn, OWRITE, 0664);
|
||||
if(fd < 0){
|
||||
fprint(2, "can't create %s: %r\n", fn);
|
||||
exits("boom");
|
||||
}
|
||||
fprint(fd, "; This file is generated automatically, do not edit!\n");
|
||||
for(i = 0; i < nx; i++)
|
||||
printArecord(fd, &x[i]);
|
||||
close(fd);
|
||||
|
||||
sprint(fn, "/lib/ndb/equiv.%-.21s", domname);
|
||||
fd = create(fn, OWRITE, 0664);
|
||||
if(fd < 0){
|
||||
fprint(2, "can't create %s: %r\n", fn);
|
||||
exits("boom");
|
||||
}
|
||||
for(i = 0; i < nx; i++)
|
||||
printsys(fd, &x[i]);
|
||||
close(fd);
|
||||
|
||||
sprint(fn, "/lib/ndb/txt.%-.23s", domname);
|
||||
fd = create(fn, OWRITE, 0664);
|
||||
if(fd < 0){
|
||||
fprint(2, "can't create %s: %r\n", fn);
|
||||
exits("boom");
|
||||
}
|
||||
for(i = 0; i < nx; i++)
|
||||
printtxt(fd, &x[i]);
|
||||
close(fd);
|
||||
|
||||
exits(0);
|
||||
}
|
||||
81
src/cmd/ndb/ndbquery.c
Normal file
81
src/cmd/ndb/ndbquery.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
|
||||
/*
|
||||
* search the database for matches
|
||||
*/
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: query attr value [returned attribute]\n");
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
void
|
||||
search(Ndb *db, char *attr, char *val, char *rattr)
|
||||
{
|
||||
Ndbs s;
|
||||
Ndbtuple *t;
|
||||
Ndbtuple *nt;
|
||||
char *p;
|
||||
|
||||
if(rattr){
|
||||
p = ndbgetvalue(db, &s, attr, val, rattr, nil);
|
||||
if(p){
|
||||
print("%s\n", p);
|
||||
free(p);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
t = ndbsearch(db, &s, attr, val);
|
||||
while(t){
|
||||
for(nt = t; nt; nt = nt->entry)
|
||||
print("%s=%s ", nt->attr, nt->val);
|
||||
print("\n");
|
||||
ndbfree(t);
|
||||
t = ndbsnext(&s, attr, val);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *rattr = 0;
|
||||
Ndb *db;
|
||||
char *dbfile = 0;
|
||||
int reps = 1;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'f':
|
||||
dbfile = ARGF();
|
||||
break;
|
||||
}ARGEND;
|
||||
|
||||
switch(argc){
|
||||
case 4:
|
||||
reps = atoi(argv[3]);
|
||||
/* fall through */
|
||||
case 3:
|
||||
rattr = argv[2];
|
||||
break;
|
||||
case 2:
|
||||
rattr = 0;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
db = ndbopen(dbfile);
|
||||
if(db == 0){
|
||||
fprint(2, "no db files\n");
|
||||
exits("no db");
|
||||
}
|
||||
while(reps--)
|
||||
search(db, argv[0], argv[1], rattr);
|
||||
ndbclose(db);
|
||||
|
||||
exits(0);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue