summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--channels.c46
-rw-r--r--channels.h13
-rw-r--r--clientloop.c67
-rw-r--r--serverloop.c85
5 files changed, 114 insertions, 103 deletions
diff --git a/ChangeLog b/ChangeLog
index 0bda0f7e6..ce08540bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
120000130
2 - (djm) OpenBSD CVS Sync:
3 - markus@cvs.openbsd.org 2001/01/29 09:55:37
4 [channels.c channels.h clientloop.c serverloop.c]
5 fix select overflow; ok deraadt@ and stevesk@
6
120000129 720000129
2 - (stevesk) sftp-server.c: use %lld vs. %qd 8 - (stevesk) sftp-server.c: use %lld vs. %qd
3 9
diff --git a/channels.c b/channels.c
index 8aaf8c6e6..6aafc3dc3 100644
--- a/channels.c
+++ b/channels.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: channels.c,v 1.83 2001/01/24 21:03:50 stevesk Exp $"); 43RCSID("$OpenBSD: channels.c,v 1.84 2001/01/29 16:55:36 markus Exp $");
44 44
45#include <openssl/rsa.h> 45#include <openssl/rsa.h>
46#include <openssl/dsa.h> 46#include <openssl/dsa.h>
@@ -84,7 +84,7 @@ static int channels_alloc = 0;
84 * Maximum file descriptor value used in any of the channels. This is 84 * Maximum file descriptor value used in any of the channels. This is
85 * updated in channel_allocate. 85 * updated in channel_allocate.
86 */ 86 */
87static int channel_max_fd_value = 0; 87static int channel_max_fd = 0;
88 88
89/* Name and directory of socket for authentication agent forwarding. */ 89/* Name and directory of socket for authentication agent forwarding. */
90static char *channel_forwarded_auth_socket_name = NULL; 90static char *channel_forwarded_auth_socket_name = NULL;
@@ -181,12 +181,10 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
181 int extusage, int nonblock) 181 int extusage, int nonblock)
182{ 182{
183 /* Update the maximum file descriptor value. */ 183 /* Update the maximum file descriptor value. */
184 if (rfd > channel_max_fd_value) 184 channel_max_fd = MAX(channel_max_fd, rfd);
185 channel_max_fd_value = rfd; 185 channel_max_fd = MAX(channel_max_fd, wfd);
186 if (wfd > channel_max_fd_value) 186 channel_max_fd = MAX(channel_max_fd, efd);
187 channel_max_fd_value = wfd; 187
188 if (efd > channel_max_fd_value)
189 channel_max_fd_value = efd;
190 /* XXX set close-on-exec -markus */ 188 /* XXX set close-on-exec -markus */
191 189
192 c->rfd = rfd; 190 c->rfd = rfd;
@@ -965,9 +963,27 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
965} 963}
966 964
967void 965void
968channel_prepare_select(fd_set * readset, fd_set * writeset) 966channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp)
969{ 967{
970 channel_handler(channel_pre, readset, writeset); 968 int n;
969 u_int sz;
970
971 n = MAX(*maxfdp, channel_max_fd);
972
973 sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
974 if (*readsetp == NULL || n > *maxfdp) {
975 if (*readsetp)
976 xfree(*readsetp);
977 if (*writesetp)
978 xfree(*writesetp);
979 *readsetp = xmalloc(sz);
980 *writesetp = xmalloc(sz);
981 *maxfdp = n;
982 }
983 memset(*readsetp, 0, sz);
984 memset(*writesetp, 0, sz);
985
986 channel_handler(channel_pre, *readsetp, *writesetp);
971} 987}
972 988
973void 989void
@@ -976,7 +992,7 @@ channel_after_select(fd_set * readset, fd_set * writeset)
976 channel_handler(channel_post, readset, writeset); 992 channel_handler(channel_post, readset, writeset);
977} 993}
978 994
979/* If there is data to send to the connection, send some of it now. */ 995/* If there is data to send to the connection, enqueue some of it now. */
980 996
981void 997void
982channel_output_poll() 998channel_output_poll()
@@ -1417,14 +1433,6 @@ channel_close_all()
1417 channel_close_fds(&channels[i]); 1433 channel_close_fds(&channels[i]);
1418} 1434}
1419 1435
1420/* Returns the maximum file descriptor number used by the channels. */
1421
1422int
1423channel_max_fd()
1424{
1425 return channel_max_fd_value;
1426}
1427
1428/* Returns true if any channel is still open. */ 1436/* Returns true if any channel is still open. */
1429 1437
1430int 1438int
diff --git a/channels.h b/channels.h
index 45b783fb3..5e030a44b 100644
--- a/channels.h
+++ b/channels.h
@@ -32,7 +32,7 @@
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35/* RCSID("$OpenBSD: channels.h,v 1.24 2000/12/05 20:34:10 markus Exp $"); */ 35/* RCSID("$OpenBSD: channels.h,v 1.25 2001/01/29 16:55:36 markus Exp $"); */
36 36
37#ifndef CHANNELS_H 37#ifndef CHANNELS_H
38#define CHANNELS_H 38#define CHANNELS_H
@@ -163,8 +163,12 @@ int channel_allocate(int type, int sock, char *remote_name);
163/* Free the channel and close its socket. */ 163/* Free the channel and close its socket. */
164void channel_free(int channel); 164void channel_free(int channel);
165 165
166/* Add any bits relevant to channels in select bitmasks. */ 166/*
167void channel_prepare_select(fd_set * readset, fd_set * writeset); 167 * Allocate/update select bitmasks and add any bits relevant to channels in
168 * select bitmasks.
169 */
170void
171channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp);
168 172
169/* 173/*
170 * After select, perform any appropriate operations for channels which have 174 * After select, perform any appropriate operations for channels which have
@@ -188,9 +192,6 @@ void channel_stop_listening(void);
188 */ 192 */
189void channel_close_all(void); 193void channel_close_all(void);
190 194
191/* Returns the maximum file descriptor number used by the channels. */
192int channel_max_fd(void);
193
194/* Returns true if there is still an open channel over the connection. */ 195/* Returns true if there is still an open channel over the connection. */
195int channel_still_open(void); 196int channel_still_open(void);
196 197
diff --git a/clientloop.c b/clientloop.c
index aade8606b..49a943a73 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -59,7 +59,7 @@
59 */ 59 */
60 60
61#include "includes.h" 61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.45 2001/01/21 19:05:47 markus Exp $"); 62RCSID("$OpenBSD: clientloop.c,v 1.46 2001/01/29 16:55:36 markus Exp $");
63 63
64#include "ssh.h" 64#include "ssh.h"
65#include "ssh1.h" 65#include "ssh1.h"
@@ -124,7 +124,6 @@ static Buffer stdout_buffer; /* Buffer for stdout data. */
124static Buffer stderr_buffer; /* Buffer for stderr data. */ 124static Buffer stderr_buffer; /* Buffer for stderr data. */
125static u_long stdin_bytes, stdout_bytes, stderr_bytes; 125static u_long stdin_bytes, stdout_bytes, stderr_bytes;
126static u_int buffer_high;/* Soft max buffer size. */ 126static u_int buffer_high;/* Soft max buffer size. */
127static int max_fd; /* Maximum file descriptor number in select(). */
128static int connection_in; /* Connection to server (input). */ 127static int connection_in; /* Connection to server (input). */
129static int connection_out; /* Connection to server (output). */ 128static int connection_out; /* Connection to server (output). */
130 129
@@ -365,45 +364,37 @@ client_check_window_change()
365 */ 364 */
366 365
367void 366void
368client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) 367client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
368 int *maxfdp)
369{ 369{
370 /* Initialize select masks. */ 370 /* Add any selections by the channel mechanism. */
371 FD_ZERO(readset); 371 channel_prepare_select(readsetp, writesetp, maxfdp);
372 FD_ZERO(writeset);
373 372
374 if (!compat20) { 373 if (!compat20) {
375 /* Read from the connection, unless our buffers are full. */ 374 /* Read from the connection, unless our buffers are full. */
376 if (buffer_len(&stdout_buffer) < buffer_high && 375 if (buffer_len(&stdout_buffer) < buffer_high &&
377 buffer_len(&stderr_buffer) < buffer_high && 376 buffer_len(&stderr_buffer) < buffer_high &&
378 channel_not_very_much_buffered_data()) 377 channel_not_very_much_buffered_data())
379 FD_SET(connection_in, readset); 378 FD_SET(connection_in, *readsetp);
380 /* 379 /*
381 * Read from stdin, unless we have seen EOF or have very much 380 * Read from stdin, unless we have seen EOF or have very much
382 * buffered data to send to the server. 381 * buffered data to send to the server.
383 */ 382 */
384 if (!stdin_eof && packet_not_very_much_data_to_write()) 383 if (!stdin_eof && packet_not_very_much_data_to_write())
385 FD_SET(fileno(stdin), readset); 384 FD_SET(fileno(stdin), *readsetp);
386 385
387 /* Select stdout/stderr if have data in buffer. */ 386 /* Select stdout/stderr if have data in buffer. */
388 if (buffer_len(&stdout_buffer) > 0) 387 if (buffer_len(&stdout_buffer) > 0)
389 FD_SET(fileno(stdout), writeset); 388 FD_SET(fileno(stdout), *writesetp);
390 if (buffer_len(&stderr_buffer) > 0) 389 if (buffer_len(&stderr_buffer) > 0)
391 FD_SET(fileno(stderr), writeset); 390 FD_SET(fileno(stderr), *writesetp);
392 } else { 391 } else {
393 FD_SET(connection_in, readset); 392 FD_SET(connection_in, *readsetp);
394 } 393 }
395 394
396 /* Add any selections by the channel mechanism. */
397 channel_prepare_select(readset, writeset);
398
399 /* Select server connection if have data to write to the server. */ 395 /* Select server connection if have data to write to the server. */
400 if (packet_have_data_to_write()) 396 if (packet_have_data_to_write())
401 FD_SET(connection_out, writeset); 397 FD_SET(connection_out, *writesetp);
402
403/* move UP XXX */
404 /* Update maximum file descriptor number, if appropriate. */
405 if (channel_max_fd() > max_fd)
406 max_fd = channel_max_fd();
407 398
408 /* 399 /*
409 * Wait for something to happen. This will suspend the process until 400 * Wait for something to happen. This will suspend the process until
@@ -414,11 +405,8 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
414 * SSH_MSG_IGNORE packet when the timeout expires. 405 * SSH_MSG_IGNORE packet when the timeout expires.
415 */ 406 */
416 407
417 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) { 408 if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
418 char buf[100]; 409 char buf[100];
419 /* Some systems fail to clear these automatically. */
420 FD_ZERO(readset);
421 FD_ZERO(writeset);
422 if (errno == EINTR) 410 if (errno == EINTR)
423 return; 411 return;
424 /* Note: we might still have data in the buffers. */ 412 /* Note: we might still have data in the buffers. */
@@ -797,6 +785,8 @@ simple_escape_filter(Channel *c, char *buf, int len)
797int 785int
798client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 786client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
799{ 787{
788 fd_set *readset = NULL, *writeset = NULL;
789 int max_fd = 0;
800 double start_time, total_time; 790 double start_time, total_time;
801 int len; 791 int len;
802 char buf[100]; 792 char buf[100];
@@ -813,9 +803,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
813 buffer_high = 64 * 1024; 803 buffer_high = 64 * 1024;
814 connection_in = packet_get_connection_in(); 804 connection_in = packet_get_connection_in();
815 connection_out = packet_get_connection_out(); 805 connection_out = packet_get_connection_out();
816 max_fd = connection_in; 806 max_fd = MAX(connection_in, connection_out);
817 if (connection_out > max_fd) 807
818 max_fd = connection_out; 808 if (!compat20) {
809 max_fd = MAX(max_fd, fileno(stdin));
810 max_fd = MAX(max_fd, fileno(stdout));
811 max_fd = MAX(max_fd, fileno(stderr));
812 }
819 stdin_bytes = 0; 813 stdin_bytes = 0;
820 stdout_bytes = 0; 814 stdout_bytes = 0;
821 stderr_bytes = 0; 815 stderr_bytes = 0;
@@ -849,7 +843,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
849 843
850 /* Main loop of the client for the interactive session mode. */ 844 /* Main loop of the client for the interactive session mode. */
851 while (!quit_pending) { 845 while (!quit_pending) {
852 fd_set readset, writeset;
853 846
854 /* Process buffered packets sent by the server. */ 847 /* Process buffered packets sent by the server. */
855 client_process_buffered_input_packets(); 848 client_process_buffered_input_packets();
@@ -867,7 +860,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
867 client_make_packets_from_stdin_data(); 860 client_make_packets_from_stdin_data();
868 861
869 /* 862 /*
870 * Make packets from buffered channel data, and buffer them 863 * Make packets from buffered channel data, and enqueue them
871 * for sending to the server. 864 * for sending to the server.
872 */ 865 */
873 if (packet_not_very_much_data_to_write()) 866 if (packet_not_very_much_data_to_write())
@@ -886,34 +879,38 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
886 * Wait until we have something to do (something becomes 879 * Wait until we have something to do (something becomes
887 * available on one of the descriptors). 880 * available on one of the descriptors).
888 */ 881 */
889 client_wait_until_can_do_something(&readset, &writeset); 882 client_wait_until_can_do_something(&readset, &writeset, &max_fd);
890 883
891 if (quit_pending) 884 if (quit_pending)
892 break; 885 break;
893 886
894 /* Do channel operations. */ 887 /* Do channel operations. */
895 channel_after_select(&readset, &writeset); 888 channel_after_select(readset, writeset);
896 889
897 /* Buffer input from the connection. */ 890 /* Buffer input from the connection. */
898 client_process_net_input(&readset); 891 client_process_net_input(readset);
899 892
900 if (quit_pending) 893 if (quit_pending)
901 break; 894 break;
902 895
903 if (!compat20) { 896 if (!compat20) {
904 /* Buffer data from stdin */ 897 /* Buffer data from stdin */
905 client_process_input(&readset); 898 client_process_input(readset);
906 /* 899 /*
907 * Process output to stdout and stderr. Output to 900 * Process output to stdout and stderr. Output to
908 * the connection is processed elsewhere (above). 901 * the connection is processed elsewhere (above).
909 */ 902 */
910 client_process_output(&writeset); 903 client_process_output(writeset);
911 } 904 }
912 905
913 /* Send as much buffered packet data as possible to the sender. */ 906 /* Send as much buffered packet data as possible to the sender. */
914 if (FD_ISSET(connection_out, &writeset)) 907 if (FD_ISSET(connection_out, writeset))
915 packet_write_poll(); 908 packet_write_poll();
916 } 909 }
910 if (readset)
911 xfree(readset);
912 if (writeset)
913 xfree(writeset);
917 914
918 /* Terminate the session. */ 915 /* Terminate the session. */
919 916
diff --git a/serverloop.c b/serverloop.c
index a7f8e72b5..bdac6a0d2 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: serverloop.c,v 1.42 2001/01/21 19:05:55 markus Exp $"); 38RCSID("$OpenBSD: serverloop.c,v 1.43 2001/01/29 16:55:37 markus Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "packet.h" 41#include "packet.h"
@@ -73,7 +73,6 @@ static int fderr_eof = 0; /* EOF encountered readung from fderr. */
73static int connection_in; /* Connection to client (input). */ 73static int connection_in; /* Connection to client (input). */
74static int connection_out; /* Connection to client (output). */ 74static int connection_out; /* Connection to client (output). */
75static u_int buffer_high;/* "Soft" max buffer size. */ 75static u_int buffer_high;/* "Soft" max buffer size. */
76static int max_fd; /* Max file descriptor number for select(). */
77 76
78/* 77/*
79 * This SIGCHLD kludge is used to detect when the child exits. The server 78 * This SIGCHLD kludge is used to detect when the child exits. The server
@@ -180,8 +179,8 @@ make_packets_from_stdout_data()
180 * for the duration of the wait (0 = infinite). 179 * for the duration of the wait (0 = infinite).
181 */ 180 */
182void 181void
183wait_until_can_do_something(fd_set * readset, fd_set * writeset, 182wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
184 u_int max_time_milliseconds) 183 u_int max_time_milliseconds)
185{ 184{
186 struct timeval tv, *tvp; 185 struct timeval tv, *tvp;
187 int ret; 186 int ret;
@@ -189,14 +188,13 @@ wait_until_can_do_something(fd_set * readset, fd_set * writeset,
189 /* When select fails we restart from here. */ 188 /* When select fails we restart from here. */
190retry_select: 189retry_select:
191 190
192 /* Initialize select() masks. */ 191 /* Allocate and update select() masks for channel descriptors. */
193 FD_ZERO(readset); 192 channel_prepare_select(readsetp, writesetp, maxfdp);
194 FD_ZERO(writeset);
195 193
196 if (compat20) { 194 if (compat20) {
197 /* wrong: bad condition XXX */ 195 /* wrong: bad condition XXX */
198 if (channel_not_very_much_buffered_data()) 196 if (channel_not_very_much_buffered_data())
199 FD_SET(connection_in, readset); 197 FD_SET(connection_in, *readsetp);
200 } else { 198 } else {
201 /* 199 /*
202 * Read packets from the client unless we have too much 200 * Read packets from the client unless we have too much
@@ -204,37 +202,31 @@ retry_select:
204 */ 202 */
205 if (buffer_len(&stdin_buffer) < buffer_high && 203 if (buffer_len(&stdin_buffer) < buffer_high &&
206 channel_not_very_much_buffered_data()) 204 channel_not_very_much_buffered_data())
207 FD_SET(connection_in, readset); 205 FD_SET(connection_in, *readsetp);
208 /* 206 /*
209 * If there is not too much data already buffered going to 207 * If there is not too much data already buffered going to
210 * the client, try to get some more data from the program. 208 * the client, try to get some more data from the program.
211 */ 209 */
212 if (packet_not_very_much_data_to_write()) { 210 if (packet_not_very_much_data_to_write()) {
213 if (!fdout_eof) 211 if (!fdout_eof)
214 FD_SET(fdout, readset); 212 FD_SET(fdout, *readsetp);
215 if (!fderr_eof) 213 if (!fderr_eof)
216 FD_SET(fderr, readset); 214 FD_SET(fderr, *readsetp);
217 } 215 }
218 /* 216 /*
219 * If we have buffered data, try to write some of that data 217 * If we have buffered data, try to write some of that data
220 * to the program. 218 * to the program.
221 */ 219 */
222 if (fdin != -1 && buffer_len(&stdin_buffer) > 0) 220 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
223 FD_SET(fdin, writeset); 221 FD_SET(fdin, *writesetp);
224 } 222 }
225 /* Set masks for channel descriptors. */
226 channel_prepare_select(readset, writeset);
227 223
228 /* 224 /*
229 * If we have buffered packet data going to the client, mark that 225 * If we have buffered packet data going to the client, mark that
230 * descriptor. 226 * descriptor.
231 */ 227 */
232 if (packet_have_data_to_write()) 228 if (packet_have_data_to_write())
233 FD_SET(connection_out, writeset); 229 FD_SET(connection_out, *writesetp);
234
235 /* Update the maximum descriptor number if appropriate. */
236 if (channel_max_fd() > max_fd)
237 max_fd = channel_max_fd();
238 230
239 /* 231 /*
240 * If child has terminated and there is enough buffer space to read 232 * If child has terminated and there is enough buffer space to read
@@ -255,7 +247,7 @@ retry_select:
255 debug2("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds); 247 debug2("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
256 248
257 /* Wait for something to happen, or the timeout to expire. */ 249 /* Wait for something to happen, or the timeout to expire. */
258 ret = select(max_fd + 1, readset, writeset, NULL, tvp); 250 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
259 251
260 if (ret < 0) { 252 if (ret < 0) {
261 if (errno != EINTR) 253 if (errno != EINTR)
@@ -400,7 +392,8 @@ process_buffered_input_packets()
400void 392void
401server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 393server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
402{ 394{
403 fd_set readset, writeset; 395 fd_set *readset = NULL, *writeset = NULL;
396 int max_fd;
404 int wait_status; /* Status returned by wait(). */ 397 int wait_status; /* Status returned by wait(). */
405 pid_t wait_pid; /* pid returned by wait(). */ 398 pid_t wait_pid; /* pid returned by wait(). */
406 int waiting_termination = 0; /* Have displayed waiting close message. */ 399 int waiting_termination = 0; /* Have displayed waiting close message. */
@@ -441,15 +434,11 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
441 buffer_high = 64 * 1024; 434 buffer_high = 64 * 1024;
442 435
443 /* Initialize max_fd to the maximum of the known file descriptors. */ 436 /* Initialize max_fd to the maximum of the known file descriptors. */
444 max_fd = fdin; 437 max_fd = MAX(fdin, fdout);
445 if (fdout > max_fd) 438 if (fderr != -1)
446 max_fd = fdout; 439 max_fd = MAX(max_fd, fderr);
447 if (fderr != -1 && fderr > max_fd) 440 max_fd = MAX(max_fd, connection_in);
448 max_fd = fderr; 441 max_fd = MAX(max_fd, connection_out);
449 if (connection_in > max_fd)
450 max_fd = connection_in;
451 if (connection_out > max_fd)
452 max_fd = connection_out;
453 442
454 /* Initialize Initialize buffers. */ 443 /* Initialize Initialize buffers. */
455 buffer_init(&stdin_buffer); 444 buffer_init(&stdin_buffer);
@@ -536,18 +525,22 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
536 } 525 }
537 } 526 }
538 /* Sleep in select() until we can do something. */ 527 /* Sleep in select() until we can do something. */
539 wait_until_can_do_something(&readset, &writeset, 528 wait_until_can_do_something(&readset, &writeset, &max_fd,
540 max_time_milliseconds); 529 max_time_milliseconds);
541 530
542 /* Process any channel events. */ 531 /* Process any channel events. */
543 channel_after_select(&readset, &writeset); 532 channel_after_select(readset, writeset);
544 533
545 /* Process input from the client and from program stdout/stderr. */ 534 /* Process input from the client and from program stdout/stderr. */
546 process_input(&readset); 535 process_input(readset);
547 536
548 /* Process output to the client and to program stdin. */ 537 /* Process output to the client and to program stdin. */
549 process_output(&writeset); 538 process_output(writeset);
550 } 539 }
540 if (readset)
541 xfree(readset);
542 if (writeset)
543 xfree(writeset);
551 544
552 /* Cleanup and termination code. */ 545 /* Cleanup and termination code. */
553 546
@@ -638,7 +631,8 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
638void 631void
639server_loop2(void) 632server_loop2(void)
640{ 633{
641 fd_set readset, writeset; 634 fd_set *readset = NULL, *writeset = NULL;
635 int max_fd;
642 int had_channel = 0; 636 int had_channel = 0;
643 int status; 637 int status;
644 pid_t pid; 638 pid_t pid;
@@ -650,9 +644,9 @@ server_loop2(void)
650 child_terminated = 0; 644 child_terminated = 0;
651 connection_in = packet_get_connection_in(); 645 connection_in = packet_get_connection_in();
652 connection_out = packet_get_connection_out(); 646 connection_out = packet_get_connection_out();
653 max_fd = connection_in; 647
654 if (connection_out > max_fd) 648 max_fd = MAX(connection_in, connection_out);
655 max_fd = connection_out; 649
656 server_init_dispatch(); 650 server_init_dispatch();
657 651
658 for (;;) { 652 for (;;) {
@@ -665,16 +659,21 @@ server_loop2(void)
665 } 659 }
666 if (packet_not_very_much_data_to_write()) 660 if (packet_not_very_much_data_to_write())
667 channel_output_poll(); 661 channel_output_poll();
668 wait_until_can_do_something(&readset, &writeset, 0); 662 wait_until_can_do_something(&readset, &writeset, &max_fd, 0);
669 if (child_terminated) { 663 if (child_terminated) {
670 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 664 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
671 session_close_by_pid(pid, status); 665 session_close_by_pid(pid, status);
672 child_terminated = 0; 666 child_terminated = 0;
673 } 667 }
674 channel_after_select(&readset, &writeset); 668 channel_after_select(readset, writeset);
675 process_input(&readset); 669 process_input(readset);
676 process_output(&writeset); 670 process_output(writeset);
677 } 671 }
672 if (readset)
673 xfree(readset);
674 if (writeset)
675 xfree(writeset);
676
678 signal(SIGCHLD, SIG_DFL); 677 signal(SIGCHLD, SIG_DFL);
679 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 678 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
680 session_close_by_pid(pid, status); 679 session_close_by_pid(pid, status);