changes from erik quanstrom
diff --git a/src/cmd/ndb/dnarea.c b/src/cmd/ndb/dnarea.c
index 9f0338b..05c9d00 100755
--- a/src/cmd/ndb/dnarea.c
+++ b/src/cmd/ndb/dnarea.c
@@ -91,12 +91,15 @@
  *  this entails running a command 'zonerefreshprogram'.  This could
  *  copy over databases from elsewhere or just do a zone transfer.
  */
-/* XXX WRONG - can't use fork and exec */
 void
 refresh_areas(Area *s)
 {
-	int pid;
 	Waitmsg *w;
+	char *argv[3];
+	
+	argv[0] = zonerefreshprogram;
+	argv[1] = "XXX";
+	argv[2] = nil;
 
 	for(; s != nil; s = s->next){
 		if(!s->needrefresh)
@@ -107,26 +110,9 @@
 			continue;
 		}
 
-		switch(pid = fork()){
-		case -1:
-			break;
-		case 0:
-			execl(zonerefreshprogram, "zonerefresh", s->soarr->owner->name, 0);
-			threadexitsall(0);
-			break;
-		default:
-			for(;;){
-				w = wait();
-				if(w == nil)
-					break;
-				if(w->pid == pid){
-					if(w->msg == nil || *w->msg == 0)
-						s->needrefresh = 0;
-					free(w);
-					break;
-				}
-				free(w);
-			}
-		}
+		argv[1] = s->soarr->owner->name;
+		w = runproc(argv[0], argv, 0);
+		free(w);
 	}
 }
+
diff --git a/src/cmd/ndb/dns.c b/src/cmd/ndb/dns.c
index de9cd96..e91d6ca 100755
--- a/src/cmd/ndb/dns.c
+++ b/src/cmd/ndb/dns.c
@@ -61,7 +61,6 @@
 	Mfile	*inuse;		/* active mfile's */
 } mfalloc;
 
-int	haveip;
 int	mfd[2];
 int	debug;
 int traceactivity;
@@ -97,7 +96,7 @@
 void	freejob(Job*);
 void	setext(char*, int, char*);
 
-char *portname = "domain";
+char 	*portname = "domain";
 char	*logfile = "dns";
 char	*dbfile;
 char	mntpt[Maxpath];
@@ -106,7 +105,7 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-dnrstT] [-a maxage] [-f ndb-file] [-p port] [-x service] [-z zoneprog]\n", argv0);
+	fprint(2, "usage: dns [-dnrstT] [-a maxage] [-f ndb-file] [-p port] [-x service] [-z zoneprog]\n");
 	threadexitsall("usage");
 }
 
@@ -134,7 +133,7 @@
 		resolver = 1;
 		break;
 	case 's':
-		serveudp = 1;	/* serve network */
+		serveudp = 1;
 		cachedb = 1;
 		break;
 	case 'T':
@@ -165,7 +164,7 @@
 	/* start syslog before we fork */
 	fmtinstall('F', fcallfmt);
 	dninit();
-	if(!haveip && myipaddr(ipaddr, mntpt) < 0)
+	if(myipaddr(ipaddr, mntpt) < 0)
 		sysfatal("can't read my ip address");
 
 	syslog(0, logfile, "starting dns on %I", ipaddr);
@@ -350,7 +349,7 @@
 
 	for(;;){
 		n = read9pmsg(mfd[0], mdata, sizeof mdata);
-		if(n<=0){
+		if(n <= 0){
 			syslog(0, logfile, "error reading mntpt: %r");
 			break;
 		}
@@ -665,7 +664,10 @@
 		dndump(dumpfile);
 		goto send;
 	} else if(strncmp(p, "dump ", 5) == 0){
-		dndump(p+5);
+		if(*(p+5))
+			dndump(p+5);
+		else
+			err = "bad filename";
 		goto send;
 	} else if(strcmp(p, "refresh")==0){
 		needrefresh = 1;
diff --git a/src/cmd/ndb/dns.h b/src/cmd/ndb/dns.h
index 4f8d06a..1d19db7 100755
--- a/src/cmd/ndb/dns.h
+++ b/src/cmd/ndb/dns.h
@@ -381,6 +381,10 @@
 extern void	mallocsanity(void*);
 extern void	lasthist(void*, int, ulong);
 
+/* runproc.c */
+extern Waitmsg*	runproc(char*, char**, int);
+extern Waitmsg*	runprocfd(char*, char**, int[3]);
+
 extern int	debug;
 extern int	traceactivity;
 extern char	*trace;
diff --git a/src/cmd/ndb/dnsdebug.c b/src/cmd/ndb/dnsdebug.c
index cc84d4e..6e3a49f 100755
--- a/src/cmd/ndb/dnsdebug.c
+++ b/src/cmd/ndb/dnsdebug.c
@@ -33,6 +33,7 @@
 char	*dbfile;
 char	mntpt[Maxpath];
 char	*zonerefreshprogram;
+char *portname = "domain";
 
 int prettyrrfmt(Fmt*);
 void preloadserveraddrs(void);
@@ -47,7 +48,6 @@
 	fprint(2, "usage: dnsdebug -rxf [-p port] [query ...]\n");
 	threadexitsall("usage");
 }
-char *portname = "domain";
 
 void
 threadmain(int argc, char *argv[])
@@ -60,9 +60,6 @@
 	strcpy(mntpt, "/net");
 
 	ARGBEGIN{
-	case 'p':	/* XXX */
-		portname = EARGF(usage());
-		break;
 	case 'r':
 		resolver = 1;
 		break;
@@ -73,6 +70,9 @@
 	case 'f':
 		dbfile = EARGF(usage());
 		break;
+	case 'p':
+		portname = EARGF(usage());
+		break;
 	default:
 		usage();
 	}ARGEND
diff --git a/src/cmd/ndb/dntcpserver.c b/src/cmd/ndb/dntcpserver.c
index 4ae787a..38e3ce7 100644
--- a/src/cmd/ndb/dntcpserver.c
+++ b/src/cmd/ndb/dntcpserver.c
@@ -35,10 +35,10 @@
 	if (lfd < 0)
 		return -1;
 	*fd = accept(lfd, ldir);
-	n = -1;
-	if (*fd < 0)
+	if (*fd >= 0)
 		n = readmsg(*fd, buf, max);
-	//close(fd);
+	else
+		n = -1;
 	close(lfd);
 	return n;
 }
