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