Browse Source

Plan 9 from Bell Labs 2004-03-07

David du Colombier 20 years ago
parent
commit
5663412370

+ 19 - 14
dist/replica/plan9.db

@@ -543,7 +543,7 @@
 386/lib/libmemdraw.a - 664 sys sys 1073851273 291288
 386/lib/libmemdraw.a - 664 sys sys 1073851273 291288
 386/lib/libmemlayer.a - 664 sys sys 1073851273 47636
 386/lib/libmemlayer.a - 664 sys sys 1073851273 47636
 386/lib/libmp.a - 664 sys sys 1077940925 77700
 386/lib/libmp.a - 664 sys sys 1077940925 77700
-386/lib/libndb.a - 664 sys sys 1077636970 54474
+386/lib/libndb.a - 664 sys sys 1078626124 61198
 386/lib/libplumb.a - 664 sys sys 1073851274 18876
 386/lib/libplumb.a - 664 sys sys 1073851274 18876
 386/lib/libregexp.a - 664 sys sys 1073851274 37502
 386/lib/libregexp.a - 664 sys sys 1073851274 37502
 386/lib/libscribble.a - 664 sys sys 1073851274 107542
 386/lib/libscribble.a - 664 sys sys 1073851274 107542
@@ -3413,7 +3413,7 @@ sys/include/memdraw.h - 664 sys sys 1039752978 5616
 sys/include/memlayer.h - 664 sys sys 1051031022 1851
 sys/include/memlayer.h - 664 sys sys 1051031022 1851
 sys/include/mouse.h - 664 sys sys 1035232010 1003
 sys/include/mouse.h - 664 sys sys 1035232010 1003
 sys/include/mp.h - 664 sys sys 1014929065 4610
 sys/include/mp.h - 664 sys sys 1014929065 4610
-sys/include/ndb.h - 664 sys sys 1077632684 4009
+sys/include/ndb.h - 664 sys sys 1078618596 4334
 sys/include/nfs3.h - 664 sys sys 1045589438 15082
 sys/include/nfs3.h - 664 sys sys 1045589438 15082
 sys/include/plumb.h - 664 sys sys 1014929065 989
 sys/include/plumb.h - 664 sys sys 1014929065 989
 sys/include/pool.h - 664 sys sys 1032058257 1156
 sys/include/pool.h - 664 sys sys 1032058257 1156
@@ -4835,7 +4835,7 @@ sys/man/2/mouse - 664 sys sys 971455512 4966
 sys/man/2/mp - 664 sys sys 1071238964 10690
 sys/man/2/mp - 664 sys sys 1071238964 10690
 sys/man/2/muldiv - 664 sys sys 984709633 639
 sys/man/2/muldiv - 664 sys sys 984709633 639
 sys/man/2/nan - 664 sys sys 975084242 937
 sys/man/2/nan - 664 sys sys 975084242 937
-sys/man/2/ndb - 664 sys sys 1077632681 8901
+sys/man/2/ndb - 664 sys sys 1078625843 9479
 sys/man/2/notify - 664 sys sys 1032058674 6376
 sys/man/2/notify - 664 sys sys 1032058674 6376
 sys/man/2/object - 664 sys sys 944959695 3864
 sys/man/2/object - 664 sys sys 944959695 3864
 sys/man/2/open - 664 sys sys 1015091524 3404
 sys/man/2/open - 664 sys sys 1015091524 3404
@@ -5468,7 +5468,7 @@ sys/src/9/port/portdat.h - 664 sys sys 1073324006 22707
 sys/src/9/port/portfns.h - 664 sys sys 1068215525 11376
 sys/src/9/port/portfns.h - 664 sys sys 1068215525 11376
 sys/src/9/port/portmkfile - 664 sys sys 1067722766 2098
 sys/src/9/port/portmkfile - 664 sys sys 1067722766 2098
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
 sys/src/9/port/print.c - 664 sys sys 1014931178 227
-sys/src/9/port/proc.c - 664 sys sys 1071247309 28305
+sys/src/9/port/proc.c - 664 sys sys 1078550254 28021
 sys/src/9/port/qio.c - 664 sys sys 1070287837 23562
 sys/src/9/port/qio.c - 664 sys sys 1070287837 23562
 sys/src/9/port/qlock.c - 664 sys sys 1067722765 3196
 sys/src/9/port/qlock.c - 664 sys sys 1067722765 3196
 sys/src/9/port/rdb.c - 664 sys sys 1018721202 1698
 sys/src/9/port/rdb.c - 664 sys sys 1018721202 1698
@@ -9735,7 +9735,7 @@ sys/src/cmd/mv.c - 664 sys sys 1014926695 4276
 sys/src/cmd/ndb - 20000000775 sys sys 988249988 0
 sys/src/cmd/ndb - 20000000775 sys sys 988249988 0
 sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1060612175 6862
 sys/src/cmd/ndb/convDNS2M.c - 664 sys sys 1060612175 6862
 sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1060612175 7248
 sys/src/cmd/ndb/convM2DNS.c - 664 sys sys 1060612175 7248
-sys/src/cmd/ndb/cs.c - 664 sys sys 1069206443 32930
+sys/src/cmd/ndb/cs.c - 664 sys sys 1078631715 33161
 sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 1051
 sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 1051
 sys/src/cmd/ndb/csquery.c - 664 sys sys 1014926159 1062
 sys/src/cmd/ndb/csquery.c - 664 sys sys 1014926159 1062
 sys/src/cmd/ndb/dblookup.c - 664 sys sys 1060612175 17896
 sys/src/cmd/ndb/dblookup.c - 664 sys sys 1060612175 17896
@@ -12110,22 +12110,27 @@ sys/src/libmp/power/mpvecsub.s - 664 sys sys 950104732 1118
 sys/src/libmp/power/placeholder.c - 664 sys sys 944961747 0
 sys/src/libmp/power/placeholder.c - 664 sys sys 944961747 0
 sys/src/libmp/test.c - 664 sys sys 964798440 12260
 sys/src/libmp/test.c - 664 sys sys 964798440 12260
 sys/src/libndb - 20000000775 sys sys 1015013466 0
 sys/src/libndb - 20000000775 sys sys 1015013466 0
-sys/src/libndb/csgetval.c - 664 sys sys 1069206439 1322
+sys/src/libndb/csgetval.c - 664 sys sys 1078626122 1600
 sys/src/libndb/csipinfo.c - 664 sys sys 1069206439 1175
 sys/src/libndb/csipinfo.c - 664 sys sys 1069206439 1175
-sys/src/libndb/dnsquery.c - 664 sys sys 1069206439 2799
+sys/src/libndb/dnsquery.c - 664 sys sys 1078618597 2840
 sys/src/libndb/ipattr.c - 664 sys sys 953844690 586
 sys/src/libndb/ipattr.c - 664 sys sys 953844690 586
-sys/src/libndb/mkfile - 664 sys sys 1035389780 424
-sys/src/libndb/ndbaux.c - 664 sys sys 1069206440 1600
-sys/src/libndb/ndbcache.c - 664 sys sys 1024156984 2227
+sys/src/libndb/mkfile - 664 sys sys 1078618596 513
+sys/src/libndb/ndbaux.c - 664 sys sys 1078618597 1518
+sys/src/libndb/ndbcache.c - 664 sys sys 1078618597 2164
 sys/src/libndb/ndbcat.c - 664 sys sys 950311789 224
 sys/src/libndb/ndbcat.c - 664 sys sys 950311789 224
-sys/src/libndb/ndbfree.c - 664 sys sys 944961749 233
-sys/src/libndb/ndbgetval.c - 664 sys sys 944961749 811
+sys/src/libndb/ndbconcatenate.c - 664 sys sys 1078618598 259
+sys/src/libndb/ndbdiscard.c - 664 sys sys 1078618598 436
+sys/src/libndb/ndbfree.c - 664 sys sys 1078618598 952
+sys/src/libndb/ndbgetipaddr.c - 664 sys sys 1078618598 813
+sys/src/libndb/ndbgetval.c - 664 sys sys 1078626122 1160
 sys/src/libndb/ndbhash.c - 664 sys sys 1069206440 4973
 sys/src/libndb/ndbhash.c - 664 sys sys 1069206440 4973
 sys/src/libndb/ndbhf.h - 664 sys sys 1015013485 746
 sys/src/libndb/ndbhf.h - 664 sys sys 1015013485 746
-sys/src/libndb/ndbipinfo.c - 664 sys sys 1063853776 6483
-sys/src/libndb/ndblookval.c - 664 sys sys 944961750 655
+sys/src/libndb/ndbipinfo.c - 664 sys sys 1078618599 4640
+sys/src/libndb/ndblookval.c - 664 sys sys 1078626123 981
 sys/src/libndb/ndbopen.c - 664 sys sys 1069206441 2716
 sys/src/libndb/ndbopen.c - 664 sys sys 1069206441 2716
 sys/src/libndb/ndbparse.c - 664 sys sys 1069206440 1167
 sys/src/libndb/ndbparse.c - 664 sys sys 1069206440 1167
+sys/src/libndb/ndbreorder.c - 664 sys sys 1078618600 966
+sys/src/libndb/ndbsubstitute.c - 664 sys sys 1078618600 692
 sys/src/libplumb - 20000000775 sys sys 1014928082 0
 sys/src/libplumb - 20000000775 sys sys 1014928082 0
 sys/src/libplumb/event.c - 664 sys sys 947358887 1861
 sys/src/libplumb/event.c - 664 sys sys 947358887 1861
 sys/src/libplumb/mesg.c - 644 sys sys 1014928082 6718
 sys/src/libplumb/mesg.c - 644 sys sys 1014928082 6718

+ 26 - 0
dist/replica/plan9.log

@@ -14029,3 +14029,29 @@
 1078497028 4 c mips/include/ape/math.h - 664 sys sys 1078495287 2176
 1078497028 4 c mips/include/ape/math.h - 664 sys sys 1078495287 2176
 1078497028 5 c power/include/ape/math.h - 664 sys sys 1078495287 2176
 1078497028 5 c power/include/ape/math.h - 664 sys sys 1078495287 2176
 1078497028 6 c sparc/include/ape/math.h - 664 sys sys 1078495288 2176
 1078497028 6 c sparc/include/ape/math.h - 664 sys sys 1078495288 2176
