# HG changeset patch # User Matt Johnston # Date 1093617541 0 # Node ID 2e9d1f29c50fe327227f41a65e0b3c3d474c0777 # Parent 10f4d331978004b710dc09f9debd83eca9155cd8 merge of 50be59810e462f9f44f55e421227d6aa0b31982b and 69b007796063cb5f042be7cca2d479e90db869c3 diff -r 10f4d3319780 -r 2e9d1f29c50f cli-chansession.c --- 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) { diff -r 10f4d3319780 -r 2e9d1f29c50f cli-main.c --- 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); diff -r 10f4d3319780 -r 2e9d1f29c50f common-channel.c --- 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 */ diff -r 10f4d3319780 -r 2e9d1f29c50f dbutil.c --- 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")); +} diff -r 10f4d3319780 -r 2e9d1f29c50f dbutil.h --- 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} diff -r 10f4d3319780 -r 2e9d1f29c50f debug.h --- 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 */ diff -r 10f4d3319780 -r 2e9d1f29c50f svr-agentfwd.c --- 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, diff -r 10f4d3319780 -r 2e9d1f29c50f svr-chansession.c --- 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); } diff -r 10f4d3319780 -r 2e9d1f29c50f svr-x11fwd.c --- 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