- markus@cvs.openbsd.org 2008/05/09 16:21:13
     [channels.h clientloop.c nchan.c serverloop.c]
     unbreak
        ssh -2 localhost od /bin/ls | true
     ignoring SIGPIPE by adding a new channel message (EOW) that signals
     the peer that we're not interested in any data it might send.
     fixes bz #85; discussion, debugging and ok djm@
diff --git a/ChangeLog b/ChangeLog
index fd75c34..7d9b0f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -133,6 +133,13 @@
      for channels with both in- and output closed, since the channel
      will go away before we call select();
      report, lots of debugging help and ok djm@
+   - markus@cvs.openbsd.org 2008/05/09 16:21:13
+     [channels.h clientloop.c nchan.c serverloop.c]
+     unbreak
+        ssh -2 localhost od /bin/ls | true
+     ignoring SIGPIPE by adding a new channel message (EOW) that signals
+     the peer that we're not interested in any data it might send.
+     fixes bz #85; discussion, debugging and ok djm@
 
 20080403
  - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile-
@@ -3993,4 +4000,4 @@
    OpenServer 6 and add osr5bigcrypt support so when someone migrates
    passwords between UnixWare and OpenServer they will still work. OK dtucker@
 
-$Id: ChangeLog,v 1.4929 2008/05/19 06:05:41 djm Exp $
+$Id: ChangeLog,v 1.4930 2008/05/19 06:06:47 djm Exp $
diff --git a/channels.h b/channels.h
index d4ac24a..ec2435d 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.91 2008/05/09 04:55:56 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.92 2008/05/09 16:21:13 markus Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -267,6 +267,7 @@
 /* channel events */
 
 void	 chan_rcvd_oclose(Channel *);
+void	 chan_rcvd_eow(Channel *);	/* SSH2-only */
 void	 chan_read_failed(Channel *);
 void	 chan_ibuf_empty(Channel *);
 
diff --git a/clientloop.c b/clientloop.c
index c87aa5a..584afb7 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.192 2008/05/09 14:18:44 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.193 2008/05/09 16:21:13 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1666,6 +1666,9 @@
 		error("client_input_channel_req: request for channel -1");
 	} else if ((c = channel_lookup(id)) == NULL) {
 		error("client_input_channel_req: channel %d: unknown channel", id);
+	} else if (strcmp(rtype, "eow@openssh.com") == 0) {
+		packet_check_eom();
+		chan_rcvd_eow(c);
 	} else if (strcmp(rtype, "exit-status") == 0) {
 		exitval = packet_get_int();
 		if (id == session_ident) {
diff --git a/nchan.c b/nchan.c
index 0d0fadd..a4a456e 100644
--- a/nchan.c
+++ b/nchan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nchan.c,v 1.58 2008/05/08 12:02:23 djm Exp $ */
+/* $OpenBSD: nchan.c,v 1.59 2008/05/09 16:21:13 markus Exp $ */
 /*
  * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  *
@@ -78,6 +78,7 @@
 static void	chan_send_oclose1(Channel *);
 static void	chan_send_close2(Channel *);
 static void	chan_send_eof2(Channel *);
+static void	chan_send_eow2(Channel *);
 
 /* helper */
 static void	chan_shutdown_write(Channel *);
@@ -306,6 +307,17 @@
 		break;
 	}
 }
+void
+chan_rcvd_eow(Channel *c)
+{
+	debug2("channel %d: rcvd eow", c->self);
+	switch (c->istate) {
+	case CHAN_INPUT_OPEN:
+		chan_shutdown_read(c);
+		chan_set_istate(c, CHAN_INPUT_CLOSED);
+		break;
+	}
+}
 static void
 chan_rcvd_eof2(Channel *c)
 {
@@ -322,6 +334,7 @@
 	case CHAN_OUTPUT_OPEN:
 	case CHAN_OUTPUT_WAIT_DRAIN:
 		chan_shutdown_write(c);
+		chan_send_eow2(c);
 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
 		break;
 	default:
@@ -364,6 +377,21 @@
 		c->flags |= CHAN_CLOSE_SENT;
 	}
 }
+static void
+chan_send_eow2(Channel *c)
+{
+	debug2("channel %d: send eow", c->self);
+	if (c->ostate == CHAN_OUTPUT_CLOSED) {
+		error("channel %d: must not sent eow on closed output",
+		    c->self);
+		return;
+	}
+	packet_start(SSH2_MSG_CHANNEL_REQUEST);
+	packet_put_int(c->remote_id);
+	packet_put_cstring("eow@openssh.com");
+	packet_put_char(0);
+	packet_send();
+}
 
 /* shared */
 
diff --git a/serverloop.c b/serverloop.c
index 2142f38..6bc140f 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.150 2008/05/09 04:55:56 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.151 2008/05/09 16:21:13 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1160,7 +1160,10 @@
 	if ((c = channel_lookup(id)) == NULL)
 		packet_disconnect("server_input_channel_req: "
 		    "unknown channel %d", id);
-	if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN)
+	if (!strcmp(rtype, "eow@openssh.com")) {
+		packet_check_eom();
+		chan_rcvd_eow(c);
+	} else if (c->type == SSH_CHANNEL_LARVAL || c->type == SSH_CHANNEL_OPEN)
 		success = session_input_channel_req(c, rtype);
 	if (reply) {
 		packet_start(success ?