9term manages to turn off echo at the right times under SunOS ?
diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c
index 2923dee..852e7da 100644
--- a/src/cmd/9term/9term.c
+++ b/src/cmd/9term/9term.c
@@ -124,6 +124,7 @@
 int		clickmsec;	/* time of last click */
 uint		clickq0;	/* point of last click */
 int		rcfd;
+int		sfd;	/* slave fd, to get/set terminal mode */
 int		rcpid;
 int		maxtab;
 int		use9wm;
@@ -223,7 +224,7 @@
 
 	mc = initmouse(nil, screen);
 	kc = initkeyboard(nil);
-	rcpid = rcstart(argc, argv, &rcfd);
+	rcpid = rcstart(argc, argv, &rcfd, &sfd);
 	hoststart();
 	plumbstart();
 
@@ -270,6 +271,10 @@
 		postnote(PNGROUP, rcpid, "hangup");
 		noted(NDFLT);
 	}
+	if(strstr(msg, "child")){
+		/* bug: do better */
+		exits(0);
+	}
 	noted(NDFLT);
 }
 
@@ -284,6 +289,8 @@
 	i = 0;
 	for(;;){
 		/* Let typing have a go -- maybe there's a rubout waiting. */
+		yield();
+
 		i = 1-i;	/* toggle */
 		n = threadread(rcfd, rcbuf[i].data, sizeof rcbuf[i].data);
 		if(n <= 0){
@@ -828,6 +835,7 @@
 		return;
 	}
 
+	rawon = israw(sfd);
 	if(rawon && t.q0==t.nr){
 		addraw(&r, 1);
 		consread();
@@ -837,6 +845,7 @@
 	if(r==ESC || (holdon && r==0x7F)){	/* toggle hold */
 		holdon = !holdon;
 		drawhold(holdon);
+	//	replaceintegerproperty("_9WM_HOLD_MODE", 1, 32, holdon);
 		if(!holdon)
 			consread();
 		if(r==ESC)
@@ -918,6 +927,7 @@
 	if(holdon)
 		return 0;
 
+	rawon = israw(sfd);
 	if(rawon) 
 		return t.nraw != 0;
 
@@ -936,6 +946,7 @@
 {
 	char buf[8000], *p;
 	int c, width, n;
+	int echo;
 
 	for(;;) {
 		if(!consready())
@@ -954,13 +965,18 @@
 			c = *p;
 			p += width;
 			n -= width;
+			rawon = israw(sfd);
 			if(!rawon && (c == '\n' || c == '\004' || c == '\x7F'))
 				break;
 		}
 		/* take out control-d when not doing a zero length write */
 		n = p-buf;
+		if(0) fprint(2, "write buf\n");
+		/* temporarily disable echo for buf. sensitive to race? Axel. */
+	//	echo = setecho(sfd, 0);
 		if(write(rcfd, buf, n) < 0)
 			exits(0);
+	//	setecho(sfd, echo);
 /*		mallocstats(); */
 	}
 }
@@ -1242,6 +1258,7 @@
 {
 	Rune *rbuf;
 
+	rawon = israw(sfd);
 	if(rawon && t.q0==t.nr){
 		addraw(r, n);
 		return;
diff --git a/src/cmd/9term/Darwin.c b/src/cmd/9term/Darwin.c
index 38212d6..8fff13f 100644
--- a/src/cmd/9term/Darwin.c
+++ b/src/cmd/9term/Darwin.c
@@ -133,3 +133,15 @@
 
 }
 
+int
+israw(int fd)
+{
+	return 0;
+}
+
+int
+setecho(int fd, int on)
+{
+	return 0;
+}
+
diff --git a/src/cmd/9term/FreeBSD.c b/src/cmd/9term/FreeBSD.c
index 89f7c7b..75a97a4 100644
--- a/src/cmd/9term/FreeBSD.c
+++ b/src/cmd/9term/FreeBSD.c
@@ -44,3 +44,15 @@
 	ows = ws;
 }
 
+int
+israw(int fd)
+{
+	return 0;
+}
+
+int
+setecho(int fd, int on)
+{
+	return 0;
+}
+
diff --git a/src/cmd/9term/Linux.c b/src/cmd/9term/Linux.c
index 872417e..823344c 100644
--- a/src/cmd/9term/Linux.c
+++ b/src/cmd/9term/Linux.c
@@ -44,3 +44,20 @@
 	ows = ws;
 }
 
+
+int
+israw(int fd)
+{
+	return 0;
+/*
+	if(tcgetattr(fd, &ttmode) < 0)
+		fprint(2, "tcgetattr: %r\n");
+	return !(ttmode.c_lflag&(ICANON|ECHO));
+*/
+}
+
+int
+setecho(int fd, int on)
+{
+	return 0;
+}
diff --git a/src/cmd/9term/OpenBSD.c b/src/cmd/9term/OpenBSD.c
index 7f18bb4..e4753de 100644
--- a/src/cmd/9term/OpenBSD.c
+++ b/src/cmd/9term/OpenBSD.c
@@ -44,3 +44,16 @@
 		fprint(2, "ioctl: %r\n");
 	ows = ws;
 }