@@ -181,7 +181,7 @@
 void
 tcpproc(void *v)
 {
-	int len;
+	int len, rv;
 	Request req;
 	DNSmsg reqmsg, repmsg;
 	char *err;
@@ -191,7 +191,7 @@
 	NetConnInfo *caller;
 
 	rfd = -1;
-	fd = (int)v;
+	fd = (uintptr)v;
 	caller = 0;
 	/* loop on requests */
 	for(;; putactivity()){
@@ -244,12 +244,13 @@
 					break;
 			} else {
 				dnserver(&reqmsg, &repmsg, &req);
-				if(reply(rfd, &repmsg, &req, caller) < 0)
-					break;
+				rv = reply(rfd, &repmsg, &req, caller);
 				rrfreelist(repmsg.qd);
 				rrfreelist(repmsg.an);
 				rrfreelist(repmsg.ns);
 				rrfreelist(repmsg.ar);
+				if(rv < 0)
+					break;
 			}
 		}
 
@@ -264,8 +265,6 @@
 	Maxactivetcp = 4,
 };
 
-extern char *portname;
-
 static int
 tcpannounce(char *mntpt)
 {
@@ -283,12 +282,10 @@
 dntcpserver(void *v)
 {
 	int i, fd;
-	char *mntpt;
 
-	mntpt = v;
-	while((fd = tcpannounce(mntpt)) < 0)
+	while((fd = tcpannounce(v)) < 0)
 		sleep(5*1000);
 
 	for(i=0; i<Maxactivetcp; i++)
-		proccreate(tcpproc, (void*)fd, STACK);
+		proccreate(tcpproc, (void*)(uintptr)fd, STACK);
 }
diff --git a/src/cmd/ndb/dnudpserver.c b/src/cmd/ndb/dnudpserver.c
index d3eaf95..9e4ac4a 100755
--- a/src/cmd/ndb/dnudpserver.c
+++ b/src/cmd/ndb/dnudpserver.c
@@ -72,15 +72,13 @@
 	char tname[32];
 	Udphdr *uh;
 
-	fd = (int)v;
+	fd = (uintptr)v;
 
 	/* loop on requests */
 	for(;; putactivity()){
 		memset(&repmsg, 0, sizeof(repmsg));
 		memset(&reqmsg, 0, sizeof(reqmsg));
-		alarm(60*1000);
 		len = udpread(fd, (Udphdr*)buf, buf+Udphdrsize, sizeof(buf)-Udphdrsize);
-		alarm(0);
 		if(len <= 0)
 			continue;
 		uh = (Udphdr*)buf;
@@ -161,7 +159,7 @@
 
 	snprint(buf, sizeof buf, "udp!*!%s", portname);
 	if((fd=announce(buf, buf)) < 0)
-		warning("can't announce on dns udp port");
+		warning("announce %s: %r", buf);
 	return fd;
 }
 
@@ -202,6 +200,6 @@
 	while((fd = udpannounce(v)) < 0)
 		sleep(5*1000);
 	for(i=0; i<Maxactive; i++)
-		proccreate(udpproc, (void*)fd, STACK);
+		proccreate(udpproc, (void*)(uintptr)fd, STACK);
 }
 
diff --git a/src/cmd/ndb/mkfile b/src/cmd/ndb/mkfile
index e45f7a1..7adcef2 100644
--- a/src/cmd/ndb/mkfile
+++ b/src/cmd/ndb/mkfile
@@ -24,6 +24,7 @@
 	dnresolve.$O\
 	dnserver.$O\
 	dntcpserver.$O\
+	runproc.$O\
 
 $DNSOFILES dns.$O dnstcp.$O dnsdebug.$O: dns.h
 
diff --git a/src/cmd/ndb/runproc.c b/src/cmd/ndb/runproc.c
new file mode 100644
index 0000000..db344f9
--- /dev/null
+++ b/src/cmd/ndb/runproc.c
@@ -0,0 +1,37 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+#include <ndb.h>
+#include "dns.h"
+
+Waitmsg*
+runprocfd(char *file, char **v, int fd[3])
+{
+	int pid, i;
+
+	threadwaitchan();
+	pid = threadspawn(fd, file, v);
+	for(i=0; i<3; i++)
+		close(fd[i]);
+	if(pid < 0)
+		return nil;
+	return procwait(pid);
+}
+
+Waitmsg*
+runproc(char *file, char **v, int devnull)
+{
+	int fd[3], i;
+
+	if(devnull){
+		fd[0] = open("/dev/null", ORDWR);
+		fd[1] = dup(1, fd[0]);
+		fd[2] = dup(2, fd[0]);
+	}else{
+		for(i=0; i<3; i++)
+			fd[i] = dup(i, -1);
+	}
+	return runprocfd(file, v, fd);
+}
+