aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ndb
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-02-11 19:41:16 +0000
committerrsc <devnull@localhost>2005-02-11 19:41:16 +0000
commitd957951b75df08a9bb0293e3e13ff87759afbb92 (patch)
tree4d7868b0d223956217cbc8819d7afb3bec532cca /src/cmd/ndb
parentad017cfbf5530cfc3ae2fafd723cdade2a4405f6 (diff)
downloadplan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.tar.gz
plan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.tar.bz2
plan9port-d957951b75df08a9bb0293e3e13ff87759afbb92.zip
new
Diffstat (limited to 'src/cmd/ndb')
-rw-r--r--src/cmd/ndb/mkfile13
-rw-r--r--src/cmd/ndb/ndbipquery.c54
-rw-r--r--src/cmd/ndb/ndbmkdb.c203
-rw-r--r--src/cmd/ndb/ndbmkhash.c155
-rw-r--r--src/cmd/ndb/ndbmkhosts.c233
-rw-r--r--src/cmd/ndb/ndbquery.c81
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);
+}