+1078551037 0 c sys/src/9/port/proc.c - 664 sys sys 1078550254 28021
+1078583444 0 c sys/src/cmd/ndb/cs.c - 664 sys sys 1078582417 33093
+1078619438 0 c 386/lib/libndb.a - 664 sys sys 1078618600 59934
+1078619438 1 c sys/include/ndb.h - 664 sys sys 1078618596 4334
+1078619438 2 c sys/src/libndb/csgetval.c - 664 sys sys 1078618596 1514
+1078619438 3 c sys/src/libndb/dnsquery.c - 664 sys sys 1078618597 2840
+1078619438 4 c sys/src/libndb/mkfile - 664 sys sys 1078618596 513
+1078619438 5 c sys/src/libndb/ndbaux.c - 664 sys sys 1078618597 1518
+1078619438 6 c sys/src/libndb/ndbcache.c - 664 sys sys 1078618597 2164
+1078619438 7 a sys/src/libndb/ndbconcatenate.c - 664 sys sys 1078618598 259
+1078619438 8 a sys/src/libndb/ndbdiscard.c - 664 sys sys 1078618598 436
+1078619438 9 c sys/src/libndb/ndbfree.c - 664 sys sys 1078618598 952
+1078619438 10 a sys/src/libndb/ndbgetipaddr.c - 664 sys sys 1078618598 813
+1078619438 11 c sys/src/libndb/ndbgetval.c - 664 sys sys 1078618599 984
+1078619438 12 c sys/src/libndb/ndbipinfo.c - 664 sys sys 1078618599 4640
+1078619438 13 c sys/src/libndb/ndblookval.c - 664 sys sys 1078618599 815
+1078619438 14 a sys/src/libndb/ndbreorder.c - 664 sys sys 1078618600 966
+1078619438 15 a sys/src/libndb/ndbsubstitute.c - 664 sys sys 1078618600 692
+1078621239 0 c sys/man/2/ndb - 664 sys sys 1078620018 9313
+1078621239 1 c sys/src/cmd/ndb/cs.c - 664 sys sys 1078620182 33161
+1078626641 0 c 386/lib/libndb.a - 664 sys sys 1078626124 61198
+1078626641 1 c sys/man/2/ndb - 664 sys sys 1078625843 9479
+1078626641 2 c sys/src/libndb/csgetval.c - 664 sys sys 1078626122 1600
+1078626641 3 c sys/src/libndb/ndbgetval.c - 664 sys sys 1078626122 1160
+1078626641 4 c sys/src/libndb/ndblookval.c - 664 sys sys 1078626123 981
+1078632040 0 c sys/src/cmd/ndb/cs.c - 664 sys sys 1078631715 33161

+ 11 - 5
sys/include/ndb.h

@@ -43,11 +43,12 @@ struct Ndb
  */
  */
 struct Ndbtuple
 struct Ndbtuple
 {
 {
-	char		attr[Ndbalen];	/* attribute name */
-	char		val[Ndbvlen];	/* value(s) */
-	Ndbtuple	*entry;		/* next tuple in this entry */
-	Ndbtuple	*line;		/* next tuple on this line */
-	ulong		ptr;		/* (for the application - starts 0) */
+	char		attr[Ndbalen];		/* attribute name */
+	char		*val;			/* value(s) */
+	Ndbtuple	*entry;			/* next tuple in this entry */
+	Ndbtuple	*line;			/* next tuple on this line */
+	ulong		ptr;			/* (for the application - starts 0) */
+	char		valbuf[Ndbvlen];	/* initial allocation for value */
 };
 };
 
 
 /*
 /*
@@ -121,6 +122,7 @@ struct Ndbs
 #define NDB_IPlen 16
 #define NDB_IPlen 16
 
 
 Ndbtuple*	csgetval(char*, char*, char*, char*, char*);
 Ndbtuple*	csgetval(char*, char*, char*, char*, char*);
+Ndbtuple*	csgetvalue(char*, char*, char*, char*, char*, int);
 Ndbtuple*	csipinfo(char*, char*, char*, char**, int);
 Ndbtuple*	csipinfo(char*, char*, char*, char**, int);
 Ndbtuple*	dnsquery(char*, char*, char*);
 Ndbtuple*	dnsquery(char*, char*, char*);
 char*		ipattr(char*);
 char*		ipattr(char*);
@@ -132,14 +134,18 @@ Ndbtuple*	ndbdiscard(Ndbtuple*, Ndbtuple*);
 void		ndbfree(Ndbtuple*);
 void		ndbfree(Ndbtuple*);
 Ndbtuple*	ndbgetipaddr(Ndb*, char*);
 Ndbtuple*	ndbgetipaddr(Ndb*, char*);
 Ndbtuple*	ndbgetval(Ndb*, Ndbs*, char*, char*, char*, char*);
 Ndbtuple*	ndbgetval(Ndb*, Ndbs*, char*, char*, char*, char*);
+Ndbtuple*	ndbgetvalue(Ndb*, Ndbs*, char*, char*, char*, char*, int);
 ulong		ndbhash(char*, int);
 ulong		ndbhash(char*, int);
 Ndbtuple*	ndbipinfo(Ndb*, char*, char*, char**, int);
 Ndbtuple*	ndbipinfo(Ndb*, char*, char*, char**, int);
 Ndbtuple*	ndblookval(Ndbtuple*, Ndbtuple*, char*, char*);
 Ndbtuple*	ndblookval(Ndbtuple*, Ndbtuple*, char*, char*);
+Ndbtuple*	ndblookvalue(Ndbtuple*, Ndbtuple*, char*, char*, int);
+Ndbtuple*	ndbnew(char*, char*);
 Ndb*		ndbopen(char*);
 Ndb*		ndbopen(char*);
 Ndbtuple*	ndbparse(Ndb*);
 Ndbtuple*	ndbparse(Ndb*);
 int		ndbreopen(Ndb*);
 int		ndbreopen(Ndb*);
 Ndbtuple*	ndbreorder(Ndbtuple*, Ndbtuple*);
 Ndbtuple*	ndbreorder(Ndbtuple*, Ndbtuple*);
 Ndbtuple*	ndbsearch(Ndb*, Ndbs*, char*, char*);
 Ndbtuple*	ndbsearch(Ndb*, Ndbs*, char*, char*);
 long		ndbseek(Ndb*, long);
 long		ndbseek(Ndb*, long);
+void		ndbsetval(Ndbtuple*, char*, int);
 Ndbtuple*	ndbsnext(Ndbs*, char*, char*);
 Ndbtuple*	ndbsnext(Ndbs*, char*, char*);
 Ndbtuple*	ndbsubstitute(Ndbtuple*, Ndbtuple*, Ndbtuple*);
 Ndbtuple*	ndbsubstitute(Ndbtuple*, Ndbtuple*, Ndbtuple*);

+ 44 - 16
sys/man/2/ndb

@@ -1,6 +1,6 @@
 .TH NDB 2
 .TH NDB 2
 .SH NAME
 .SH NAME
-ndbopen, ndbcat, ndbchanged, ndbclose, ndbreopen, ndbsearch, ndbsnext, ndbgetval, ndbfree, ipattr, ndbgetipaddr, ndbipinfo, csipinfo, ndbhash, ndbparse, csgetval, ndblookval, dnsquery, ndbdiscard, ndbconcatenate, ndbreorder, ndbsubstitute \- network database
+ndbopen, ndbcat, ndbchanged, ndbclose, ndbreopen, ndbsearch, ndbsnext, ndbgetvalue, ndbfree, ipattr, ndbgetipaddr, ndbipinfo, csipinfo, ndbhash, ndbparse, csgetvalue, ndblookvalue, dnsquery, ndbdiscard, ndbconcatenate, ndbreorder, ndbsubstitute, ndbgetval, csgetval, ndblookval \- network database
 .SH SYNOPSIS
 .SH SYNOPSIS
 .B #include <u.h>
 .B #include <u.h>
 .br
 .br
@@ -33,13 +33,14 @@ Ndbtuple*	ndbsearch(Ndb *db, Ndbs *s, char *attr, char *val)
 Ndbtuple*	ndbsnext(Ndbs *s, char *attr, char *val)
 Ndbtuple*	ndbsnext(Ndbs *s, char *attr, char *val)
 .PP
 .PP
 .B
 .B
-Ndbtuple*	ndbgetval(Ndb *db, Ndbs *s, char *attr, char *val,
+Ndbtuple*	ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val,
 .br
 .br
 .B
 .B
-		char *rattr, char *buf)
+		char *rattr, char *buf, int buflen)
 .PP
 .PP
 .B
 .B
-Ndbtuple*	csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
+Ndbtuple*	csgetvalue(char *netroot, char *attr, char *val, char *rattr,
+		char *buf, int buflen)
 .PP
 .PP
 .B
 .B
 char*	ipattr(char *name)
 char*	ipattr(char *name)
@@ -67,7 +68,8 @@ Ndbtuple*	ndbparse(Ndb *db)
 Ndbtuple*	dnsquery(char *netroot, char *domainname, char *type)
 Ndbtuple*	dnsquery(char *netroot, char *domainname, char *type)
 .PP
 .PP
 .B
 .B
-Ndbtuple*	ndblookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
+Ndbtuple*	ndblookvalue(Ndbtuple *entry, Ndbtuple *line, char *attr,
+		char *to, int tolen)
 .PP
 .PP
 .B
 .B
 void	ndbfree(Ndbtuple *db)
 void	ndbfree(Ndbtuple *db)
@@ -136,10 +138,11 @@ On failure they return zero.
 typedef struct Ndbtuple Ndbtuple;
 typedef struct Ndbtuple Ndbtuple;
 struct Ndbtuple {
 struct Ndbtuple {
         char      attr[Ndbalen];
         char      attr[Ndbalen];
-        char      val[Ndbvlen];
+        char      *val;
         Ndbtuple  *entry;
         Ndbtuple  *entry;
         Ndbtuple  *line;
         Ndbtuple  *line;
         ulong     ptr;    /* for the application; starts 0 */
         ulong     ptr;    /* for the application; starts 0 */