+
+int
+israw(int fd)
+{
+	return 0;
+}
+
+int
+setecho(int fd, int on)
+{
+	return 0;
+}
+
diff --git a/src/cmd/9term/SunOS.c b/src/cmd/9term/SunOS.c
index d9104ed..2522834 100644
--- a/src/cmd/9term/SunOS.c
+++ b/src/cmd/9term/SunOS.c
@@ -1,6 +1,6 @@
 #include <u.h>
 #include <termios.h>
-#include <sys/termios.h>
+#include <stropts.h>
 #include <libc.h>
 #include "term.h"
 
@@ -11,8 +11,17 @@
 	if ((grantpt(fd[1]) < 0) || (unlockpt(fd[1]) < 0))
 		return -1;
 	fchmod(fd[1], 0622);
+
 	strcpy(slave, ptsname(fd[1]));
-	fd[0] = open(slave, OREAD);
+
+	fd[0] = open(slave, ORDWR);
+	if(fd[0] < 0)
+		sysfatal("open %s: %r\n", slave);
+
+	/* set up the right streams modules for a tty */
+	ioctl(fd[0], I_PUSH, "ptem");        /* push ptem */
+	ioctl(fd[0], I_PUSH, "ldterm");      /* push ldterm */
+
 	return 0;
 }
 
@@ -42,7 +51,76 @@
 	ws.ws_ypixel = dy;
 	if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
 	if(ioctl(rcfd, TIOCSWINSZ, &ws) < 0)
-		fprint(2, "ioctl: %r\n");
+		fprint(2, "ioctl TIOCSWINSZ: %r\n");
 	ows = ws;
 }
 
