diff options
author | rsc <devnull@localhost> | 2005-02-11 19:41:16 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-02-11 19:41:16 +0000 |
commit | d957951b75df08a9bb0293e3e13ff87759afbb92 (patch) | |
tree | 4d7868b0d223956217cbc8819d7afb3bec532cca /src/cmd/ndb | |
parent | ad017cfbf5530cfc3ae2fafd723cdade2a4405f6 (diff) | |
download | plan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.tar.gz plan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.tar.bz2 plan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.zip |
new
Diffstat (limited to 'src/cmd/ndb')
-rw-r--r-- | src/cmd/ndb/mkfile | 13 | ||||
-rw-r--r-- | src/cmd/ndb/ndbipquery.c | 54 | ||||
-rw-r--r-- | src/cmd/ndb/ndbmkdb.c | 203 | ||||
-rw-r--r-- | src/cmd/ndb/ndbmkhash.c | 155 | ||||
-rw-r--r-- | src/cmd/ndb/ndbmkhosts.c | 233 | ||||
-rw-r--r-- | src/cmd/ndb/ndbquery.c | 81 |
6 files changed, 739 insertions, 0 deletions
diff --git a/src/cmd/ndb/mkfile b/src/cmd/ndb/mkfile new file mode 100644 index 00000000..9bbcfd31 --- /dev/null +++ b/src/cmd/ndb/mkfile @@ -0,0 +1,13 @@ +<$PLAN9/src/mkhdr + +TARG=\ + ndbmkdb\ + ndbquery\ + ndbmkhash\ + ndbmkhosts\ + ndbipquery\ + +LIB=$PLAN9/lib/libndb.a + +<$PLAN9/src/mkmany + diff --git a/src/cmd/ndb/ndbipquery.c b/src/cmd/ndb/ndbipquery.c new file mode 100644 index 00000000..c2859dca --- /dev/null +++ b/src/cmd/ndb/ndbipquery.c @@ -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); +} diff --git a/src/cmd/ndb/ndbmkdb.c b/src/cmd/ndb/ndbmkdb.c new file mode 100644 index 00000000..e19685a6 --- /dev/null +++ b/src/cmd/ndb/ndbmkdb.c @@ -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); +} diff --git a/src/cmd/ndb/ndbmkhash.c b/src/cmd/ndb/ndbmkhash.c new file mode 100644 index 00000000..507bd7c7 --- /dev/null +++ b/src/cmd/ndb/ndbmkhash.c @@ -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); +} diff --git a/src/cmd/ndb/ndbmkhosts.c b/src/cmd/ndb/ndbmkhosts.c new file mode 100644 index 00000000..46f9f978 --- /dev/null +++ b/src/cmd/ndb/ndbmkhosts.c @@ -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); +} diff --git a/src/cmd/ndb/ndbquery.c b/src/cmd/ndb/ndbquery.c new file mode 100644 index 00000000..65bc0472 --- /dev/null +++ b/src/cmd/ndb/ndbquery.c @@ -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); +} |