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