diff options
author | Damien Miller <djm@mindrot.org> | 2001-01-30 09:14:00 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2001-01-30 09:14:00 +1100 |
commit | 5e953217f13b340d8a5fbcd771a1dbaf43354f20 (patch) | |
tree | c138151966b6e8299f4c291cfb1b3ca006e1984c | |
parent | b71eb58ff44f0f2d9c918dc2d17e765269d21c8c (diff) |
- (djm) OpenBSD CVS Sync:
- markus@cvs.openbsd.org 2001/01/29 09:55:37
[channels.c channels.h clientloop.c serverloop.c]
fix select overflow; ok deraadt@ and stevesk@
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | channels.c | 46 | ||||
-rw-r--r-- | channels.h | 13 | ||||
-rw-r--r-- | clientloop.c | 67 | ||||
-rw-r--r-- | serverloop.c | 85 |
5 files changed, 114 insertions, 103 deletions
@@ -1,3 +1,9 @@ | |||
1 | 20000130 | ||
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 | |||
1 | 20000129 | 7 | 20000129 |
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" |
43 | RCSID("$OpenBSD: channels.c,v 1.83 2001/01/24 21:03:50 stevesk Exp $"); | 43 | RCSID("$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 | */ |
87 | static int channel_max_fd_value = 0; | 87 | static 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. */ |
90 | static char *channel_forwarded_auth_socket_name = NULL; | 90 | static 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 | ||
967 | void | 965 | void |
968 | channel_prepare_select(fd_set * readset, fd_set * writeset) | 966 | channel_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 | ||
973 | void | 989 | void |
@@ -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 | ||
981 | void | 997 | void |
982 | channel_output_poll() | 998 | channel_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 | |||
1422 | int | ||
1423 | channel_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 | ||
1430 | int | 1438 | int |
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. */ |
164 | void channel_free(int channel); | 164 | void channel_free(int channel); |
165 | 165 | ||
166 | /* Add any bits relevant to channels in select bitmasks. */ | 166 | /* |
167 | void 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 | */ | ||
170 | void | ||
171 | channel_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 | */ |
189 | void channel_close_all(void); | 193 | void channel_close_all(void); |
190 | 194 | ||
191 | /* Returns the maximum file descriptor number used by the channels. */ | ||
192 | int 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. */ |
195 | int channel_still_open(void); | 196 | int 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" |
62 | RCSID("$OpenBSD: clientloop.c,v 1.45 2001/01/21 19:05:47 markus Exp $"); | 62 | RCSID("$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. */ | |||
124 | static Buffer stderr_buffer; /* Buffer for stderr data. */ | 124 | static Buffer stderr_buffer; /* Buffer for stderr data. */ |
125 | static u_long stdin_bytes, stdout_bytes, stderr_bytes; | 125 | static u_long stdin_bytes, stdout_bytes, stderr_bytes; |
126 | static u_int buffer_high;/* Soft max buffer size. */ | 126 | static u_int buffer_high;/* Soft max buffer size. */ |
127 | static int max_fd; /* Maximum file descriptor number in select(). */ | ||
128 | static int connection_in; /* Connection to server (input). */ | 127 | static int connection_in; /* Connection to server (input). */ |
129 | static int connection_out; /* Connection to server (output). */ | 128 | static int connection_out; /* Connection to server (output). */ |
130 | 129 | ||
@@ -365,45 +364,37 @@ client_check_window_change() | |||
365 | */ | 364 | */ |
366 | 365 | ||
367 | void | 366 | void |
368 | client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) | 367 | client_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) | |||
797 | int | 785 | int |
798 | client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | 786 | client_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" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.42 2001/01/21 19:05:55 markus Exp $"); | 38 | RCSID("$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. */ | |||
73 | static int connection_in; /* Connection to client (input). */ | 73 | static int connection_in; /* Connection to client (input). */ |
74 | static int connection_out; /* Connection to client (output). */ | 74 | static int connection_out; /* Connection to client (output). */ |
75 | static u_int buffer_high;/* "Soft" max buffer size. */ | 75 | static u_int buffer_high;/* "Soft" max buffer size. */ |
76 | static 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 | */ |
182 | void | 181 | void |
183 | wait_until_can_do_something(fd_set * readset, fd_set * writeset, | 182 | wait_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. */ |
190 | retry_select: | 189 | retry_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() | |||
400 | void | 392 | void |
401 | server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | 393 | server_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) | |||
638 | void | 631 | void |
639 | server_loop2(void) | 632 | server_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); |