+        char      valbuf[Ndbvlen];  /* initial allocation for val */
 };
 };
 .EE
 .EE
 .LP
 .LP
@@ -186,23 +189,21 @@ field points to the pair within the entry matched by the
 or
 or
 .IR ndbsnext .
 .IR ndbsnext .
 .PP
 .PP
-.I Ndbgetval
+.I Ndbgetvalue
 searches the database for an entry containing not only an
 searches the database for an entry containing not only an
 attribute/value pair,
 attribute/value pair,
 .IR attr = val ,
 .IR attr = val ,
 but also a pair with the attribute
 but also a pair with the attribute
 .IR rattr .
 .IR rattr .
-If successful, it copies the value associated with
+If successful, it copies up to
+.I buflen
+bytes of the value associated with
 .I rattr
 .I rattr
 into
 into
 .IR buf .
 .IR buf .
-.I Buf
-must point to an area at least
-.I Ndbvlen
-long.
-.I Csgetval
+.I Csgetvalue
 is like
 is like
-.I ndbgetval
+.I ndbgetvalue
 but queries the connection server
 but queries the connection server
 instead of looking directly at the database.
 instead of looking directly at the database.
 Its first argument specifies the network root to use.
 Its first argument specifies the network root to use.
@@ -373,13 +374,15 @@ name servers.  Returns domain name
 and name server
 and name server
 .RI ( ns )
 .RI ( ns )
 .PP
 .PP
-.I Ndblookval
+.I Ndblookvalue
 searches 
 searches 
 .I entry
 .I entry
 for the tuple
 for the tuple
 with attribute
 with attribute
 .IR attr ,
 .IR attr ,
-copies the value into
+copies up to
+.I tolen
+bytes of the value into
 .IR to ,
 .IR to ,
 and returns a pointer to the tuple.
 and returns a pointer to the tuple.
 If
 If
@@ -452,3 +455,28 @@ is freed.
 .SH DIAGNOSTICS
 .SH DIAGNOSTICS
 These routines set
 These routines set
 .IR errstr .
 .IR errstr .
+.IR Ndbgetvalue ,
+.IR csgetvalue ,
+and
+.I ndblookvalue
+set
+.I errstr
+to
+.B "return value truncated"
+if the buffer provided isn't long enough for the
+returned value.
+.SH BUGS
+.IR Ndbgetval ,
+.IR csgetval ,
+and
+.I ndblookval
+are deprecated versions of
+.IR ndbgetvalue ,
+.IR csgetvalue ,
+and
+.IR ndblookvalue .
+They expect a fixed 64 byte long result
+buffer and existed when the values of a
+.I Ndbtuple
+structure where fixed length.
+

+ 13 - 24
sys/src/9/port/proc.c

@@ -7,7 +7,8 @@
 #include	"edf.h"
 #include	"edf.h"
 #include	<trace.h>
 #include	<trace.h>
 
 
-int	coopsched = 1;
+int	coopsched;
+int	schedgain = 30;	/* units in seconds */
 int	nrdy;
 int	nrdy;
 Ref	noteidalloc;
 Ref	noteidalloc;
 
 
@@ -33,18 +34,11 @@ enum
 {
 {
 	Q=10,
 	Q=10,
 	DQ=4,
 	DQ=4,
+	Scaling=2,
 };
 };
 
 
 Schedq	runq[Nrq];
 Schedq	runq[Nrq];
 ulong	runvec;
 ulong	runvec;
-static int	quanta[Npriq] =
-{
-	Q+19*DQ, Q+18*DQ, Q+17*DQ, Q+16*DQ,
-	Q+15*DQ, Q+14*DQ, Q+13*DQ, Q+12*DQ,
-	Q+11*DQ, Q+10*DQ, Q+ 9*DQ, Q+ 8*DQ,
-	Q+ 7*DQ, Q+ 6*DQ, Q+ 5*DQ, Q+ 4*DQ,
-	Q+ 3*DQ, Q+ 2*DQ, Q+ 1*DQ, Q+ 0*DQ,
-};
 
 
 char *statename[] =
 char *statename[] =
 {	/* BUG: generate automatically */
 {	/* BUG: generate automatically */
@@ -155,6 +149,7 @@ sched(void)
 	}
 	}
 	if(p != m->readied)
 	if(p != m->readied)
 		m->schedticks = m->ticks + HZ/10;
 		m->schedticks = m->ticks + HZ/10;
+	m->readied = 0;
 	up = p;
 	up = p;
 	up->state = Running;
 	up->state = Running;
 	up->mach = MACHP(m->machno);
 	up->mach = MACHP(m->machno);
@@ -259,12 +254,12 @@ void
 updatecpu(Proc *p)
 updatecpu(Proc *p)
 {
 {
 	int n, t, ocpu;
 	int n, t, ocpu;
-	enum { D = 30*HZ };
+	int D = schedgain*HZ*Scaling;
 
 
 	if(p->edf)
 	if(p->edf)
 		return;
 		return;
 
 
-	t = MACHP(0)->ticks;
+	t = MACHP(0)->ticks*Scaling + Scaling/2;
 	n = t - p->lastupdate;
 	n = t - p->lastupdate;
 	p->lastupdate = t;
 	p->lastupdate = t;
 
 
@@ -429,16 +424,16 @@ void
 yield(void)
 yield(void)
 {
 {
 	if(anyready()){
 	if(anyready()){
-		/* pretend we just used 10ms */
-		up->lastupdate -= HZ/100;
+		/* pretend we just used 1/2 tick */
+		up->lastupdate -= Scaling/2;  
 		sched();
 		sched();
 	}
 	}
 }
 }
 
 
 /*
 /*
- * move up any process waiting more than its quanta
- * called once per clock tick on processor 0.
- * we reduce this to once per second via blaancetime.
+ *  recalculate priorities once a second.  We need to do this
+ *  since priorities will otherwise only be recalculated when
+ *  the running process blocks.
  */
  */
 ulong balancetime;
 ulong balancetime;
 
 
@@ -631,12 +626,8 @@ newproc(void)
 	p->mp = 0;
 	p->mp = 0;
 	p->wired = 0;
 	p->wired = 0;
 	procpriority(p, PriNormal, 0);
 	procpriority(p, PriNormal, 0);
-
-	/* a priori, somewhere below interactive but above the cpu hogs */
-	p->cpu = 1000000/(5*MACHP(0)->load+1);
-	if(p->cpu > 1000)
-		p->cpu = 1000;
-	p->priority = reprioritize(p);
+	p->cpu = 0;
+	p->lastupdate = MACHP(0)->ticks*Scaling;
 	p->edf = nil;
 	p->edf = nil;
 
 
 	return p;
 	return p;
@@ -686,10 +677,8 @@ procpriority(Proc *p, int pri, int fixed)
 	p->basepri = pri;
 	p->basepri = pri;
 	p->priority = pri;
 	p->priority = pri;
 	if(fixed){
 	if(fixed){
-		// p->quanta = 0xfffff;
 		p->fixedpri = 1;
 		p->fixedpri = 1;
 	} else {
 	} else {
-		// p->quanta = quanta[pri];
 		p->fixedpri = 0;
 		p->fixedpri = 0;
 	}
 	}
 }
 }

+ 77 - 80
sys/src/cmd/ndb/cs.c

@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include <ctype.h>
 #include <ndb.h>
 #include <ndb.h>
 #include <ip.h>
 #include <ip.h>