+/*
+ * israw has been inspired by Matty Farrow's 9term.
+ * The code below is probably a gross simplification --
+ * for the few cases tested it seems to be enough.
+ * However, for example, Matty's code also looks at ISIG,
+ * whereas, we do not (yet?). Axel.
+ *
+ *Note: I guess only the get/set terminal mode attribute
+ * code needs to be here; the logic around it could be
+ * elswhere (9term.c) - but if the code below is split,
+ * the question is what a nice interface would be. Axel.
+ */
+
+static struct termios ttmode;
+
+int
+israw(int fd)
+{
+	int e, c, i;
+
+	tcgetattr(fd, &ttmode);
+	c = (ttmode.c_lflag & ICANON) ? 1 : 0;
+	e = (ttmode.c_lflag & ECHO) ? 1 : 0;
+	i = (ttmode.c_lflag & ISIG) ? 1 : 0;
+
+	if(0) fprint(2, "israw: icanon=%d echo=%d isig=%d\n", c, e, i);
+
+	return !c || !e ;
+}
+
+
+int
+setecho(int fd, int on)
+{
+	int e, c, i;
+	int oldecho;
+
+	tcgetattr(fd, &ttmode);
+	c = (ttmode.c_lflag & ICANON) ? 1 : 0;
+	e = (ttmode.c_lflag & ECHO) ? 1 : 0;
+	i = (ttmode.c_lflag & ISIG) ? 1 : 0;
+
+	if(0) fprint(2, "setecho(%d) pre: icanon=%d echo=%d isig=%d\n", on, c, e, i);
+
+	oldecho = e;
+
+	if (oldecho == on)
+		return  oldecho;
+
+	if (on) {
+		ttmode.c_lflag |= ECHO;
+		tcsetattr(fd, TCSANOW, &ttmode);
+	} else {
+		ttmode.c_lflag &= ~ECHO;
+		tcsetattr(fd, TCSANOW, &ttmode);
+	}
+
+	if (0){
+		tcgetattr(fd, &ttmode);
+		c = (ttmode.c_lflag & ICANON) ? 1 : 0;
+		e =  (ttmode.c_lflag & ECHO) ? 1 : 0;
+		i = (ttmode.c_lflag & ISIG) ? 1 : 0;
+
+		fprint(2, "setecho(%d) post: icanon=%d echo=%d isig=%d\n", on, c, e, i);
+	}
+
+	return oldecho;
+}
+
diff --git a/src/cmd/9term/rcstart.c b/src/cmd/9term/rcstart.c
index ec168e9..499c591 100644
--- a/src/cmd/9term/rcstart.c
+++ b/src/cmd/9term/rcstart.c
@@ -1,11 +1,21 @@
 #include <u.h>
 #include <libc.h>
+#if 0
+#include <sys/wait.h>
+#endif
+#include <signal.h>
 #include "term.h"
 
+/*
+ * Somehow we no longer automatically exit
+ * when the shell exits; hence the SIGCHLD stuff.
+ * Something that can be fixed? Axel.
+ */
+static int pid;
+
 int
-rcstart(int argc, char **argv, int *pfd)
+rcstart(int argc, char **argv, int *pfd, int *tfd)
 {
-	int pid;
 	int fd[2];
 	char *xargv[3];
 	char slave[256];
@@ -27,7 +37,6 @@
 	if(getpts(fd, slave) < 0)
 		sysfatal("getpts: %r\n");
 
-
 	switch(pid = fork()) {
 	case 0:
 		putenv("TERM", "9term");
@@ -44,8 +53,11 @@
 		sysfatal("proc failed: %r");
 		break;
 	}
-	close(fd[0]);
 	*pfd = fd[1];
+	if(tfd)
+		*tfd = fd[0];
+	else
+		close(fd[0]);
 	return pid;
 }
 
diff --git a/src/cmd/9term/term.h b/src/cmd/9term/term.h
index a608b7e..c35ff4a 100644
--- a/src/cmd/9term/term.h
+++ b/src/cmd/9term/term.h
@@ -2,4 +2,6 @@
 extern int childpty(int[], char*);
 extern void updatewinsize(int, int, int, int);
 extern int rcfd;
-extern int rcstart(int, char*[], int*);
+extern int rcstart(int, char*[], int*, int*);
+extern int israw(int);
+extern int setecho(int, int);
diff --git a/src/cmd/9term/win.c b/src/cmd/9term/win.c
index d5dbef2..0e1fd8a 100644
--- a/src/cmd/9term/win.c
+++ b/src/cmd/9term/win.c
@@ -161,7 +161,7 @@
 
 	cwait = threadwaitchan();
 	threadcreate(waitthread, nil, STACK);
-	pid = rcstart(argc, argv, &rcfd);
+	pid = rcstart(argc, argv, &rcfd, nil);
 	if(pid == -1)
 		sysfatal("exec failed");