summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c1524
1 files changed, 747 insertions, 777 deletions
diff --git a/clientloop.c b/clientloop.c
index 8e8d7627d..c49346c2c 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,21 +1,21 @@
1/* 1/*
2 2 *
3clientloop.c 3 * clientloop.c
4 4 *
5Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Author: Tatu Ylonen <ylo@cs.hut.fi>
6 6 *
7Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8 All rights reserved 8 * All rights reserved
9 9 *
10 10 *
11Created: Sat Sep 23 12:23:57 1995 ylo 11 * Created: Sat Sep 23 12:23:57 1995 ylo
12 12 *
13The main loop for the interactive session (client side). 13 * The main loop for the interactive session (client side).
14 14 *
15*/ 15 */
16 16
17#include "includes.h" 17#include "includes.h"
18RCSID("$Id: clientloop.c,v 1.4 1999/11/21 02:23:53 damien Exp $"); 18RCSID("$Id: clientloop.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
19 19
20#include "xmalloc.h" 20#include "xmalloc.h"
21#include "ssh.h" 21#include "ssh.h"
@@ -49,292 +49,294 @@ static int in_raw_mode = 0;
49static int in_non_blocking_mode = 0; 49static int in_non_blocking_mode = 0;
50 50
51/* Common data for the client loop code. */ 51/* Common data for the client loop code. */
52static int escape_pending; /* Last character was the escape character */ 52static int escape_pending; /* Last character was the escape character */
53static int last_was_cr; /* Last character was a newline. */ 53static int last_was_cr; /* Last character was a newline. */
54static int exit_status; /* Used to store the exit status of the command. */ 54static int exit_status; /* Used to store the exit status of the command. */
55static int stdin_eof; /* EOF has been encountered on standard error. */ 55static int stdin_eof; /* EOF has been encountered on standard error. */
56static Buffer stdin_buffer; /* Buffer for stdin data. */ 56static Buffer stdin_buffer; /* Buffer for stdin data. */
57static Buffer stdout_buffer; /* Buffer for stdout data. */ 57static Buffer stdout_buffer; /* Buffer for stdout data. */
58static Buffer stderr_buffer; /* Buffer for stderr data. */ 58static Buffer stderr_buffer; /* Buffer for stderr data. */
59static unsigned int buffer_high; /* Soft max buffer size. */ 59static unsigned int buffer_high;/* Soft max buffer size. */
60static int max_fd; /* Maximum file descriptor number in select(). */ 60static int max_fd; /* Maximum file descriptor number in select(). */
61static int connection_in; /* Connection to server (input). */ 61static int connection_in; /* Connection to server (input). */
62static int connection_out; /* Connection to server (output). */ 62static int connection_out; /* Connection to server (output). */
63static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; 63static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
64static int quit_pending; /* Set to non-zero to quit the client loop. */ 64static int quit_pending; /* Set to non-zero to quit the client loop. */
65static int escape_char; /* Escape character. */ 65static int escape_char; /* Escape character. */
66 66
67/* Returns the user\'s terminal to normal mode if it had been put in raw 67/* Returns the user\'s terminal to normal mode if it had been put in raw
68 mode. */ 68 mode. */
69 69
70void leave_raw_mode() 70void
71leave_raw_mode()
71{ 72{
72 if (!in_raw_mode) 73 if (!in_raw_mode)
73 return; 74 return;
74 in_raw_mode = 0; 75 in_raw_mode = 0;
75 if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0) 76 if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
76 perror("tcsetattr"); 77 perror("tcsetattr");
77 78
78 fatal_remove_cleanup((void (*)(void *))leave_raw_mode, NULL); 79 fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL);
79} 80}
80 81
81/* Puts the user\'s terminal in raw mode. */ 82/* Puts the user\'s terminal in raw mode. */
82 83
83void enter_raw_mode() 84void
85enter_raw_mode()
84{ 86{
85 struct termios tio; 87 struct termios tio;
86 88
87 if (tcgetattr(fileno(stdin), &tio) < 0) 89 if (tcgetattr(fileno(stdin), &tio) < 0)
88 perror("tcgetattr"); 90 perror("tcgetattr");
89 saved_tio = tio; 91 saved_tio = tio;
90 tio.c_iflag |= IGNPAR; 92 tio.c_iflag |= IGNPAR;
91 tio.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF); 93 tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
92 tio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL); 94 tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
93#ifdef IEXTEN 95#ifdef IEXTEN
94 tio.c_lflag &= ~IEXTEN; 96 tio.c_lflag &= ~IEXTEN;
95#endif /* IEXTEN */ 97#endif /* IEXTEN */
96 tio.c_oflag &= ~OPOST; 98 tio.c_oflag &= ~OPOST;
97 tio.c_cc[VMIN] = 1; 99 tio.c_cc[VMIN] = 1;
98 tio.c_cc[VTIME] = 0; 100 tio.c_cc[VTIME] = 0;
99 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) 101 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
100 perror("tcsetattr"); 102 perror("tcsetattr");
101 in_raw_mode = 1; 103 in_raw_mode = 1;
102 104
103 fatal_add_cleanup((void (*)(void *))leave_raw_mode, NULL); 105 fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL);
104} 106}
105
106/* Puts stdin terminal in non-blocking mode. */
107 107
108/* Restores stdin to blocking mode. */ 108/* Restores stdin to blocking mode. */
109 109
110void leave_non_blocking() 110void
111leave_non_blocking()
111{ 112{
112 if (in_non_blocking_mode) 113 if (in_non_blocking_mode) {
113 { 114 (void) fcntl(fileno(stdin), F_SETFL, 0);
114 (void)fcntl(fileno(stdin), F_SETFL, 0); 115 in_non_blocking_mode = 0;
115 in_non_blocking_mode = 0; 116 fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
116 fatal_remove_cleanup((void (*)(void *))leave_non_blocking, NULL); 117 }
117 }
118} 118}
119 119
120void enter_non_blocking() 120/* Puts stdin terminal in non-blocking mode. */
121
122void
123enter_non_blocking()
121{ 124{
122 in_non_blocking_mode = 1; 125 in_non_blocking_mode = 1;
123 (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); 126 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
124 fatal_add_cleanup((void (*)(void *))leave_non_blocking, NULL); 127 fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
125} 128}
126 129
127/* Signal handler for the window change signal (SIGWINCH). This just 130/* Signal handler for the window change signal (SIGWINCH). This just
128 sets a flag indicating that the window has changed. */ 131 sets a flag indicating that the window has changed. */
129 132
130void window_change_handler(int sig) 133void
134window_change_handler(int sig)
131{ 135{
132 received_window_change_signal = 1; 136 received_window_change_signal = 1;
133 signal(SIGWINCH, window_change_handler); 137 signal(SIGWINCH, window_change_handler);
134} 138}
135 139
136/* Signal handler for signals that cause the program to terminate. These 140/* Signal handler for signals that cause the program to terminate. These
137 signals must be trapped to restore terminal modes. */ 141 signals must be trapped to restore terminal modes. */
138 142
139void signal_handler(int sig) 143void
144signal_handler(int sig)
140{ 145{
141 if (in_raw_mode) 146 if (in_raw_mode)
142 leave_raw_mode(); 147 leave_raw_mode();
143 if (in_non_blocking_mode) 148 if (in_non_blocking_mode)
144 leave_non_blocking(); 149 leave_non_blocking();
145 channel_stop_listening(); 150 channel_stop_listening();
146 packet_close(); 151 packet_close();
147 fatal("Killed by signal %d.", sig); 152 fatal("Killed by signal %d.", sig);
148} 153}
149 154
150/* Returns current time in seconds from Jan 1, 1970 with the maximum available 155/* Returns current time in seconds from Jan 1, 1970 with the maximum available
151 resolution. */ 156 resolution. */
152 157
153double get_current_time() 158double
159get_current_time()
154{ 160{
155 struct timeval tv; 161 struct timeval tv;
156 gettimeofday(&tv, NULL); 162 gettimeofday(&tv, NULL);
157 return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; 163 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
158} 164}
159 165
160/* This is called when the interactive is entered. This checks if there 166/* This is called when the interactive is entered. This checks if there
161 is an EOF coming on stdin. We must check this explicitly, as select() 167 is an EOF coming on stdin. We must check this explicitly, as select()
162 does not appear to wake up when redirecting from /dev/null. */ 168 does not appear to wake up when redirecting from /dev/null. */
163 169
164void client_check_initial_eof_on_stdin() 170void
171client_check_initial_eof_on_stdin()
165{ 172{
166 int len; 173 int len;
167 char buf[1]; 174 char buf[1];
168 175
169 /* If standard input is to be "redirected from /dev/null", we simply 176 /* If standard input is to be "redirected from /dev/null", we
170 mark that we have seen an EOF and send an EOF message to the server. 177 simply mark that we have seen an EOF and send an EOF message to
171 Otherwise, we try to read a single character; it appears that for some 178 the server. Otherwise, we try to read a single character; it
172 files, such /dev/null, select() never wakes up for read for this 179 appears that for some files, such /dev/null, select() never
173 descriptor, which means that we never get EOF. This way we will get 180 wakes up for read for this descriptor, which means that we
174 the EOF if stdin comes from /dev/null or similar. */ 181 never get EOF. This way we will get the EOF if stdin comes
175 if (stdin_null_flag) 182 from /dev/null or similar. */
176 { 183 if (stdin_null_flag) {
177 /* Fake EOF on stdin. */ 184 /* Fake EOF on stdin. */
178 debug("Sending eof."); 185 debug("Sending eof.");
179 stdin_eof = 1; 186 stdin_eof = 1;
180 packet_start(SSH_CMSG_EOF); 187 packet_start(SSH_CMSG_EOF);
181 packet_send(); 188 packet_send();
182 } 189 } else {
183 else 190 /* Enter non-blocking mode for stdin. */
184 { 191 enter_non_blocking();
185 /* Enter non-blocking mode for stdin. */ 192
186 enter_non_blocking(); 193 /* Check for immediate EOF on stdin. */
187 194 len = read(fileno(stdin), buf, 1);
188 /* Check for immediate EOF on stdin. */ 195 if (len == 0) {
189 len = read(fileno(stdin), buf, 1); 196 /* EOF. Record that we have seen it and send EOF
190 if (len == 0) 197 to server. */
191 { 198 debug("Sending eof.");
192 /* EOF. Record that we have seen it and send EOF to server. */ 199 stdin_eof = 1;
193 debug("Sending eof."); 200 packet_start(SSH_CMSG_EOF);
194 stdin_eof = 1; 201 packet_send();
195 packet_start(SSH_CMSG_EOF); 202 } else if (len > 0) {
196 packet_send(); 203 /* Got data. We must store the data in the
204 buffer, and also process it as an escape
205 character if appropriate. */
206 if ((unsigned char) buf[0] == escape_char)
207 escape_pending = 1;
208 else {
209 buffer_append(&stdin_buffer, buf, 1);
210 stdin_bytes += 1;
211 }
212 }
213 /* Leave non-blocking mode. */
214 leave_non_blocking();
197 } 215 }
198 else
199 if (len > 0)
200 {
201 /* Got data. We must store the data in the buffer, and also
202 process it as an escape character if appropriate. */
203 if ((unsigned char)buf[0] == escape_char)
204 escape_pending = 1;
205 else
206 {
207 buffer_append(&stdin_buffer, buf, 1);
208 stdin_bytes += 1;
209 }
210 }
211
212 /* Leave non-blocking mode. */
213 leave_non_blocking();
214 }
215} 216}
216 217
217/* Get packets from the connection input buffer, and process them as long 218/* Get packets from the connection input buffer, and process them as long
218 as there are packets available. */ 219 as there are packets available. */
219 220
220void client_process_buffered_input_packets() 221void
222client_process_buffered_input_packets()
221{ 223{
222 int type; 224 int type;
223 char *data; 225 char *data;
224 unsigned int data_len; 226 unsigned int data_len;
225 int payload_len; 227 int payload_len;
226 228
227 /* Process any buffered packets from the server. */ 229 /* Process any buffered packets from the server. */
228 while (!quit_pending && (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) 230 while (!quit_pending &&
229 { 231 (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
230 switch (type) 232 switch (type) {
231 { 233
232 234 case SSH_SMSG_STDOUT_DATA:
233 case SSH_SMSG_STDOUT_DATA: 235 data = packet_get_string(&data_len);
234 data = packet_get_string(&data_len); 236 packet_integrity_check(payload_len, 4 + data_len, type);
235 packet_integrity_check(payload_len, 4 + data_len, type); 237 buffer_append(&stdout_buffer, data, data_len);
236 buffer_append(&stdout_buffer, data, data_len); 238 stdout_bytes += data_len;
237 stdout_bytes += data_len; 239 memset(data, 0, data_len);
238 memset(data, 0, data_len); 240 xfree(data);
239 xfree(data); 241 break;
240 break; 242
241 243 case SSH_SMSG_STDERR_DATA:
242 case SSH_SMSG_STDERR_DATA: 244 data = packet_get_string(&data_len);
243 data = packet_get_string(&data_len); 245 packet_integrity_check(payload_len, 4 + data_len, type);
244 packet_integrity_check(payload_len, 4 + data_len, type); 246 buffer_append(&stderr_buffer, data, data_len);
245 buffer_append(&stderr_buffer, data, data_len); 247 stdout_bytes += data_len;
246 stdout_bytes += data_len; 248 memset(data, 0, data_len);
247 memset(data, 0, data_len); 249 xfree(data);
248 xfree(data); 250 break;
249 break; 251
250 252 case SSH_SMSG_EXITSTATUS:
251 case SSH_SMSG_EXITSTATUS: 253 packet_integrity_check(payload_len, 4, type);
252 packet_integrity_check(payload_len, 4, type); 254 exit_status = packet_get_int();
253 exit_status = packet_get_int(); 255 /* Acknowledge the exit. */
254 /* Acknowledge the exit. */ 256 packet_start(SSH_CMSG_EXIT_CONFIRMATION);
255 packet_start(SSH_CMSG_EXIT_CONFIRMATION); 257 packet_send();
256 packet_send(); 258 /* Must wait for packet to be sent since we are
257 /* Must wait for packet to be sent since we are exiting the 259 exiting the loop. */
258 loop. */ 260 packet_write_wait();
259 packet_write_wait(); 261 /* Flag that we want to exit. */
260 /* Flag that we want to exit. */ 262 quit_pending = 1;
261 quit_pending = 1; 263 break;
262 break; 264
263 265 case SSH_SMSG_X11_OPEN:
264 case SSH_SMSG_X11_OPEN: 266 x11_input_open(payload_len);
265 x11_input_open(payload_len); 267 break;
266 break; 268
267 269 case SSH_MSG_PORT_OPEN:
268 case SSH_MSG_PORT_OPEN: 270 channel_input_port_open(payload_len);
269 channel_input_port_open(payload_len); 271 break;
270 break; 272
271 273 case SSH_SMSG_AGENT_OPEN:
272 case SSH_SMSG_AGENT_OPEN: 274 packet_integrity_check(payload_len, 4, type);
273 packet_integrity_check(payload_len, 4, type); 275 auth_input_open_request();
274 auth_input_open_request(); 276 break;
275 break; 277
276 278 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
277 case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: 279 packet_integrity_check(payload_len, 4 + 4, type);
278 packet_integrity_check(payload_len, 4 + 4, type); 280 channel_input_open_confirmation();
279 channel_input_open_confirmation(); 281 break;
280 break; 282
281 283 case SSH_MSG_CHANNEL_OPEN_FAILURE:
282 case SSH_MSG_CHANNEL_OPEN_FAILURE: 284 packet_integrity_check(payload_len, 4, type);
283 packet_integrity_check(payload_len, 4, type); 285 channel_input_open_failure();
284 channel_input_open_failure(); 286 break;
285 break; 287
286 288 case SSH_MSG_CHANNEL_DATA:
287 case SSH_MSG_CHANNEL_DATA: 289 channel_input_data(payload_len);
288 channel_input_data(payload_len); 290 break;
289 break; 291
290 292 case SSH_MSG_CHANNEL_CLOSE:
291 case SSH_MSG_CHANNEL_CLOSE: 293 packet_integrity_check(payload_len, 4, type);
292 packet_integrity_check(payload_len, 4, type); 294 channel_input_close();
293 channel_input_close(); 295 break;
294 break; 296
295 297 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
296 case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION: 298 packet_integrity_check(payload_len, 4, type);
297 packet_integrity_check(payload_len, 4, type); 299 channel_input_close_confirmation();
298 channel_input_close_confirmation(); 300 break;
299 break; 301
300 302 default:
301 default: 303 /* Any unknown packets received during the actual
302 /* Any unknown packets received during the actual session 304 session cause the session to terminate. This
303 cause the session to terminate. This is intended to make 305 is intended to make debugging easier since no
304 debugging easier since no confirmations are sent. Any 306 confirmations are sent. Any compatible
305 compatible protocol extensions must be negotiated during 307 protocol extensions must be negotiated during
306 the preparatory phase. */ 308 the preparatory phase. */
307 packet_disconnect("Protocol error during session: type %d", 309 packet_disconnect("Protocol error during session: type %d",
308 type); 310 type);
311 }
309 } 312 }
310 }
311} 313}
312 314
313/* Make packets from buffered stdin data, and buffer them for sending to 315/* Make packets from buffered stdin data, and buffer them for sending to
314 the connection. */ 316 the connection. */
315 317
316void client_make_packets_from_stdin_data() 318void
319client_make_packets_from_stdin_data()
317{ 320{
318 unsigned int len; 321 unsigned int len;
319 322
320 /* Send buffered stdin data to the server. */ 323 /* Send buffered stdin data to the server. */
321 while (buffer_len(&stdin_buffer) > 0 && 324 while (buffer_len(&stdin_buffer) > 0 &&
322 packet_not_very_much_data_to_write()) 325 packet_not_very_much_data_to_write()) {
323 { 326 len = buffer_len(&stdin_buffer);
324 len = buffer_len(&stdin_buffer); 327 /* Keep the packets at reasonable size. */
325 if (len > packet_get_maxsize()) 328 if (len > packet_get_maxsize())
326 len = packet_get_maxsize(); /* Keep the packets at reasonable size. */ 329 len = packet_get_maxsize();
327 packet_start(SSH_CMSG_STDIN_DATA); 330 packet_start(SSH_CMSG_STDIN_DATA);
328 packet_put_string(buffer_ptr(&stdin_buffer), len); 331 packet_put_string(buffer_ptr(&stdin_buffer), len);
329 packet_send(); 332 packet_send();
330 buffer_consume(&stdin_buffer, len); 333 buffer_consume(&stdin_buffer, len);
331 /* If we have a pending EOF, send it now. */ 334 /* If we have a pending EOF, send it now. */
332 if (stdin_eof && buffer_len(&stdin_buffer) == 0) 335 if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
333 { 336 packet_start(SSH_CMSG_EOF);
334 packet_start(SSH_CMSG_EOF); 337 packet_send();
335 packet_send(); 338 }
336 } 339 }
337 }
338} 340}
339 341
340/* Checks if the client window has changed, and sends a packet about it to 342/* Checks if the client window has changed, and sends a packet about it to
@@ -342,303 +344,286 @@ void client_make_packets_from_stdin_data()
342 interrupt on Unix); this just checks the flag and sends a message if 344 interrupt on Unix); this just checks the flag and sends a message if
343 appropriate. */ 345 appropriate. */
344 346
345void client_check_window_change() 347void
348client_check_window_change()
346{ 349{
347 /* Send possible window change message to the server. */ 350 /* Send possible window change message to the server. */
348 if (received_window_change_signal) 351 if (received_window_change_signal) {
349 { 352 struct winsize ws;
350 struct winsize ws; 353
351 354 /* Clear the window change indicator. */
352 /* Clear the window change indicator. */ 355 received_window_change_signal = 0;
353 received_window_change_signal = 0; 356
354 357 /* Read new window size. */
355 /* Read new window size. */ 358 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) {
356 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) 359 /* Successful, send the packet now. */
357 { 360 packet_start(SSH_CMSG_WINDOW_SIZE);
358 /* Successful, send the packet now. */ 361 packet_put_int(ws.ws_row);
359 packet_start(SSH_CMSG_WINDOW_SIZE); 362 packet_put_int(ws.ws_col);
360 packet_put_int(ws.ws_row); 363 packet_put_int(ws.ws_xpixel);
361 packet_put_int(ws.ws_col); 364 packet_put_int(ws.ws_ypixel);
362 packet_put_int(ws.ws_xpixel); 365 packet_send();
363 packet_put_int(ws.ws_ypixel); 366 }
364 packet_send();
365 } 367 }
366 }
367} 368}
368 369
369/* Waits until the client can do something (some data becomes available on 370/* Waits until the client can do something (some data becomes available on
370 one of the file descriptors). */ 371 one of the file descriptors). */
371 372
372void client_wait_until_can_do_something(fd_set *readset, fd_set *writeset) 373void
374client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
373{ 375{
374 /* Initialize select masks. */ 376 /* Initialize select masks. */
375 FD_ZERO(readset); 377 FD_ZERO(readset);
376 378
377 /* Read from the connection, unless our buffers are full. */ 379 /* Read from the connection, unless our buffers are full. */
378 if (buffer_len(&stdout_buffer) < buffer_high && 380 if (buffer_len(&stdout_buffer) < buffer_high &&
379 buffer_len(&stderr_buffer) < buffer_high && 381 buffer_len(&stderr_buffer) < buffer_high &&
380 channel_not_very_much_buffered_data()) 382 channel_not_very_much_buffered_data())
381 FD_SET(connection_in, readset); 383 FD_SET(connection_in, readset);
382 384
383 /* Read from stdin, unless we have seen EOF or have very much buffered 385 /* Read from stdin, unless we have seen EOF or have very much
384 data to send to the server. */ 386 buffered data to send to the server. */
385 if (!stdin_eof && packet_not_very_much_data_to_write()) 387 if (!stdin_eof && packet_not_very_much_data_to_write())
386 FD_SET(fileno(stdin), readset); 388 FD_SET(fileno(stdin), readset);
387 389
388 FD_ZERO(writeset); 390 FD_ZERO(writeset);
389 391
390 /* Add any selections by the channel mechanism. */ 392 /* Add any selections by the channel mechanism. */
391 channel_prepare_select(readset, writeset); 393 channel_prepare_select(readset, writeset);
392 394
393 /* Select server connection if have data to write to the server. */ 395 /* Select server connection if have data to write to the server. */
394 if (packet_have_data_to_write()) 396 if (packet_have_data_to_write())
395 FD_SET(connection_out, writeset); 397 FD_SET(connection_out, writeset);
396 398
397 /* Select stdout if have data in buffer. */ 399 /* Select stdout if have data in buffer. */
398 if (buffer_len(&stdout_buffer) > 0) 400 if (buffer_len(&stdout_buffer) > 0)
399 FD_SET(fileno(stdout), writeset); 401 FD_SET(fileno(stdout), writeset);
400 402
401 /* Select stderr if have data in buffer. */ 403 /* Select stderr if have data in buffer. */
402 if (buffer_len(&stderr_buffer) > 0) 404 if (buffer_len(&stderr_buffer) > 0)
403 FD_SET(fileno(stderr), writeset); 405 FD_SET(fileno(stderr), writeset);
404 406
405 /* Update maximum file descriptor number, if appropriate. */ 407 /* Update maximum file descriptor number, if appropriate. */
406 if (channel_max_fd() > max_fd) 408 if (channel_max_fd() > max_fd)
407 max_fd = channel_max_fd(); 409 max_fd = channel_max_fd();
408 410
409 /* Wait for something to happen. This will suspend the process until 411 /* Wait for something to happen. This will suspend the process
410 some selected descriptor can be read, written, or has some other 412 until some selected descriptor can be read, written, or has
411 event pending. Note: if you want to implement SSH_MSG_IGNORE 413 some other event pending.
412 messages to fool traffic analysis, this might be the place to do 414 Note: if you want to implement SSH_MSG_IGNORE messages to fool
413 it: just have a random timeout for the select, and send a random 415 traffic analysis, this might be the place to do it:
414 SSH_MSG_IGNORE packet when the timeout expires. */ 416 just have a random timeout for the select, and send a random
415 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) 417 SSH_MSG_IGNORE packet when the timeout expires. */
416 { 418
417 char buf[100]; 419 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) {
418 /* Some systems fail to clear these automatically. */ 420 char buf[100];
419 FD_ZERO(readset); 421 /* Some systems fail to clear these automatically. */
420 FD_ZERO(writeset); 422 FD_ZERO(readset);
421 if (errno == EINTR) 423 FD_ZERO(writeset);
422 return; 424 if (errno == EINTR)
423 /* Note: we might still have data in the buffers. */ 425 return;
424 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); 426 /* Note: we might still have data in the buffers. */
425 buffer_append(&stderr_buffer, buf, strlen(buf)); 427 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
426 stderr_bytes += strlen(buf); 428 buffer_append(&stderr_buffer, buf, strlen(buf));
427 quit_pending = 1; 429 stderr_bytes += strlen(buf);
428 } 430 quit_pending = 1;
431 }
429} 432}
430 433
431void client_suspend_self() 434void
435client_suspend_self()
432{ 436{
433 struct winsize oldws, newws; 437 struct winsize oldws, newws;
434 438
435 /* Flush stdout and stderr buffers. */ 439 /* Flush stdout and stderr buffers. */
436 if (buffer_len(&stdout_buffer) > 0) 440 if (buffer_len(&stdout_buffer) > 0)
437 write(fileno(stdout), 441 write(fileno(stdout),
438 buffer_ptr(&stdout_buffer), 442 buffer_ptr(&stdout_buffer),
439 buffer_len(&stdout_buffer)); 443 buffer_len(&stdout_buffer));
440 if (buffer_len(&stderr_buffer) > 0) 444 if (buffer_len(&stderr_buffer) > 0)
441 write(fileno(stderr), 445 write(fileno(stderr),
442 buffer_ptr(&stderr_buffer), 446 buffer_ptr(&stderr_buffer),
443 buffer_len(&stderr_buffer)); 447 buffer_len(&stderr_buffer));
444 448
445 /* Leave raw mode. */ 449 /* Leave raw mode. */
446 leave_raw_mode(); 450 leave_raw_mode();
447 451
448 /* Free (and clear) the buffer to reduce the 452 /* Free (and clear) the buffer to reduce the amount of data that
449 amount of data that gets written to swap. */ 453 gets written to swap. */
450 buffer_free(&stdin_buffer); 454 buffer_free(&stdin_buffer);
451 buffer_free(&stdout_buffer); 455 buffer_free(&stdout_buffer);
452 buffer_free(&stderr_buffer); 456 buffer_free(&stderr_buffer);
453 457
454 /* Save old window size. */ 458 /* Save old window size. */
455 ioctl(fileno(stdin), TIOCGWINSZ, &oldws); 459 ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
456 460
457 /* Send the suspend signal to the program 461 /* Send the suspend signal to the program itself. */
458 itself. */ 462 kill(getpid(), SIGTSTP);
459 kill(getpid(), SIGTSTP); 463
460 464 /* Check if the window size has changed. */
461 /* Check if the window size has changed. */ 465 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
462 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && 466 (oldws.ws_row != newws.ws_row ||
463 (oldws.ws_row != newws.ws_row || oldws.ws_col != newws.ws_col || 467 oldws.ws_col != newws.ws_col ||
464 oldws.ws_xpixel != newws.ws_xpixel || 468 oldws.ws_xpixel != newws.ws_xpixel ||
465 oldws.ws_ypixel != newws.ws_ypixel)) 469 oldws.ws_ypixel != newws.ws_ypixel))
466 received_window_change_signal = 1; 470 received_window_change_signal = 1;
467 471
468 /* OK, we have been continued by the user. 472 /* OK, we have been continued by the user. Reinitialize buffers. */
469 Reinitialize buffers. */ 473 buffer_init(&stdin_buffer);
470 buffer_init(&stdin_buffer); 474 buffer_init(&stdout_buffer);
471 buffer_init(&stdout_buffer); 475 buffer_init(&stderr_buffer);
472 buffer_init(&stderr_buffer); 476
473 477 /* Re-enter raw mode. */
474 /* Re-enter raw mode. */ 478 enter_raw_mode();
475 enter_raw_mode();
476} 479}
477 480
478void client_process_input(fd_set *readset) 481void
482client_process_input(fd_set * readset)
479{ 483{
480 int len, pid; 484 int len, pid;
481 char buf[8192], *s; 485 char buf[8192], *s;
482 486
483 /* Read input from the server, and add any such data to the buffer of the 487 /* Read input from the server, and add any such data to the buffer
484 packet subsystem. */ 488 of the packet subsystem. */
485 if (FD_ISSET(connection_in, readset)) 489 if (FD_ISSET(connection_in, readset)) {
486 { 490 /* Read as much as possible. */
487 /* Read as much as possible. */ 491 len = read(connection_in, buf, sizeof(buf));
488 len = read(connection_in, buf, sizeof(buf)); 492 if (len == 0) {
489 if (len == 0) 493 /* Received EOF. The remote host has closed the connection. */
490 { 494 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
491 /* Received EOF. The remote host has closed the connection. */ 495 host);
492 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
493 host);
494 buffer_append(&stderr_buffer, buf, strlen(buf));
495 stderr_bytes += strlen(buf);
496 quit_pending = 1;
497 return;
498 }
499
500 /* There is a kernel bug on Solaris that causes select to sometimes
501 wake up even though there is no data available. */
502 if (len < 0 && errno == EAGAIN)
503 len = 0;
504
505 if (len < 0)
506 {
507 /* An error has encountered. Perhaps there is a network
508 problem. */
509 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
510 host, strerror(errno));
511 buffer_append(&stderr_buffer, buf, strlen(buf));
512 stderr_bytes += strlen(buf);
513 quit_pending = 1;
514 return;
515 }
516 packet_process_incoming(buf, len);
517 }
518
519 /* Read input from stdin. */
520 if (FD_ISSET(fileno(stdin), readset))
521 {
522 /* Read as much as possible. */
523 len = read(fileno(stdin), buf, sizeof(buf));
524 if (len <= 0)
525 {
526 /* Received EOF or error. They are treated similarly,
527 except that an error message is printed if it was
528 an error condition. */
529 if (len < 0)
530 {
531 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
532 buffer_append(&stderr_buffer, buf, strlen(buf));
533 stderr_bytes += strlen(buf);
534 }
535 /* Mark that we have seen EOF. */
536 stdin_eof = 1;
537 /* Send an EOF message to the server unless there is data
538 in the buffer. If there is data in the buffer, no message
539 will be sent now. Code elsewhere will send the EOF
540 when the buffer becomes empty if stdin_eof is set. */
541 if (buffer_len(&stdin_buffer) == 0)
542 {
543 packet_start(SSH_CMSG_EOF);
544 packet_send();
545 }
546 }
547 else
548 if (escape_char == -1)
549 {
550 /* Normal successful read, and no escape character. Just
551 append the data to buffer. */
552 buffer_append(&stdin_buffer, buf, len);
553 stdin_bytes += len;
554 }
555 else
556 {
557 /* Normal, successful read. But we have an escape character
558 and have to process the characters one by one. */
559 unsigned int i;
560 for (i = 0; i < len; i++)
561 {
562 unsigned char ch;
563 /* Get one character at a time. */
564 ch = buf[i];
565
566 /* Check if we have a pending escape character. */
567 if (escape_pending)
568 {
569 /* We have previously seen an escape character. */
570 /* Clear the flag now. */
571 escape_pending = 0;
572 /* Process the escaped character. */
573 switch (ch)
574 {
575 case '.':
576 /* Terminate the connection. */
577 snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
578 buffer_append(&stderr_buffer, buf, strlen(buf)); 496 buffer_append(&stderr_buffer, buf, strlen(buf));
579 stderr_bytes += strlen(buf); 497 stderr_bytes += strlen(buf);
580 quit_pending = 1; 498 quit_pending = 1;
581 return; 499 return;
582 500 }
583 case 'Z' - 64: 501 /* There is a kernel bug on Solaris that causes select to
584 /* Suspend the program. */ 502 sometimes wake up even though there is no data
585 /* Print a message to that effect to the user. */ 503 available. */
586 snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char); 504 if (len < 0 && errno == EAGAIN)
587 buffer_append(&stderr_buffer, buf, strlen(buf)); 505 len = 0;
588 stderr_bytes += strlen(buf); 506
589 507 if (len < 0) {
590 /* Restore terminal modes and suspend. */ 508 /* An error has encountered. Perhaps there is a network problem. */
591 client_suspend_self(); 509 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
592 510 host, strerror(errno));
593 /* We have been continued. */ 511 buffer_append(&stderr_buffer, buf, strlen(buf));
594 continue; 512 stderr_bytes += strlen(buf);
595 513 quit_pending = 1;
596 case '&': 514 return;
597 /* Detach the program (continue to serve connections, 515 }
598 but put in background and no more new 516 packet_process_incoming(buf, len);
599 connections). */ 517 }
600 if (!stdin_eof) 518 /* Read input from stdin. */
601 { 519 if (FD_ISSET(fileno(stdin), readset)) {
602 /* Sending SSH_CMSG_EOF alone does not always 520 /* Read as much as possible. */
603 appear to be enough. So we try to send an 521 len = read(fileno(stdin), buf, sizeof(buf));
604 EOF character first. */ 522 if (len <= 0) {
605 packet_start(SSH_CMSG_STDIN_DATA); 523 /* Received EOF or error. They are treated
606 packet_put_string("\004", 1); 524 similarly, except that an error message is
607 packet_send(); 525 printed if it was an error condition. */
608 /* Close stdin. */ 526 if (len < 0) {
609 stdin_eof = 1; 527 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
610 if (buffer_len(&stdin_buffer) == 0) 528 buffer_append(&stderr_buffer, buf, strlen(buf));
611 { 529 stderr_bytes += strlen(buf);
530 }
531 /* Mark that we have seen EOF. */
532 stdin_eof = 1;
533 /* Send an EOF message to the server unless there
534 is data in the buffer. If there is data in the
535 buffer, no message will be sent now. Code
536 elsewhere will send the EOF when the buffer
537 becomes empty if stdin_eof is set. */
538 if (buffer_len(&stdin_buffer) == 0) {
612 packet_start(SSH_CMSG_EOF); 539 packet_start(SSH_CMSG_EOF);
613 packet_send(); 540 packet_send();
614 } 541 }
615 } 542 } else if (escape_char == -1) {
616 /* Restore tty modes. */ 543 /* Normal successful read, and no escape
617 leave_raw_mode(); 544 character. Just append the data to buffer. */
618 545 buffer_append(&stdin_buffer, buf, len);
619 /* Stop listening for new connections. */ 546 stdin_bytes += len;
620 channel_stop_listening(); 547 } else {
621 548 /* Normal, successful read. But we have an escape
622 printf("%c& [backgrounded]\n", escape_char); 549 character and have to process the characters
623 550 one by one. */
624 /* Fork into background. */ 551 unsigned int i;
625 pid = fork(); 552 for (i = 0; i < len; i++) {
626 if (pid < 0) 553 unsigned char ch;
627 { 554 /* Get one character at a time. */
628 error("fork: %.100s", strerror(errno)); 555 ch = buf[i];
629 continue; 556
630 } 557 /* Check if we have a pending escape
631 if (pid != 0) 558 character. */
632 { /* This is the parent. */ 559 if (escape_pending) {
633 /* The parent just exits. */ 560 /* We have previously seen an escape character. */
634 exit(0); 561 /* Clear the flag now. */
635 } 562 escape_pending = 0;
636 563 /* Process the escaped character. */
637 /* The child continues serving connections. */ 564 switch (ch) {
638 continue; 565 case '.':
639 566 /* Terminate the connection. */
640 case '?': 567 snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
641 snprintf(buf, sizeof buf, "%c?\r\n\ 568 buffer_append(&stderr_buffer, buf, strlen(buf));
569 stderr_bytes += strlen(buf);
570 quit_pending = 1;
571 return;
572
573 case 'Z' - 64:
574 /* Suspend the program. */
575 /* Print a message to that effect to the user. */
576 snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char);
577 buffer_append(&stderr_buffer, buf, strlen(buf));
578 stderr_bytes += strlen(buf);
579
580 /* Restore terminal modes and suspend. */
581 client_suspend_self();
582
583 /* We have been continued. */
584 continue;
585
586 case '&':
587 /* Detach the program (continue to serve connections,
588 but put in background and no more new connections). */
589 if (!stdin_eof) {
590 /* Sending SSH_CMSG_EOF alone does not always appear
591 to be enough. So we try to send an EOF character
592 first. */
593 packet_start(SSH_CMSG_STDIN_DATA);
594 packet_put_string("\004", 1);
595 packet_send();
596 /* Close stdin. */
597 stdin_eof = 1;
598 if (buffer_len(&stdin_buffer) == 0) {
599 packet_start(SSH_CMSG_EOF);
600 packet_send();
601 }
602 }
603 /* Restore tty modes. */
604 leave_raw_mode();
605
606 /* Stop listening for new connections. */
607 channel_stop_listening();
608
609 printf("%c& [backgrounded]\n", escape_char);
610
611 /* Fork into background. */
612 pid = fork();
613 if (pid < 0) {
614 error("fork: %.100s", strerror(errno));
615 continue;
616 }
617 if (pid != 0) { /* This is the parent. */
618 /* The parent just exits. */
619 exit(0);
620 }
621 /* The child continues serving connections. */
622 continue;
623
624 case '?':
625 snprintf(buf, sizeof buf,
626"%c?\r\n\
642Supported escape sequences:\r\n\ 627Supported escape sequences:\r\n\
643~. - terminate connection\r\n\ 628~. - terminate connection\r\n\
644~^Z - suspend ssh\r\n\ 629~^Z - suspend ssh\r\n\
@@ -647,110 +632,100 @@ Supported escape sequences:\r\n\
647~? - this message\r\n\ 632~? - this message\r\n\
648~~ - send the escape character by typing it twice\r\n\ 633~~ - send the escape character by typing it twice\r\n\
649(Note that escapes are only recognized immediately after newline.)\r\n", 634(Note that escapes are only recognized immediately after newline.)\r\n",
650 escape_char); 635 escape_char);
651 buffer_append(&stderr_buffer, buf, strlen(buf)); 636 buffer_append(&stderr_buffer, buf, strlen(buf));
652 continue; 637 continue;
653 638
654 case '#': 639 case '#':
655 snprintf(buf, sizeof buf, "%c#\r\n", escape_char); 640 snprintf(buf, sizeof buf, "%c#\r\n", escape_char);
656 buffer_append(&stderr_buffer, buf, strlen(buf)); 641 buffer_append(&stderr_buffer, buf, strlen(buf));
657 s = channel_open_message(); 642 s = channel_open_message();
658 buffer_append(&stderr_buffer, s, strlen(s)); 643 buffer_append(&stderr_buffer, s, strlen(s));
659 xfree(s); 644 xfree(s);
660 continue; 645 continue;
661 646
662 default: 647 default:
663 if (ch != escape_char) 648 if (ch != escape_char) {
664 { 649 /* Escape character followed by non-special character.
665 /* Escape character followed by non-special 650 Append both to the input buffer. */
666 character. Append both to the input 651 buf[0] = escape_char;
667 buffer. */ 652 buf[1] = ch;
668 buf[0] = escape_char; 653 buffer_append(&stdin_buffer, buf, 2);
669 buf[1] = ch; 654 stdin_bytes += 2;
670 buffer_append(&stdin_buffer, buf, 2); 655 continue;
671 stdin_bytes += 2; 656 }
672 continue; 657 /* Note that escape character typed twice
673 } 658 falls through here; the latter gets processed
674 /* Note that escape character typed twice falls through 659 as a normal character below. */
675 here; the latter gets processed as a normal 660 break;
676 character below. */ 661 }
677 break; 662 } else {
678 } 663 /* The previous character was not an escape char. Check if this
679 } 664 is an escape. */
680 else 665 if (last_was_cr && ch == escape_char) {
681 { 666 /* It is. Set the flag and continue to next character. */
682 /* The previous character was not an escape char. 667 escape_pending = 1;
683 Check if this is an escape. */ 668 continue;
684 if (last_was_cr && ch == escape_char) 669 }
685 { 670 }
686 /* It is. Set the flag and continue to next 671
687 character. */ 672 /* Normal character. Record whether it was a newline, and append it to the
688 escape_pending = 1; 673 buffer. */
689 continue; 674 last_was_cr = (ch == '\r' || ch == '\n');
690 } 675 buf[0] = ch;
691 } 676 buffer_append(&stdin_buffer, buf, 1);
692 677 stdin_bytes += 1;
693 /* Normal character. Record whether it was a newline, 678 continue;
694 and append it to the buffer. */ 679 }
695 last_was_cr = (ch == '\r' || ch == '\n'); 680 }
696 buf[0] = ch; 681 }
697 buffer_append(&stdin_buffer, buf, 1);
698 stdin_bytes += 1;
699 continue;
700 }
701 }
702 }
703} 682}
704 683
705void client_process_output(fd_set *writeset) 684void
685client_process_output(fd_set * writeset)
706{ 686{
707 int len; 687 int len;
708 char buf[100]; 688 char buf[100];
709 689
710 /* Write buffered output to stdout. */ 690 /* Write buffered output to stdout. */
711 if (FD_ISSET(fileno(stdout), writeset)) 691 if (FD_ISSET(fileno(stdout), writeset)) {
712 { 692 /* Write as much data as possible. */
713 /* Write as much data as possible. */ 693 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
714 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 694 buffer_len(&stdout_buffer));
715 buffer_len(&stdout_buffer)); 695 if (len <= 0) {
716 if (len <= 0) 696 if (errno == EAGAIN)
717 { 697 len = 0;
718 if (errno == EAGAIN) 698 else {
719 len = 0; 699 /* An error or EOF was encountered. Put
720 else 700 an error message to stderr buffer. */
721 { 701 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
722 /* An error or EOF was encountered. Put an error message 702 buffer_append(&stderr_buffer, buf, strlen(buf));
723 to stderr buffer. */ 703 stderr_bytes += strlen(buf);
724 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); 704 quit_pending = 1;
725 buffer_append(&stderr_buffer, buf, strlen(buf)); 705 return;
726 stderr_bytes += strlen(buf); 706 }
727 quit_pending = 1; 707 }
728 return; 708 /* Consume printed data from the buffer. */
729 } 709 buffer_consume(&stdout_buffer, len);
710 }
711 /* Write buffered output to stderr. */
712 if (FD_ISSET(fileno(stderr), writeset)) {
713 /* Write as much data as possible. */
714 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
715 buffer_len(&stderr_buffer));
716 if (len <= 0) {
717 if (errno == EAGAIN)
718 len = 0;
719 else {
720 /* EOF or error, but can't even print
721 error message. */
722 quit_pending = 1;
723 return;
724 }
725 }
726 /* Consume printed characters from the buffer. */
727 buffer_consume(&stderr_buffer, len);
730 } 728 }
731 /* Consume printed data from the buffer. */
732 buffer_consume(&stdout_buffer, len);
733 }
734
735 /* Write buffered output to stderr. */
736 if (FD_ISSET(fileno(stderr), writeset))
737 {
738 /* Write as much data as possible. */
739 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
740 buffer_len(&stderr_buffer));
741 if (len <= 0) {
742 if (errno == EAGAIN)
743 len = 0;
744 else
745 {
746 /* EOF or error, but can't even print error message. */
747 quit_pending = 1;
748 return;
749 }
750 }
751 /* Consume printed characters from the buffer. */
752 buffer_consume(&stderr_buffer, len);
753 }
754} 729}
755 730
756/* Implements the interactive session with the server. This is called 731/* Implements the interactive session with the server. This is called
@@ -759,165 +734,160 @@ void client_process_output(fd_set *writeset)
759 used as an escape character for terminating or suspending the 734 used as an escape character for terminating or suspending the
760 session. */ 735 session. */
761 736
762int client_loop(int have_pty, int escape_char_arg) 737int
738client_loop(int have_pty, int escape_char_arg)
763{ 739{
764 extern Options options; 740 extern Options options;
765 double start_time, total_time; 741 double start_time, total_time;
766 int len; 742 int len;
767 char buf[100]; 743 char buf[100];
768 744
769 debug("Entering interactive session."); 745 debug("Entering interactive session.");
770 746
771 start_time = get_current_time(); 747 start_time = get_current_time();
772 748
773 /* Initialize variables. */ 749 /* Initialize variables. */
774 escape_pending = 0; 750 escape_pending = 0;
775 last_was_cr = 1; 751 last_was_cr = 1;
776 exit_status = -1; 752 exit_status = -1;
777 stdin_eof = 0; 753 stdin_eof = 0;
778 buffer_high = 64 * 1024; 754 buffer_high = 64 * 1024;
779 connection_in = packet_get_connection_in(); 755 connection_in = packet_get_connection_in();
780 connection_out = packet_get_connection_out(); 756 connection_out = packet_get_connection_out();
781 max_fd = connection_in; 757 max_fd = connection_in;
782 if (connection_out > max_fd) 758 if (connection_out > max_fd)
783 max_fd = connection_out; 759 max_fd = connection_out;
784 stdin_bytes = 0; 760 stdin_bytes = 0;
785 stdout_bytes = 0; 761 stdout_bytes = 0;
786 stderr_bytes = 0; 762 stderr_bytes = 0;
787 quit_pending = 0; 763 quit_pending = 0;
788 escape_char = escape_char_arg; 764 escape_char = escape_char_arg;
789 765
790 /* Initialize buffers. */ 766 /* Initialize buffers. */
791 buffer_init(&stdin_buffer); 767 buffer_init(&stdin_buffer);
792 buffer_init(&stdout_buffer); 768 buffer_init(&stdout_buffer);
793 buffer_init(&stderr_buffer); 769 buffer_init(&stderr_buffer);
794 770
795 /* Set signal handlers to restore non-blocking mode. */ 771 /* Set signal handlers to restore non-blocking mode. */
796 signal(SIGINT, signal_handler); 772 signal(SIGINT, signal_handler);
797 signal(SIGQUIT, signal_handler); 773 signal(SIGQUIT, signal_handler);
798 signal(SIGTERM, signal_handler); 774 signal(SIGTERM, signal_handler);
799 signal(SIGPIPE, SIG_IGN); 775 signal(SIGPIPE, SIG_IGN);
800 if (have_pty) 776 if (have_pty)
801 signal(SIGWINCH, window_change_handler); 777 signal(SIGWINCH, window_change_handler);
802 778
803 /* Enter raw mode if have a pseudo terminal. */ 779 /* Enter raw mode if have a pseudo terminal. */
804 if (have_pty) 780 if (have_pty)
805 enter_raw_mode(); 781 enter_raw_mode();
806 782
807 /* Check if we should immediately send of on stdin. */ 783 /* Check if we should immediately send of on stdin. */
808 client_check_initial_eof_on_stdin(); 784 client_check_initial_eof_on_stdin();
809 785
810 /* Main loop of the client for the interactive session mode. */ 786 /* Main loop of the client for the interactive session mode. */
811 while (!quit_pending) 787 while (!quit_pending) {
812 { 788 fd_set readset, writeset;
813 fd_set readset, writeset; 789
814 790 /* Precess buffered packets sent by the server. */
815 /* Precess buffered packets sent by the server. */ 791 client_process_buffered_input_packets();
816 client_process_buffered_input_packets(); 792
817 793 /* Make packets of buffered stdin data, and buffer them
818 /* Make packets of buffered stdin data, and buffer them for sending 794 for sending to the server. */
819 to the server. */ 795 client_make_packets_from_stdin_data();
820 client_make_packets_from_stdin_data(); 796
821 797 /* Make packets from buffered channel data, and buffer
822 /* Make packets from buffered channel data, and buffer them for sending 798 them for sending to the server. */
823 to the server. */ 799 if (packet_not_very_much_data_to_write())
824 if (packet_not_very_much_data_to_write()) 800 channel_output_poll();
825 channel_output_poll(); 801
826 802 /* Check if the window size has changed, and buffer a
827 /* Check if the window size has changed, and buffer a message about 803 message about it to the server if so. */
828 it to the server if so. */ 804 client_check_window_change();
829 client_check_window_change(); 805
830 806 if (quit_pending)
831 if (quit_pending) 807 break;
832 break; 808
833 809 /* Wait until we have something to do (something becomes
834 /* Wait until we have something to do (something becomes available 810 available on one of the descriptors). */
835 on one of the descriptors). */ 811 client_wait_until_can_do_something(&readset, &writeset);
836 client_wait_until_can_do_something(&readset, &writeset); 812
837 813 if (quit_pending)
838 if (quit_pending) 814 break;
839 break; 815
840 816 /* Do channel operations. */
841 /* Do channel operations. */ 817 channel_after_select(&readset, &writeset);
842 channel_after_select(&readset, &writeset); 818
843 819 /* Process input from the connection and from stdin.
844 /* Process input from the connection and from stdin. Buffer any data 820 Buffer any data that is available. */
845 that is available. */ 821 client_process_input(&readset);
846 client_process_input(&readset); 822
847 823 /* Process output to stdout and stderr. Output to the
848 /* Process output to stdout and stderr. Output to the connection 824 connection is processed elsewhere (above). */
849 is processed elsewhere (above). */ 825 client_process_output(&writeset);
850 client_process_output(&writeset); 826
851 827 /* Send as much buffered packet data as possible to the
852 /* Send as much buffered packet data as possible to the sender. */ 828 sender. */
853 if (FD_ISSET(connection_out, &writeset)) 829 if (FD_ISSET(connection_out, &writeset))
854 packet_write_poll(); 830 packet_write_poll();
855 } 831 }
856 832
857 /* Terminate the session. */ 833 /* Terminate the session. */
858 834
859 /* Stop watching for window change. */ 835 /* Stop watching for window change. */
860 if (have_pty) 836 if (have_pty)
861 signal(SIGWINCH, SIG_DFL); 837 signal(SIGWINCH, SIG_DFL);
862 838
863 /* Stop listening for connections. */ 839 /* Stop listening for connections. */
864 channel_stop_listening(); 840 channel_stop_listening();
865 841
866 /* In interactive mode (with pseudo tty) display a message indicating that 842 /* In interactive mode (with pseudo tty) display a message
867 the connection has been closed. */ 843 indicating that the connection has been closed. */
868 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) 844 if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
869 { 845 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
870 snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host); 846 buffer_append(&stderr_buffer, buf, strlen(buf));
871 buffer_append(&stderr_buffer, buf, strlen(buf)); 847 stderr_bytes += strlen(buf);
872 stderr_bytes += strlen(buf);
873 }
874
875 /* Output any buffered data for stdout. */
876 while (buffer_len(&stdout_buffer) > 0)
877 {
878 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
879 buffer_len(&stdout_buffer));
880 if (len <= 0)
881 {
882 error("Write failed flushing stdout buffer.");
883 break;
884 } 848 }
885 buffer_consume(&stdout_buffer, len); 849 /* Output any buffered data for stdout. */
886 } 850 while (buffer_len(&stdout_buffer) > 0) {
887 851 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
888 /* Output any buffered data for stderr. */ 852 buffer_len(&stdout_buffer));
889 while (buffer_len(&stderr_buffer) > 0) 853 if (len <= 0) {
890 { 854 error("Write failed flushing stdout buffer.");
891 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 855 break;
892 buffer_len(&stderr_buffer)); 856 }
893 if (len <= 0) 857 buffer_consume(&stdout_buffer, len);
894 {
895 error("Write failed flushing stderr buffer.");
896 break;
897 } 858 }
898 buffer_consume(&stderr_buffer, len); 859
899 } 860 /* Output any buffered data for stderr. */
900 861 while (buffer_len(&stderr_buffer) > 0) {
901 /* Leave raw mode. */ 862 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
902 if (have_pty) 863 buffer_len(&stderr_buffer));
903 leave_raw_mode(); 864 if (len <= 0) {
904 865 error("Write failed flushing stderr buffer.");
905 /* Clear and free any buffers. */ 866 break;
906 memset(buf, 0, sizeof(buf)); 867 }
907 buffer_free(&stdin_buffer); 868 buffer_consume(&stderr_buffer, len);
908 buffer_free(&stdout_buffer); 869 }
909 buffer_free(&stderr_buffer); 870
910 871 /* Leave raw mode. */
911 /* Report bytes transferred, and transfer rates. */ 872 if (have_pty)
912 total_time = get_current_time() - start_time; 873 leave_raw_mode();
913 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds", 874
914 stdin_bytes, stdout_bytes, stderr_bytes, total_time); 875 /* Clear and free any buffers. */
915 if (total_time > 0) 876 memset(buf, 0, sizeof(buf));
916 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f", 877 buffer_free(&stdin_buffer);
917 stdin_bytes / total_time, stdout_bytes / total_time, 878 buffer_free(&stdout_buffer);
918 stderr_bytes / total_time); 879 buffer_free(&stderr_buffer);
919 880
920 /* Return the exit status of the program. */ 881 /* Report bytes transferred, and transfer rates. */
921 debug("Exit status %d", exit_status); 882 total_time = get_current_time() - start_time;
922 return exit_status; 883 debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
884 stdin_bytes, stdout_bytes, stderr_bytes, total_time);
885 if (total_time > 0)
886 debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
887 stdin_bytes / total_time, stdout_bytes / total_time,
888 stderr_bytes / total_time);
889
890 /* Return the exit status of the program. */
891 debug("Exit status %d", exit_status);
892 return exit_status;
923} 893}