changeset 109:2e9d1f29c50f

merge of 50be59810e462f9f44f55e421227d6aa0b31982b and 69b007796063cb5f042be7cca2d479e90db869c3
author Matt Johnston <matt@ucc.asn.au>
date Fri, 27 Aug 2004 14:39:01 +0000
parents 10f4d3319780
children 9b7fc71039cd
files cli-chansession.c cli-main.c common-channel.c dbutil.c dbutil.h debug.h svr-agentfwd.c svr-chansession.c svr-x11fwd.c
diffstat 9 files changed, 65 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/cli-chansession.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/cli-chansession.c	Fri Aug 27 14:39:01 2004 +0000
@@ -341,8 +341,14 @@
 
 
 	channel->infd = STDOUT_FILENO;
+	setnonblocking(STDOUT_FILENO);
+
 	channel->outfd = STDIN_FILENO;
+	setnonblocking(STDIN_FILENO);
+
 	channel->errfd = STDERR_FILENO;
+	setnonblocking(STDERR_FILENO);
+
 	channel->extrabuf = cbuf_new(RECV_MAXWINDOW);
 
 	if (cli_opts.wantpty) {
--- a/cli-main.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/cli-main.c	Fri Aug 27 14:39:01 2004 +0000
@@ -52,6 +52,10 @@
 	TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
 				cli_opts.remotehost, cli_opts.remoteport));
 
+	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+		dropbear_exit("signal() error");
+	}
+
 	sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 
 			0, &error);
 
--- a/common-channel.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/common-channel.c	Fri Aug 27 14:39:01 2004 +0000
@@ -192,7 +192,8 @@
 		}
 
 		/* read from program/pipe stderr */
-		if (channel->errfd >= 0 && FD_ISSET(channel->errfd, readfd)) {
+		if (channel->extrabuf == NULL &&
+				channel->errfd >= 0 && FD_ISSET(channel->errfd, readfd)) {
 				send_msg_channel_data(channel, 1, SSH_EXTENDED_DATA_STDERR);
 		}
 
@@ -245,6 +246,14 @@
 /* do all the EOF/close type stuff checking for a channel */
 static void checkclose(struct Channel *channel) {
 
+	TRACE(("checkclose: infd %d, outfd %d, errfd %d, sentclosed %d, recvclosed %d", 
+				channel->infd, channel->outfd,
+				channel->errfd, channel->sentclosed, channel->recvclosed));
+	TRACE(("writebuf %d extrabuf %s extrabuf %d",
+				cbuf_getused(channel->writebuf),
+				channel->writebuf,
+				channel->writebuf ? 0 : cbuf_getused(channel->extrabuf)));
+
 	if (!channel->sentclosed) {
 
 		/* check for exited - currently only used for server sessions,
@@ -257,13 +266,13 @@
 
 		if (!channel->senteof
 			&& channel->outfd == FD_CLOSED 
-			&& channel->errfd == FD_CLOSED) {
+			&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
 			send_msg_channel_eof(channel);
 		}
 
 		if (channel->infd == FD_CLOSED
-				&& channel->outfd == FD_CLOSED
-				&& channel->errfd == FD_CLOSED) {
+			&& channel->outfd == FD_CLOSED
+			&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
 			send_msg_channel_close(channel);
 		}
 	}
@@ -383,9 +392,8 @@
 	if (fd == channel->infd && len == maxlen && channel->recveof) { 
 		/* Check if we're closing up */
 		closeinfd(channel);
+		TRACE(("leave writechannel: recveof set"));
 		return;
-		TRACE(("leave writechannel: recveof set"));
-
 	}
 
 	/* Window adjust handling */
@@ -433,7 +441,9 @@
 
 		/* For checking FD status (ie closure etc) - we don't actually
 		 * read data from infd */
-		TRACE(("infd = %d, outfd %d, bufused %d", channel->infd, channel->outfd,
+		TRACE(("infd = %d, outfd %d, errfd %d, bufused %d", 
+					channel->infd, channel->outfd,
+					channel->errfd,
 					cbuf_getused(channel->writebuf) ));
 		if (channel->infd >= 0 && channel->infd != channel->outfd) {
 			FD_SET(channel->infd, readfd);
@@ -534,9 +544,8 @@
 	 * yet (ie they were shutdown etc */
 	close(channel->infd);
 	close(channel->outfd);
-	if (channel->errfd >= 0) {
-		close(channel->errfd);
-	}
+	close(channel->errfd);
+
 	channel->typedata = NULL;
 
 	deletechannel(channel);
@@ -619,16 +628,19 @@
 	}
 
 	/* read the data */
+	TRACE(("maxlen %d", maxlen));
 	buf = buf_new(maxlen);
+	TRACE(("buf pos %d data %x", buf->pos, buf->data));
 	len = read(fd, buf_getwriteptr(buf, maxlen), maxlen);
 	if (len <= 0) {
 		/* on error/eof, send eof */
 		if (len == 0 || errno != EINTR) {
 			closeoutfd(channel, fd);
-			TRACE(("leave send_msg_channel_data: read err %d", channel->index));
 		}
 		buf_free(buf);
 		buf = NULL;
+		TRACE(("leave send_msg_channel_data: read err or EOF for fd %d", 
+					channel->index));
 		return;
 	}
 	buf_incrlen(buf, len);
@@ -714,7 +726,7 @@
 		len -= buflen;
 	}
 
-	assert(channel->recvwindow > datalen);
+	assert(channel->recvwindow >= datalen);
 	channel->recvwindow -= datalen;
 	assert(channel->recvwindow <= RECV_MAXWINDOW);
 
@@ -927,10 +939,7 @@
 	}
 
 	/* set fd non-blocking */
-	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-		TRACE(("leave send_msg_channel_open_init() - FAILED in fcntl()"));
-		return DROPBEAR_FAILURE;
-	}
+	setnonblocking(fd);
 
 	chan->infd = chan->outfd = fd;
 	ses.maxfd = MAX(ses.maxfd, fd);
@@ -1034,15 +1043,19 @@
 		closein = closeout = 1;
 	}
 
-	if (closeout && fd == channel->errfd) {
-		channel->errfd = FD_CLOSED;
-	}
 	if (closeout && fd == channel->outfd) {
 		channel->outfd = FD_CLOSED;
 	}
+	if (closeout && (channel->extrabuf == NULL) && (fd == channel->errfd)) {
+		channel->errfd = FD_CLOSED;
+	}
+
 	if (closein && fd == channel->infd) {
 		channel->infd = FD_CLOSED;
 	}
+	if (closein && (channel->extrabuf != NULL) && (fd == channel->errfd)) {
+		channel->errfd = FD_CLOSED;
+	}
 }
 
 #endif /* USING_LISTENERS */