+#include <String.h>
 
 
 enum
 enum
 {
 {
@@ -14,6 +15,8 @@ enum
 	Maxrequest=		128,
 	Maxrequest=		128,
 	Maxpath=		128,
 	Maxpath=		128,
 	Maxfdata=		8192,
 	Maxfdata=		8192,
+	Maxhost=		64,		/* maximum host name size */
+	Maxservice=		64,		/* maximum service name size */
 
 
 	Qdir=			0,
 	Qdir=			0,
 	Qcs=			1,
 	Qcs=			1,
@@ -152,12 +155,13 @@ enum
 	Nil,
 	Nil,
 	Nudp,
 	Nudp,
 	Nicmp,
 	Nicmp,
+	Nicmpv6,
 	Nrudp,
 	Nrudp,
 	Ntelco,
 	Ntelco,
 };
 };
 
 
 /*
 /*
- *  net doesn't apply to udp, icmp, or telco (for speed)
+>  *  net doesn't apply to (r)udp, icmp(v6), or telco (for speed)
  */
  */
 Network network[] = {
 Network network[] = {
 [Nilfast]	{ "il",		iplookup,	iptrans,	0, 1 },
 [Nilfast]	{ "il",		iplookup,	iptrans,	0, 1 },
@@ -165,6 +169,7 @@ Network network[] = {
 [Nil]		{ "il",		iplookup,	iptrans,	0, 0 },
 [Nil]		{ "il",		iplookup,	iptrans,	0, 0 },
 [Nudp]		{ "udp",	iplookup,	iptrans,	1, 0 },
 [Nudp]		{ "udp",	iplookup,	iptrans,	1, 0 },
 [Nicmp]		{ "icmp",	iplookup,	iptrans,	1, 0 },
 [Nicmp]		{ "icmp",	iplookup,	iptrans,	1, 0 },
+[Nicmpv6]	{ "icmpv6",	iplookup,	iptrans,	1, 0 },
 [Nrudp]		{ "rudp",	iplookup,	iptrans,	1, 0 },
 [Nrudp]		{ "rudp",	iplookup,	iptrans,	1, 0 },
 [Ntelco]	{ "telco",	telcolookup,	telcotrans,	1, 0 },
 [Ntelco]	{ "telco",	telcolookup,	telcotrans,	1, 0 },
 		{ 0 },
 		{ 0 },
@@ -173,14 +178,22 @@ Network network[] = {
 Lock ipifclock;
 Lock ipifclock;
 Ipifc *ipifcs;
 Ipifc *ipifcs;
 
 
-char	eaddr[Ndbvlen];		/* ascii ethernet address */
-char	ipaddr[Ndbvlen];	/* ascii internet address */
+char	eaddr[16];		/* ascii ethernet address */
+char	ipaddr[64];		/* ascii internet address */
 uchar	ipa[IPaddrlen];		/* binary internet address */
 uchar	ipa[IPaddrlen];		/* binary internet address */
-char	mysysname[Ndbvlen];
+char	*mysysname;
 
 
 Network *netlist;		/* networks ordered by preference */
 Network *netlist;		/* networks ordered by preference */
 Network *last;
 Network *last;
 
 
+static void
+nstrcpy(char *to, char *from, int len)
+{
+	strncpy(to, from, len);
+	to[len-1] = 0;
+}
+
+
 void
 void
 usage(void)
 usage(void)
 {
 {
@@ -957,9 +970,8 @@ ipid(void)
 	int f;
 	int f;
 	char buf[Maxpath];
 	char buf[Maxpath];
 
 
-
 	/* use environment, ether addr, or ipaddr to get system name */
 	/* use environment, ether addr, or ipaddr to get system name */
-	if(*mysysname == 0){
+	if(mysysname == 0){
 		/*
 		/*
 		 *  environment has priority.
 		 *  environment has priority.
 		 *
 		 *
@@ -971,7 +983,7 @@ ipid(void)
 		if(p){
 		if(p){
 			attr = ipattr(p);
 			attr = ipattr(p);
 			if(strcmp(attr, "ip") != 0)
 			if(strcmp(attr, "ip") != 0)
-				strcpy(mysysname, p);
+				mysysname = strdup(p);
 		}
 		}
 
 
 		/*
 		/*
@@ -979,11 +991,11 @@ ipid(void)
 		 *  figured out from DHCP.  use that name if
 		 *  figured out from DHCP.  use that name if
 		 *  there is one. 
 		 *  there is one. 
 		 */
 		 */
-		if(*mysysname == 0 && netdb != nil){
+		if(mysysname == 0 && netdb != nil){
 			ndbreopen(netdb);
 			ndbreopen(netdb);
 			for(tt = t = ndbparse(netdb); t != nil; t = t->entry){
 			for(tt = t = ndbparse(netdb); t != nil; t = t->entry){
 				if(strcmp(t->attr, "sys") == 0){
 				if(strcmp(t->attr, "sys") == 0){
-					strcpy(mysysname, t->val);
+					mysysname = strdup(t->val);
 					break;
 					break;
 				}
 				}
 			}
 			}
@@ -991,32 +1003,37 @@ ipid(void)
 		}
 		}
 
 
 		/* next network database, ip address, and ether address to find a name */
 		/* next network database, ip address, and ether address to find a name */
-		if(*mysysname == 0){
+		if(mysysname == 0){
 			t = nil;
 			t = nil;
 			if(isvalidip(ipa))
 			if(isvalidip(ipa))
-				t = ndbgetval(db, &s, "ip", ipaddr, "sys", mysysname);
-			else {
+				t = ndbgetvalue(db, &s, "ip", ipaddr, "sys", nil, 0);
+			if(t == nil){
 				for(f = 0; f < 3; f++){
 				for(f = 0; f < 3; f++){
 					snprint(buf, sizeof buf, "%s/ether%d", mntpt, f);
 					snprint(buf, sizeof buf, "%s/ether%d", mntpt, f);
 					if(myetheraddr(addr, buf) >= 0){
 					if(myetheraddr(addr, buf) >= 0){
 						snprint(eaddr, sizeof(eaddr), "%E", addr);
 						snprint(eaddr, sizeof(eaddr), "%E", addr);
-						t = ndbgetval(db, &s, "ether", eaddr, "sys",
-							mysysname);
+						t = ndbgetvalue(db, &s, "ether", eaddr, "sys",
+							nil, 0);
 						if(t != nil)
 						if(t != nil)
 							break;
 							break;
 					}
 					}
 				}
 				}
 			}
 			}
+			for(tt = t; tt != nil; tt = tt->entry)
+				if(strcmp(t->attr, "sys") == 0){
+					mysysname = strdup(t->val);
+					break;
+				}
 			ndbfree(t);
 			ndbfree(t);
 		}
 		}
 
 
 		/* nothing else worked, use the ip address */
 		/* nothing else worked, use the ip address */
-		if(*mysysname == 0 && isvalidip(ipa))
-			strcpy(mysysname, ipaddr);
+		if(mysysname == 0 && isvalidip(ipa))
+			mysysname = strdup(ipaddr);
 					
 					
 
 
 		/* set /dev/sysname if we now know it */
 		/* set /dev/sysname if we now know it */
-		if(*mysysname){
+		if(mysysname){
 			f = open("/dev/sysname", OWRITE);
 			f = open("/dev/sysname", OWRITE);
 			if(f >= 0){
 			if(f >= 0){
 				write(f, mysysname, strlen(mysysname));
 				write(f, mysysname, strlen(mysysname));
@@ -1071,7 +1088,7 @@ netinit(int background)
 
 
 	if(debug)
 	if(debug)
 		syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n",
 		syslog(0, logfile, "mysysname %s eaddr %s ipaddr %s ipa %I\n",
-			mysysname, eaddr, ipaddr, ipa);
+			mysysname?mysysname:"???", eaddr, ipaddr, ipa);
 
 
 	if(background){
 	if(background){
 		unlock(&netlock);
 		unlock(&netlock);
@@ -1107,23 +1124,6 @@ netadd(char *p)
 	}
 	}
 }
 }
 
 
-/*
- *  make a tuple
- */
-Ndbtuple*
-mktuple(char *attr, char *val)
-{
-	Ndbtuple *t;
-
-	t = emalloc(sizeof(Ndbtuple));
-	strcpy(t->attr, attr);
-	strncpy(t->val, val, sizeof(t->val));
-	t->val[sizeof(t->val)-1] = 0;
-	t->line = t;
-	t->entry = 0;
-	return t;
-}
-
 int
 int
 lookforproto(Ndbtuple *t, char *proto)
 lookforproto(Ndbtuple *t, char *proto)
 {
 {
@@ -1195,22 +1195,23 @@ lookup(Mfile *mf)
 	 */
 	 */
 	if(mf->nreply != 0)
 	if(mf->nreply != 0)
 		return 0;
 		return 0;
-
 	/*
 	/*
 	 *  look for a specific network
 	 *  look for a specific network
 	 */
 	 */
-	for(np = netlist; np->net != nil; np++){
+	for(np = netlist; np && np->net != nil; np++){
 		if(np->fasttimeouthack)
 		if(np->fasttimeouthack)
 			continue;
 			continue;
 		if(strcmp(np->net, mf->net) == 0)
 		if(strcmp(np->net, mf->net) == 0)
 			break;
 			break;
 	}
 	}
 
 
-	if(np->net != nil){
+	if(np && np->net != nil){
 		/*
 		/*
 		 *  known network
 		 *  known network
 		 */
 		 */
+syslog(0, logfile, "specific lookup %s", np->net);
 		nt = (*np->lookup)(np, mf->host, mf->serv, 1);
 		nt = (*np->lookup)(np, mf->host, mf->serv, 1);
+syslog(0, logfile, "returned %p", nt);
 		for(t = nt; mf->nreply < Nreply && t; t = t->entry){
 		for(t = nt; mf->nreply < Nreply && t; t = t->entry){
 			cp = (*np->trans)(t, np, mf->serv, mf->rem, 0);
 			cp = (*np->trans)(t, np, mf->serv, mf->rem, 0);
 			if(cp){
 			if(cp){
@@ -1245,12 +1246,12 @@ lookup(Mfile *mf)
  *  the service '*' needs no translation.
  *  the service '*' needs no translation.
  */
  */
 char*
 char*
-ipserv(Network *np, char *name, char *buf)
+ipserv(Network *np, char *name, char *buf, int blen)
 {
 {
 	char *p;
 	char *p;
 	int alpha = 0;
 	int alpha = 0;
 	int restr = 0;
 	int restr = 0;
-	char port[Ndbvlen];
+	char port[10];
 	Ndbtuple *t, *nt;
 	Ndbtuple *t, *nt;
 	Ndbs s;
 	Ndbs s;
 
 
@@ -1271,7 +1272,7 @@ ipserv(Network *np, char *name, char *buf)
 			return 0;
 			return 0;
 	}
 	}
 	if(alpha){
 	if(alpha){
-		t = ndbgetval(db, &s, np->net, name, "port", port);
+		t = ndbgetvalue(db, &s, np->net, name, "port", port, sizeof(port));
 		if(t == 0)
 		if(t == 0)
 			return 0;
 			return 0;
 	} else {
 	} else {
@@ -1280,11 +1281,9 @@ ipserv(Network *np, char *name, char *buf)
 		 */
 		 */
 		t = nil;
 		t = nil;
 		if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0)
 		if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0)
-			t = ndbgetval(db, &s, "port", name, "port", port);
-		if(t == nil){
-			strncpy(port, name, sizeof(port));
-			port[sizeof(port)-1] = 0;
-		}
+			t = ndbgetvalue(db, &s, "port", name, "port", port, sizeof(port));
+		if(t == nil)
+			nstrcpy(port, name, sizeof(port));
 	}
 	}
 
 
 	if(t){
 	if(t){
@@ -1293,7 +1292,7 @@ ipserv(Network *np, char *name, char *buf)
 				restr = 1;
 				restr = 1;
 		ndbfree(t);
 		ndbfree(t);
 	}
 	}
-	sprint(buf, "%s%s", port, restr ? "!r" : ""); 
+	snprint(buf, blen, "%s%s", port, restr ? "!r" : ""); 
 	return buf;
 	return buf;
 }
 }
 
 
@@ -1301,7 +1300,7 @@ ipserv(Network *np, char *name, char *buf)
  *  lookup an ip attribute
  *  lookup an ip attribute
  */
  */
 int
 int
-ipattrlookup(Ndb *db, char *ipa, char *attr, char *val)
+ipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen)
 {
 {
 	
 	
 	Ndbtuple *t, *nt;
 	Ndbtuple *t, *nt;
@@ -1313,7 +1312,7 @@ ipattrlookup(Ndb *db, char *ipa, char *attr, char *val)
 		return 0;
 		return 0;
 	for(nt = t; nt != nil; nt = nt->entry){
 	for(nt = t; nt != nil; nt = nt->entry){
 		if(strcmp(nt->attr, attr) == 0){
 		if(strcmp(nt->attr, attr) == 0){
-			strcpy(val, nt->val);
+			nstrcpy(val, nt->val, vlen);
 			ndbfree(t);
 			ndbfree(t);
 			return 1;
 			return 1;
 		}
 		}
@@ -1333,9 +1332,9 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
 	char *attr;
 	char *attr;
 	Ndbtuple *t, *nt;
 	Ndbtuple *t, *nt;
 	Ndbs s;
 	Ndbs s;
-	char ts[Ndbvlen+1];
-	char th[Ndbvlen+1];
-	char dollar[Ndbvlen+1];
+	char ts[Maxservice];
+	char th[Maxhost];
+	char dollar[Maxhost];
 	uchar ip[IPaddrlen];
 	uchar ip[IPaddrlen];
 	uchar net[IPaddrlen];
 	uchar net[IPaddrlen];
 	uchar tnet[IPaddrlen];
 	uchar tnet[IPaddrlen];
@@ -1349,27 +1348,27 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
 	 *  and costs the least
 	 *  and costs the least
 	 */
 	 */
 	werrstr("can't translate address");
 	werrstr("can't translate address");
-	if(serv==0 || ipserv(np, serv, ts) == 0){
+	if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){
 		werrstr("can't translate service");
 		werrstr("can't translate service");
 		return 0;
 		return 0;
 	}
 	}
 
 
 	/* for dial strings with no host */
 	/* for dial strings with no host */
 	if(strcmp(host, "*") == 0)
 	if(strcmp(host, "*") == 0)
-		return mktuple("ip", "*");
+		return ndbnew("ip", "*");
 
 
 	/*
 	/*
 	 *  hack till we go v6 :: = 0.0.0.0
 	 *  hack till we go v6 :: = 0.0.0.0
 	 */
 	 */
 	if(strcmp("::", host) == 0)
 	if(strcmp("::", host) == 0)
-		return mktuple("ip", "*");
+		return ndbnew("ip", "*");
 
 
 	/*
 	/*
 	 *  '$' means the rest of the name is an attribute that we
 	 *  '$' means the rest of the name is an attribute that we
 	 *  need to search for
 	 *  need to search for
 	 */
 	 */
 	if(*host == '$'){
 	if(*host == '$'){
-		if(ipattrlookup(db, ipaddr, host+1, dollar))
+		if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar))
 			host = dollar;
 			host = dollar;
 	}
 	}
 
 
@@ -1386,7 +1385,7 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
 	 */
 	 */
 	attr = ipattr(host);
 	attr = ipattr(host);
 	if(strcmp(attr, "ip") == 0)
 	if(strcmp(attr, "ip") == 0)
-		return mktuple("ip", host);
+		return ndbnew("ip", host);
 
 
 	/*
 	/*
 	 *  give the domain name server the first opportunity to
 	 *  give the domain name server the first opportunity to
@@ -1397,11 +1396,9 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
 	if(strcmp(attr, "dom") == 0)
 	if(strcmp(attr, "dom") == 0)
 		t = dnsiplookup(host, &s);
 		t = dnsiplookup(host, &s);
 	if(t == 0)
 	if(t == 0)
-		t = ndbgetval(db, &s, attr, host, "ip", th);
+		t = ndbgetvalue(db, &s, attr, host, "ip", th, sizeof(th));
 	if(t == 0)
 	if(t == 0)
 		t = dnsiplookup(host, &s);
 		t = dnsiplookup(host, &s);
-	if(t == 0 && strcmp(attr, "dom") != 0)
-		t = dnsiplookup(host, &s);
 	if(t == 0)
 	if(t == 0)
 		return 0;
 		return 0;
 
 
@@ -1442,14 +1439,14 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
 char*
 char*
 iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
 iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
 {
 {
-	char ts[Ndbvlen+1];
+	char ts[Maxservice];
 	char reply[Maxreply];
 	char reply[Maxreply];
-	char x[Ndbvlen+1];
+	char x[Maxservice];
 
 
 	if(strcmp(t->attr, "ip") != 0)
 	if(strcmp(t->attr, "ip") != 0)
 		return 0;
 		return 0;
 
 
-	if(serv == 0 || ipserv(np, serv, ts) == 0){
+	if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){
 		werrstr("can't translate service");
 		werrstr("can't translate service");
 		return 0;
 		return 0;
 	}
 	}
@@ -1476,14 +1473,14 @@ telcolookup(Network *np, char *host, char *serv, int nolookup)
 {
 {
 	Ndbtuple *t;
 	Ndbtuple *t;
 	Ndbs s;
 	Ndbs s;
-	char th[Ndbvlen+1];
+	char th[Maxhost];
 
 
 	USED(np, nolookup, serv);
 	USED(np, nolookup, serv);
 
 
 	werrstr("can't translate address");
 	werrstr("can't translate address");
-	t = ndbgetval(db, &s, "sys", host, "telco", th);
+	t = ndbgetvalue(db, &s, "sys", host, "telco", th, sizeof(th));
 	if(t == 0)
 	if(t == 0)
-		return mktuple("telco", host);
+		return ndbnew("telco", host);
 
 
 	return reorder(t, s.t);
 	return reorder(t, s.t);
 }
 }
@@ -1495,7 +1492,7 @@ char*
 telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int)
 telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int)
 {
 {
 	char reply[Maxreply];
 	char reply[Maxreply];
-	char x[Ndbvlen+1];
+	char x[Maxservice];
 
 
 	if(strcmp(t->attr, "telco") != 0)
 	if(strcmp(t->attr, "telco") != 0)
 		return 0;
 		return 0;
@@ -1571,7 +1568,7 @@ slave(void)
 Ndbtuple*
 Ndbtuple*
 dnsiplookup(char *host, Ndbs *s)
 dnsiplookup(char *host, Ndbs *s)
 {
 {
-	char buf[Ndbvlen + 4];
+	char buf[Maxreply];
 	Ndbtuple *t;
 	Ndbtuple *t;
 
 
 	unlock(&dblock);
 	unlock(&dblock);
@@ -1623,23 +1620,23 @@ qmatch(Ndbtuple *t, char **attr, char **val, int n)
 void
 void
 qreply(Mfile *mf, Ndbtuple *t)
 qreply(Mfile *mf, Ndbtuple *t)
 {
 {
-	int i;
 	Ndbtuple *nt;
 	Ndbtuple *nt;
-	char buf[2048];
+	String *s;
 
 
-	buf[0] = 0;
+	s = s_new();
 	for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){
 	for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){
-		strcat(buf, nt->attr);
-		strcat(buf, "=");
-		strcat(buf, nt->val);
-		i = strlen(buf);
-		if(nt->line != nt->entry || sizeof(buf) - i < 2*Ndbvlen+2){
-			mf->replylen[mf->nreply] = strlen(buf);
-			mf->reply[mf->nreply++] = strdup(buf);
-			buf[0] = 0;
+		s_append(s, nt->attr);
+		s_append(s, "=");
+		s_append(s, nt->val);
+
+		if(nt->line != nt->entry){
+			mf->replylen[mf->nreply] = s_len(s);
+			mf->reply[mf->nreply++] = strdup(s_to_c(s));
+			s_restart(s);
 		} else
 		} else
-			strcat(buf, " ");
+			s_append(s, " ");
 	}
 	}
+	s_free(s);
 }
 }
 
 
 enum
 enum

+ 14 - 3
sys/src/libndb/csgetval.c

@@ -11,7 +11,7 @@
  *  return 0 if not found.
  *  return 0 if not found.
  */
  */
 Ndbtuple*
 Ndbtuple*
-csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
+csgetvalue(char *netroot, char *attr, char *val, char *rattr, char *buf, int len)
 {
 {
 	Ndbtuple *t, *first, *last;
 	Ndbtuple *t, *first, *last;
 	int n, linefound;
 	int n, linefound;
@@ -35,6 +35,7 @@ csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
 	}
 	}
 	seek(fd, 0, 0);
 	seek(fd, 0, 0);
 
 
+	werrstr("");
 	first = last = 0;
 	first = last = 0;
 	linefound = 0;
 	linefound = 0;
 	for(;;){
 	for(;;){
@@ -58,8 +59,12 @@ csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
 
 
 		for(; t; t = t->entry){
 		for(; t; t = t->entry){
 			if(buf[0] == 0 || linefound == 0)
 			if(buf[0] == 0 || linefound == 0)
-				if(strcmp(rattr, t->attr) == 0)
-					strcpy(buf, t->val);
+				if(strcmp(rattr, t->attr) == 0){
+					strncpy(buf, t->val, len);
+					buf[len-1] = 0;
+					if(strlen(t->val) >= len)
+						werrstr("return value truncated");
+				}
 			if(linefound == 0)
 			if(linefound == 0)
 				if(strcmp(attr, t->attr) == 0)
 				if(strcmp(attr, t->attr) == 0)
 					linefound = 1;
 					linefound = 1;
@@ -70,3 +75,9 @@ csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
 	setmalloctag(first, getcallerpc(&netroot));
 	setmalloctag(first, getcallerpc(&netroot));
 	return first;
 	return first;
 }
 }
+
+Ndbtuple*
+csgetval(char *netroot, char *attr, char *val, char *rattr, char *buf)
+{
+	return csgetvalue(netroot, attr, val, rattr, buf, Ndbvlen);
+}

+ 11 - 11
sys/src/libndb/dnsquery.c

@@ -4,8 +4,8 @@
 #include <ndb.h>
 #include <ndb.h>
 #include <ndbhf.h>
 #include <ndbhf.h>
 
 
-static void nstrcpy(char*, char*);
-static void mkptrname(char*, char*);
+static void nstrcpy(char*, char*, int);
+static void mkptrname(char*, char*, int);
 static Ndbtuple *doquery(int, char *dn, char *type);
 static Ndbtuple *doquery(int, char *dn, char *type);
 
 
 /*
 /*
@@ -17,7 +17,7 @@ static Ndbtuple *doquery(int, char *dn, char *type);
 Ndbtuple*
 Ndbtuple*
 dnsquery(char *net, char *val, char *type)
 dnsquery(char *net, char *val, char *type)
 {
 {
-	char rip[Ndbvlen];
+	char rip[128];
 	char *p;
 	char *p;
 	Ndbtuple *t;
 	Ndbtuple *t;
 	int fd;
 	int fd;
@@ -57,7 +57,7 @@ dnsquery(char *net, char *val, char *type)
 
 
 	/* if this is a reverse lookup, first lookup the domain name */
 	/* if this is a reverse lookup, first lookup the domain name */
 	if(strcmp(type, "ptr") == 0){
 	if(strcmp(type, "ptr") == 0){
-		mkptrname(val, rip);
+		mkptrname(val, rip, sizeof rip);
 		t = doquery(fd, rip, "ptr");
 		t = doquery(fd, rip, "ptr");
 	} else
 	} else
 		t = doquery(fd, val, type);
 		t = doquery(fd, val, type);
@@ -70,18 +70,18 @@ dnsquery(char *net, char *val, char *type)
  *  convert address into a reverse lookup address
  *  convert address into a reverse lookup address
  */
  */
 static void
 static void
-mkptrname(char *ip, char *rip)
+mkptrname(char *ip, char *rip, int rlen)
 {
 {
-	char buf[Ndbvlen];
+	char buf[128];
 	char *p, *np;
 	char *p, *np;
 	int len;
 	int len;
 
 
 	if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
 	if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
-		nstrcpy(rip, ip);
+		nstrcpy(rip, ip, rlen);
 		return;
 		return;
 	}
 	}
 
 
-	nstrcpy(buf, ip);
+	nstrcpy(buf, ip, sizeof buf);
 	for(p = buf; *p; p++)
 	for(p = buf; *p; p++)
 		;
 		;
 	*p = '.';
 	*p = '.';
@@ -102,10 +102,10 @@ mkptrname(char *ip, char *rip)
 }
 }
 
 
 static void
 static void
-nstrcpy(char *to, char *from)
+nstrcpy(char *to, char *from, int len)
 {
 {
-	strncpy(to, from, Ndbvlen-1);
-	to[Ndbvlen-1] = 0;
+	strncpy(to, from, len);
+	to[len-1] = 0;
 }
 }
 
 
 static Ndbtuple*
 static Ndbtuple*

+ 14 - 9
sys/src/libndb/mkfile

@@ -2,20 +2,25 @@
 
 
 LIB=/$objtype/lib/libndb.a
 LIB=/$objtype/lib/libndb.a
 OFILES=\
 OFILES=\
-	ndbhash.$O\
-	ndbopen.$O\
-	ndbparse.$O\
+	csgetval.$O\
+	csipinfo.$O\
+	dnsquery.$O\
+	ipattr.$O\
+	ndbaux.$O\
 	ndbcache.$O\
 	ndbcache.$O\
 	ndbcat.$O\
 	ndbcat.$O\
-	ndbgetval.$O\
-	ndbaux.$O\
+	ndbconcatenate.$O\
+	ndbdiscard.$O\
 	ndbfree.$O\
 	ndbfree.$O\
-	ipattr.$O\
+	ndbgetipaddr.$O\
+	ndbgetval.$O\
+	ndbhash.$O\
 	ndbipinfo.$O\
 	ndbipinfo.$O\
 	ndblookval.$O\
 	ndblookval.$O\
-	csgetval.$O\
-	csipinfo.$O\
-	dnsquery.$O\
+	ndbopen.$O\
+	ndbparse.$O\
+	ndbreorder.$O\
+	ndbsubstitute.$O\
 
 
 HFILES=\
 HFILES=\
 	/sys/include/ndb.h\
 	/sys/include/ndb.h\

+ 2 - 6
sys/src/libndb/ndbaux.c

@@ -21,9 +21,7 @@ _ndbparsetuple(char *cp, Ndbtuple **tp)
 	if(*cp == '#' || *cp == '\n')
 	if(*cp == '#' || *cp == '\n')
 		return 0;
 		return 0;
 
 
-	t = mallocz(sizeof(Ndbtuple), 1);
-	if(t == nil)
-		return nil;
+	t = ndbnew(nil, nil);
 	setmalloctag(t, getcallerpc(&cp));
 	setmalloctag(t, getcallerpc(&cp));
 	*tp = t;
 	*tp = t;
 
 
@@ -56,9 +54,7 @@ _ndbparsetuple(char *cp, Ndbtuple **tp)
 				cp++;
 				cp++;
 			len = cp - p;
 			len = cp - p;
 		}
 		}
-		if(len >= Ndbvlen)
-			len = Ndbvlen;
-		strncpy(t->val, p, len);
+		ndbsetval(t, p, len);
 	}
 	}
 
 
 	return cp;
 	return cp;

+ 1 - 6
sys/src/libndb/ndbcache.c

@@ -42,12 +42,7 @@ ndbcopy(Ndb *db, Ndbtuple *from_t, Ndbs *from_s, Ndbs *to_s)
 	first = nil;
 	first = nil;
 	line = nil;
 	line = nil;
 	for(; from_t != nil; from_t = from_t->entry){
 	for(; from_t != nil; from_t = from_t->entry){
-		to_t = malloc(sizeof *to_t);
-		if(to_t == nil){
-			ndbfree(first);
-			return nil;
-		}
-		*to_t = *from_t;
+		to_t = ndbnew(from_t->attr, from_t->val);
 
 
 		/* have s point to matching tuple */
 		/* have s point to matching tuple */
 		if(from_s->t == from_t)
 		if(from_s->t == from_t)

+ 18 - 0
sys/src/libndb/ndbconcatenate.c

@@ -0,0 +1,18 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+
+/* concatenate two tuples */
+Ndbtuple*
+ndbconcatenate(Ndbtuple *a, Ndbtuple *b)
+{
+	Ndbtuple *t;
+
+	if(a == nil)
+		return b;
+	for(t = a; t->entry; t = t->entry)
+		;
+	t->entry = b;
+	return a;
+}

+ 29 - 0
sys/src/libndb/ndbdiscard.c

@@ -0,0 +1,29 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+
+/* remove a from t and free it */
+Ndbtuple*
+ndbdiscard(Ndbtuple *t, Ndbtuple *a)
+{
+	Ndbtuple *nt;
+
+	/* unchain a */
+	for(nt = t; nt != nil; nt = nt->entry){
+		if(nt->line == a)
+			nt->line = a->line;
+		if(nt->entry == a)
+			nt->entry = a->entry;
+	}
+
+	/* a may be start of chain */
+	if(t == a)
+		t = a->entry;
+
+	/* free a */
+	a->entry = nil;
+	ndbfree(a);
+
+	return t;
+}

+ 45 - 0
sys/src/libndb/ndbfree.c

@@ -15,6 +15,51 @@ ndbfree(Ndbtuple *t)
 
 
 	for(; t; t = tn){
 	for(; t; t = tn){
 		tn = t->entry;
 		tn = t->entry;
+		if(t->val != t->valbuf){
+			free(t->val);
+		}
 		free(t);
 		free(t);
 	}
 	}
 }
 }
+
+/*
+ *  set a value in a tuple
+ */
+void
+ndbsetval(Ndbtuple *t, char *val, int n)
+{
+	if(n < Ndbvlen){
+		if(t->val != t->valbuf){
+			free(t->val);
+			t->val = t->valbuf;
+		}
+	} else {
+		if(t->val != t->valbuf)
+			t->val = realloc(t->val, n+1);
+		else
+			t->val = malloc(n+1);
+		if(t->val == nil)
+			sysfatal("ndbsetval %r");
+	}
+	strncpy(t->val, val, n);
+	t->val[n] = 0;
+}
+
+/*
+ *  allocate a tuple
+ */
+Ndbtuple*
+ndbnew(char *attr, char *val)
+{
+	Ndbtuple *t;
+
+	t = mallocz(sizeof(*t), 1);
+	if(t == nil)
+		sysfatal("ndbnew %r");
+	if(attr != nil)
+		strncpy(t->attr, attr, sizeof(t->attr)-1);
+	t->val = t->valbuf;
+	if(val != nil)
+		ndbsetval(t, val, strlen(val));
+	return t;	
+}

+ 47 - 0
sys/src/libndb/ndbgetipaddr.c

@@ -0,0 +1,47 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+#include <ip.h>
+
+/* return list of ip addresses for a name */
+Ndbtuple*
+ndbgetipaddr(Ndb *db, char *val)
+{
+	char *attr;
+	Ndbtuple *it, *first, *last, *next;
+	Ndbs s;
+	char buf[Ndbvlen];
+
+	/* already an IP address? */
+	attr = ipattr(val);
+	if(strcmp(attr, "ip") == 0){
+		it = ndbnew("ip", val);
+		return it;
+	}
+
+	/* look it up */
+	it = ndbgetvalue(db, &s, attr, val, "ip", buf, sizeof(buf));
+	if(it == nil)
+		return nil;
+
+	/* remove the non-ip entries */
+	first = last = nil;
+	for(; it; it = next){
+		next = it->entry;
+		if(strcmp(it->attr, "ip") == 0){
+			if(first == nil)
+				first = it;
+			else
+				last->entry = it;
+			it->entry = nil;
+			it->line = first;
+			last = it;
+		} else {
+			it->entry = nil;
+			ndbfree(it);
+		}
+	}
+
+	return first;
+}

+ 16 - 3
sys/src/libndb/ndbgetval.c

@@ -10,17 +10,21 @@
  *  return 0 if not found.
  *  return 0 if not found.
  */
  */
 Ndbtuple*
 Ndbtuple*
-ndbgetval(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, char *buf)
+ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, char *buf, int len)
 {
 {
 	Ndbtuple *t, *nt;
 	Ndbtuple *t, *nt;
 
 
+	werrstr("");
 	t = ndbsearch(db, s, attr, val);
 	t = ndbsearch(db, s, attr, val);
 	while(t){
 	while(t){
 		/* first look on same line (closer binding) */
 		/* first look on same line (closer binding) */
 		nt = s->t;
 		nt = s->t;
 		for(;;){
 		for(;;){
 			if(strcmp(rattr, nt->attr) == 0){
 			if(strcmp(rattr, nt->attr) == 0){
-				strncpy(buf, nt->val, Ndbvlen);
+				strncpy(buf, nt->val, len);
+				buf[len-1] = 0;
+				if(strlen(nt->val) >= len)
+					werrstr("return value truncated");
 				return t;
 				return t;
 			}
 			}
 			nt = nt->line;
 			nt = nt->line;
@@ -30,7 +34,10 @@ ndbgetval(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, char *buf)
 		/* search whole tuple */
 		/* search whole tuple */
 		for(nt = t; nt; nt = nt->entry)
 		for(nt = t; nt; nt = nt->entry)
 			if(strcmp(rattr, nt->attr) == 0){
 			if(strcmp(rattr, nt->attr) == 0){
-				strncpy(buf, nt->val, Ndbvlen);
+				strncpy(buf, nt->val, len);
+				buf[len-1] = 0;
+				if(strlen(nt->val) >= len)
+					werrstr("return value truncated");
 				return t;
 				return t;
 			}
 			}
 		ndbfree(t);
 		ndbfree(t);
@@ -38,3 +45,9 @@ ndbgetval(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, char *buf)
 	}
 	}
 	return 0;
 	return 0;
 }
 }
+
+Ndbtuple*
+ndbgetval(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, char *buf)
+{
+	return ndbgetvalue(db, s, attr, val, rattr, buf, Ndbvlen);
+}

+ 100 - 223
sys/src/libndb/ndbipinfo.c

@@ -1,179 +1,102 @@
 #include <u.h>
 #include <u.h>
 #include <libc.h>
 #include <libc.h>
 #include <bio.h>
 #include <bio.h>
-#include <ip.h>
 #include <ndb.h>
 #include <ndb.h>
+#include <ip.h>
 
 
-typedef struct Attr Attr;
-struct Attr
+enum
 {
 {
-	Attr		*next;
-	int		addronly;
-	char		*attr;
-	Ndbtuple	*first;	
-	Ndbtuple	*last;
-	int		masklen;
+	Ffound=	1<<0,
+	Fignore=1<<1,
+	Faddr=	1<<2,
 };
 };
 
 
-#ifdef DEBUGGING
-static void
-prtuple(char *tag, Ndbtuple *t)
-{
-	print("%s tag\n\t", tag);
-	for(; t != nil; t = t->entry){
-		print("%s=%s ", t->attr, t->val);
-		if(t->entry != t->line){
-			if(t->entry != nil)
-				print("\n\t");
-			else
-				print("\n");
-		}
-	}
-}
-#endif DEBUGGING
+static Ndbtuple*	filter(Ndb *db, Ndbtuple *t, Ndbtuple *f);
+static Ndbtuple*	mkfilter(int argc, char **argv);
+static int		filtercomplete(Ndbtuple *f);
+static Ndbtuple*	toipaddr(Ndb *db, Ndbtuple *t);
+static int		prefixlen(uchar *ip);
+static Ndbtuple*	subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix);
 
 
-/*
- *  reorder the tuple to put x's line first in the entry
- */
+/* make a filter to be used in filter */
 static Ndbtuple*
 static Ndbtuple*
-reorder(Ndbtuple *t, Ndbtuple *x)
+mkfilter(int argc, char **argv)
 {
 {
-	Ndbtuple *nt;
-	Ndbtuple *last, *prev;
-
-	/* if x is first, we're done */
-	if(x == t)
-		return t;
-
-	/* find end of x's line */
-	for(last = x; last->line == last->entry; last = last->line)
-		;
-
-	/* rotate to make this line first */
-	if(last->line != t){
-
-		/* detach this line and everything after it from the entry */
-		for(nt = t; nt->entry != last->line; nt = nt->entry)
-			;
-		nt->entry = nil;
-	
-		/* switch */
-		for(nt = last; nt->entry != nil; nt = nt->entry)
-			;
-		nt->entry = t;
-	}
-
-	/* rotate line to make x first */
-	if(x != last->line){
-
-		/* find entry before x */
-		for(prev = last; prev->line != x; prev = prev->line);
-			;
-
-		/* detach line */
-		nt = last->entry;
-		last->entry = last->line;
+	Ndbtuple *t, *first, *last;
+	char *p;
 
 
-		/* reattach */
-		prev->entry = nt;
+	last = first = nil;
+	while(argc-- > 0){
+		t = ndbnew(0, 0);
+		if(first)
+			last->entry = t;
+		else
+			first = t;
+		last = t;
+		p = *argv++;
+		if(*p == '@'){
+			t->ptr |= Faddr;
+			p++;
+		}
+		strncpy(t->attr, p, sizeof(t->attr)-1);
 	}
 	}
+	return first;
+}
 
 
-	return x;
+/* return true if every pair of filter has been used */
+static int
+filtercomplete(Ndbtuple *f)
+{
+	for(; f; f = f->entry)
+		if((f->ptr & Fignore) == 0)
+			return 0;
+	return 1;
 }
 }
 
 
-/*
- *  lookup an ip addresses
- */
+/* set the attribute of all entries in a tuple */
 static Ndbtuple*
 static Ndbtuple*
-toipaddr(Ndb *db, Ndbtuple *t)
+setattr(Ndbtuple *t, char *attr)
 {
 {
-	Ndbtuple *xt, *nt, **l;
-	char buf[Ndbvlen];
-	Ndbs s;
-	char *attr;
-
-	attr = ipattr(t->val);
-	if(strcmp(attr, "ip") == 0)
-		return t;
-
-	nt = ndbgetval(db, &s, attr, t->val, "ip", buf);
-	if(nt == nil)
-		return 0;
-	nt = reorder(nt, s.t);
-
-	/* throw out non ip twoples */
-	l = &nt;
-	while(*l != nil){
-		xt = *l;
-		if(strcmp(xt->attr, "ip") != 0){
-			/* unlink */
-			*l = xt->entry;
-			xt->entry = nil;
-
-			/* free */
-			ndbfree(xt);
-			continue;
-		}
-		strcpy(xt->attr, t->attr);
-		l = &xt->entry;
-	}
+	Ndbtuple *nt;
 
 
-	ndbfree(t);
-	return nt;
+	for(nt = t; nt; nt = nt->entry)
+		strcpy(nt->attr, attr);
+	return t;
 }
 }
 
 
 /*
 /*
- *  Mine the entry for the desired attributes.  Longer masks
- *  take priority.
+ *  return only the attr/value pairs in t maching the filter, f.
+ *  others are freed.  line structure is preserved.
  */
  */
 static Ndbtuple*
 static Ndbtuple*
-mine(Ndb *db, Ndbtuple *t, Attr *a, int masklen, int *needed)
+filter(Ndb *db, Ndbtuple *t, Ndbtuple *f)
 {
 {
-	Ndbtuple **l, *nt;
-
-	for(; a != nil; a = a->next){
-		for(l = &t; *l != nil;){
-			nt = *l;
-			if(strcmp(a->attr, nt->attr) != 0){
-				l = &nt->entry;
-				continue;
-			}
+	Ndbtuple *nt, *nf, *next;
 
 
-			if(a->first){
-				/* longer masks replace shorter */
-				if(masklen > a->masklen){
-					ndbfree(a->first);
-					a->first = nil;
-					a->last = nil;
-					(*needed)++;
-				} else if(a->masklen > masklen) {
-					l = &nt->entry;
-					continue;
-				}
-			}
+	/* filter out what we don't want */
+	for(nt = t; nt; nt = next){
+		next = nt->entry;
 
 
-			/* unchain tuple from t */
-			*l = nt->entry;
-			nt->entry = nil;
-
-			if(a->addronly)
-				nt = toipaddr(db, nt);
-			if(nt == nil)
-				continue;
-
-			/* chain tuple into the Attr */
-			if(a->last)
-				a->last->entry = nt;
-			else
-				a->first = nt;
-			while(nt->entry)
-				nt = nt->entry;
-			a->last = nt;
-			a->masklen = masklen;
-			(*needed)--;
+		/* look through filter */
+		for(nf = f; nf != nil; nf = nf->entry){
+			if(!(nf->ptr&Fignore) && strcmp(nt->attr, nf->attr) == 0)
+				break;
+		}
+		if(nf == nil){
+			/* remove nt from t */
+			t = ndbdiscard(t, nt);
+		} else {
+			if(nf->ptr & Faddr)
+				t = ndbsubstitute(t, nt, setattr(ndbgetipaddr(db, nt->val), nt->attr));
+			nf->ptr |= Ffound;
 		}
 		}
 	}
 	}
 
 
+	/* remember filter etnries that matched */
+	for(nf = f; nf != nil; nf = nf->entry)
+		if(nf->ptr & Ffound)
+			nf->ptr = (nf->ptr & ~Ffound) | Fignore;
+
 	return t;
 	return t;
 }
 }
 
 
@@ -190,34 +113,35 @@ prefixlen(uchar *ip)
 }
 }
 
 
 /*
 /*
- *  look for all networks whose masks are shorter than lastlen
- *  and whose IP address matches net.
+ *  look through a containing subset
  */
  */
-static void
-subnet(Ndb *db, uchar *net, Attr *a, int prefix, int *needed)
+static Ndbtuple*
+subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix)
 {
 {
 	Ndbs s;
 	Ndbs s;
-	Ndbtuple *t;
+	Ndbtuple *t, *nt;
 	char netstr[Ndbvlen];
 	char netstr[Ndbvlen];
 	char maskstr[Ndbvlen];
 	char maskstr[Ndbvlen];
 	uchar mask[IPaddrlen];
 	uchar mask[IPaddrlen];
 	int masklen;
 	int masklen;
 
 
+	t = nil;
 	sprint(netstr, "%I", net);
 	sprint(netstr, "%I", net);
-	t = ndbsearch(db, &s, "ip", netstr);
-	while(t != nil){
-		if(ndblookval(t, t, "ipnet", maskstr) != nil){
-			if(ndblookval(t, t, "ipmask", maskstr))
+	nt = ndbsearch(db, &s, "ip", netstr);
+	while(nt != nil){
+		if(ndblookval(nt, nt, "ipnet", maskstr) != nil){
+			if(ndblookval(nt, nt, "ipmask", maskstr))
 				parseipmask(mask, maskstr);
 				parseipmask(mask, maskstr);
 			else
 			else
 				ipmove(mask, defmask(net));
 				ipmove(mask, defmask(net));
 			masklen = prefixlen(mask);
 			masklen = prefixlen(mask);
 			if(masklen <= prefix)
 			if(masklen <= prefix)
-				t = mine(db, t, a, masklen, needed);
-		}
-		ndbfree(t);
-		t = ndbsnext(&s, "ip", netstr);
+				t = ndbconcatenate(t, filter(db, nt, f));
+		} else
+			ndbfree(nt);
+		nt = ndbsnext(&s, "ip", netstr);
 	}
 	}
+	return t;
 }
 }
 
 
 /*
 /*
@@ -229,13 +153,9 @@ subnet(Ndb *db, uchar *net, Attr *a, int prefix, int *needed)
 Ndbtuple*
 Ndbtuple*
 ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
 ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
 {
 {
-	Ndbtuple *t, *nt, **lt;
+	Ndbtuple *t, *nt, *f;
 	Ndbs s;
 	Ndbs s;
-	char *p;
-	Attr *a, *list, **l;
-	int i, needed;
 	char ipstr[Ndbvlen];
 	char ipstr[Ndbvlen];
-	uchar ip[IPaddrlen];
 	uchar net[IPaddrlen];
 	uchar net[IPaddrlen];
 	int prefix, smallestprefix;
 	int prefix, smallestprefix;
 	int force;
 	int force;
@@ -245,63 +165,40 @@ ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
 	fmtinstall('M', eipfmt);
 	fmtinstall('M', eipfmt);
 
 
 	/* get needed attributes */
 	/* get needed attributes */
-	needed = 0;
-	l = &list;
-	for(i = 0; i < n; i++){
-		p = *alist++;
-		if(p == nil)
-			break;
-		a = mallocz(sizeof(*a), 1);
-		if(a == nil)
-			break;
-		if(*p == '@'){
-			a->addronly = 1;
-			p++;
-		}
-		a->attr = p;
-		*l = a;
-		l = &(*l)->next;
-		needed++;
-	}
+	f = mkfilter(n, alist);
 
 
 	/*
 	/*
 	 *  first look for a matching entry with an ip address
 	 *  first look for a matching entry with an ip address
 	 */
 	 */
-	t = ndbgetval(db, &s, attr, val, "ip", ipstr);
-	if(t == nil){
+	t = nil;
+	nt = ndbgetval(db, &s, attr, val, "ip", ipstr);
+	if(nt == nil){
 		/* none found, make one up */
 		/* none found, make one up */
 		if(strcmp(attr, "ip") != 0)
 		if(strcmp(attr, "ip") != 0)
 			return nil;
 			return nil;
-		strncpy(ipstr, val, sizeof(ipstr)-1);
-		ip[sizeof(ip)-1] = 0;
-		t = malloc(sizeof(*t));
-		strcpy(t->attr, "ip");
-		strcpy(t->val, ipstr);
+		t = ndbnew("ip", val);
 		t->line = t;
 		t->line = t;
 		t->entry = nil;
 		t->entry = nil;
-		t = mine(db, t, list, 128, &needed);
-		ndbfree(t);
 	} else {
 	} else {
 		/* found one */
 		/* found one */
-		while(t != nil){
-			t = reorder(t, s.t);
-			t = mine(db, t, list, 128, &needed);
-			ndbfree(t);
-			t = ndbsnext(&s, attr, val);
+		while(nt != nil){
+			nt = ndbreorder(nt, s.t);
+			t = ndbconcatenate(t, nt);
+			nt = ndbsnext(&s, attr, val);
 		}
 		}
 	}
 	}
-	parseip(ip, ipstr);
-	ipmove(net, ip);
+	t = filter(db, t, f);
+	parseip(net, ipstr);
 
 
 	/*
 	/*
 	 *  now go through subnets to fill in any missing attributes
 	 *  now go through subnets to fill in any missing attributes
 	 */
 	 */
-	if(isv4(ip)){
+	if(isv4(net)){
 		prefix = 127;
 		prefix = 127;
 		smallestprefix = 100;
 		smallestprefix = 100;
 		force = 0;
 		force = 0;
 	} else {
 	} else {
-		/* in v6, the last 8 bytes have no structure */
+		/* in v6, the last 8 bytes have no structure (we hope) */
 		prefix = 64;
 		prefix = 64;
 		smallestprefix = 2;
 		smallestprefix = 2;
 		memset(net+8, 0, 8);
 		memset(net+8, 0, 8);
@@ -315,35 +212,15 @@ ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
 	 *  complete, we may need to find a trick to speed this up.
 	 *  complete, we may need to find a trick to speed this up.
 	 */
 	 */
 	for(; prefix >= smallestprefix; prefix--){
 	for(; prefix >= smallestprefix; prefix--){
-		if(needed == 0)
+		if(filtercomplete(f))
 			break;
 			break;
 		if(!force && (net[prefix/8] & (1<<(7-(prefix%8)))) == 0)
 		if(!force && (net[prefix/8] & (1<<(7-(prefix%8)))) == 0)
 			continue;
 			continue;
 		force = 0;
 		force = 0;
 		net[prefix/8] &= ~(1<<(7-(prefix%8)));
 		net[prefix/8] &= ~(1<<(7-(prefix%8)));
-		subnet(db, net, list, prefix, &needed);
-	}
-
-	/*
-	 *  chain together the results and free the list
-	 */
-	lt = &t;
-	while(list != nil){
-		a = list;
-		list = a->next;
-		*lt = a->first;
-		if(*lt == nil && strcmp(a->attr, "ipmask") == 0){
-			/* add a default ipmask if we need one */
-			*lt = mallocz(sizeof( Ndbtuple), 1);
-			strcpy((*lt)->attr, "ipmask");
-			snprint((*lt)->val, sizeof((*lt)->val), "%M", defmask(ip));
-		}
-		while(nt = *lt){
-			nt->line = nt->entry;
-			lt = &nt->entry;
-		}
-		free(a);
+		t = ndbconcatenate(t, subnet(db, net, f, prefix));
 	}
 	}
 
 
+	ndbfree(f);
 	return t;
 	return t;
 }
 }

+ 16 - 3
sys/src/libndb/ndblookval.c

@@ -9,14 +9,18 @@
  *  then in the whole entry.
  *  then in the whole entry.
  */
  */
 Ndbtuple*
 Ndbtuple*
-ndblookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
+ndblookvalue(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to, int len)
 {
 {
 	Ndbtuple *nt;
 	Ndbtuple *nt;
 
 
 	/* first look on same line (closer binding) */
 	/* first look on same line (closer binding) */
+	werrstr("");
 	for(nt = line;;){
 	for(nt = line;;){
 		if(strcmp(attr, nt->attr) == 0){
 		if(strcmp(attr, nt->attr) == 0){
-			strncpy(to, nt->val, Ndbvlen);
+			strncpy(to, nt->val, len);
+			to[len-1] = 0;
+			if(strlen(nt->val) >= len)
+				werrstr("return value truncated");
 			return nt;
 			return nt;
 		}
 		}
 		nt = nt->line;
 		nt = nt->line;
@@ -27,8 +31,17 @@ ndblookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
 	/* search whole tuple */
 	/* search whole tuple */
 	for(nt = entry; nt; nt = nt->entry)
 	for(nt = entry; nt; nt = nt->entry)
 		if(strcmp(attr, nt->attr) == 0){
 		if(strcmp(attr, nt->attr) == 0){
-			strncpy(to, nt->val, Ndbvlen);
+			strncpy(to, nt->val, len);
+			to[len-1] = 0;
+			if(strlen(nt->val) >= len)
+				werrstr("return value truncated");
 			return nt;
 			return nt;
 		}
 		}
 	return 0;
 	return 0;
 }
 }
+
+Ndbtuple*
+ndblookval(Ndbtuple *entry, Ndbtuple *line, char *attr, char *to)
+{
+	return ndblookvalue(entry, line, attr, to, Ndbvlen);
+}

+ 53 - 0
sys/src/libndb/ndbreorder.c

@@ -0,0 +1,53 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+
+/*
+ *  reorder the tuple to put x's line first in the entry and x fitst in its line
+ */
+Ndbtuple*
+ndbreorder(Ndbtuple *t, Ndbtuple *x)
+{
+	Ndbtuple *nt;
+	Ndbtuple *last, *prev;
+
+	/* if x is first, we're done */
+	if(x == t)
+		return t;
+
+	/* find end of x's line */
+	for(last = x; last->line == last->entry; last = last->line)
+		;
+
+	/* rotate to make this line first */
+	if(last->line != t){
+
+		/* detach this line and everything after it from the entry */
+		for(nt = t; nt->entry != last->line; nt = nt->entry)
+			;
+		nt->entry = nil;
+	
+		/* switch */
+		for(nt = last; nt->entry != nil; nt = nt->entry)
+			;
+		nt->entry = t;
+	}
+
+	/* rotate line to make x first */
+	if(x != last->line){
+
+		/* find entry before x */
+		for(prev = last; prev->line != x; prev = prev->line);
+			;
+
+		/* detach line */
+		nt = last->entry;
+		last->entry = last->line;
+
+		/* reattach */
+		prev->entry = nt;
+	}
+
+	return x;
+}

+ 39 - 0
sys/src/libndb/ndbsubstitute.c

@@ -0,0 +1,39 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <ndb.h>
+
+/* replace a in t with b, the line structure in b is lost, c'est la vie */
+Ndbtuple*
+ndbsubstitute(Ndbtuple *t, Ndbtuple *a, Ndbtuple *b)
+{
+	Ndbtuple *nt;
+
+	if(a == b)
+		return t;
+	if(b == nil)
+		return ndbdiscard(t, a);
+
+	/* all pointers to a become pointers to b */
+	for(nt = t; nt != nil; nt = nt->entry){
+		if(nt->line == a)
+			nt->line = b;
+		if(nt->entry == a)
+			nt->entry = b;
+	}
+
+	/* end of b chain points to a's successors */
+	for(nt = b; nt->entry; nt = nt->entry){
+		nt->line = nt->entry;
+	}
+	nt->line = a->line;
+	nt->entry = a->entry;
+
+	a->entry = nil;
+	ndbfree(a);
+
+	if(a == t)
+		return b;
+	else
+		return t;
+}