--- a/dbutil.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/dbutil.c	Fri Aug 27 14:39:01 2004 +0000
@@ -595,3 +595,13 @@
 	}
 }
 
+
+void setnonblocking(int fd) {
+
+	TRACE(("setnonblocking: %d", fd));
+
+	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
+		dropbear_exit("Couldn't set nonblocking");
+	}
+	TRACE(("leave setnonblocking"));
+}
--- a/dbutil.h	Thu Aug 26 13:16:40 2004 +0000
+++ b/dbutil.h	Fri Aug 27 14:39:01 2004 +0000
@@ -61,6 +61,7 @@
 #define m_free(X) __m_free(X); (X) = NULL;
 void __m_free(void* ptr);
 void m_burn(void* data, unsigned int len);
+void setnonblocking(int fd);
 
 /* Used to force mp_ints to be initialised */
 #define DEF_MP_INT(X) mp_int X = {0, 0, 0, NULL}
--- a/debug.h	Thu Aug 26 13:16:40 2004 +0000
+++ b/debug.h	Fri Aug 27 14:39:01 2004 +0000
@@ -33,12 +33,13 @@
  * etc. Don't use this normally, it might cause problems */
 /* #define DEBUG_VALGRIND */
 
-/* Define this to compile in trace debugging printf()s. You'll need to 
- * run programs with "-v" to turn this on.
+/* Define this to compile in trace debugging printf()s. 
+ * You'll need to run programs with "-v" to turn this on.
+ *
  * Caution: Don't use this in an unfriendly environment (ie unfirewalled),
  * since the printing may not sanitise strings etc. This will add a reasonable
  * amount to your executable size. */
- #define DEBUG_TRACE 
+/* #define DEBUG_TRACE */
 
 /* All functions writing to the cleartext payload buffer call
  * CHECKCLEARTOWRITE() before writing. This is only really useful if you're
@@ -49,6 +50,7 @@
 /* Define this, compile with -pg and set GMON_OUT_PREFIX=gmon to get gmon
  * output when Dropbear forks. This will allow it gprof to be used.
  * It's useful to run dropbear -F, so you don't fork as much */
+/* (This is Linux specific) */
 /*#define DEBUG_FORKGPROF*/
 
 /* A couple of flags, not usually useful, and mightn't do anything */
--- a/svr-agentfwd.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/svr-agentfwd.c	Fri Aug 27 14:39:01 2004 +0000
@@ -73,9 +73,7 @@
 	}
 
 	/* set non-blocking */
-	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-		goto fail;
-	}
+	setnonblocking(fd);
 
 	/* pass if off to listener */
 	chansess->agentlistener = new_listener( &fd, 1, 0, chansess, 
--- a/svr-chansession.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/svr-chansession.c	Fri Aug 27 14:39:01 2004 +0000
@@ -651,11 +651,10 @@
 		ses.maxfd = MAX(ses.maxfd, channel->outfd);
 		ses.maxfd = MAX(ses.maxfd, channel->errfd);
 
-		if ((fcntl(channel->outfd, F_SETFL, O_NONBLOCK) < 0) ||
-			(fcntl(channel->infd, F_SETFL, O_NONBLOCK) < 0) ||
-			(fcntl(channel->errfd, F_SETFL, O_NONBLOCK) < 0)) {
-			dropbear_exit("Couldn't set nonblocking");
-		}
+		setnonblocking(channel->outfd);
+		setnonblocking(channel->infd);
+		setnonblocking(channel->errfd);
+
 	}
 #undef FDIN
 #undef FDOUT
@@ -761,9 +760,7 @@
 		/* don't need to set stderr here */
 		ses.maxfd = MAX(ses.maxfd, chansess->master);
 
-		if (fcntl(chansess->master, F_SETFL, O_NONBLOCK) < 0) {
-			dropbear_exit("Couldn't set nonblocking");
-		}
+		setnonblocking(chansess->master);
 
 	}
 
--- a/svr-x11fwd.c	Thu Aug 26 13:16:40 2004 +0000
+++ b/svr-x11fwd.c	Fri Aug 27 14:39:01 2004 +0000
@@ -75,9 +75,7 @@
 	}
 
 	/* set non-blocking */
-	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
-		goto fail;
-	}
+	setnonblocking(fd);
 
 	/* listener code will handle the socket now.
 	 * No cleanup handler needed, since listener_remove only happens