if (need_rekeying) { debug("user requests rekeying");
if (need_rekeying || packet_need_rekeying()) { debug("need rekeying");
client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id){	fd_set *readset = NULL, *writeset = NULL;	double start_time, total_time;	int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0;	char buf[100];	debug("Entering interactive session.");	start_time = get_current_time();	/* Initialize variables. */	escape_pending = 0;	last_was_cr = 1;	exit_status = -1;	stdin_eof = 0;	buffer_high = 64 * 1024;	connection_in = packet_get_connection_in();	connection_out = packet_get_connection_out();	max_fd = MAX(connection_in, connection_out);	if (!compat20) {		/* enable nonblocking unless tty */		if (!isatty(fileno(stdin)))			set_nonblock(fileno(stdin));		if (!isatty(fileno(stdout)))			set_nonblock(fileno(stdout));		if (!isatty(fileno(stderr)))			set_nonblock(fileno(stderr));		max_fd = MAX(max_fd, fileno(stdin));		max_fd = MAX(max_fd, fileno(stdout));		max_fd = MAX(max_fd, fileno(stderr));	}	stdin_bytes = 0;	stdout_bytes = 0;	stderr_bytes = 0;	quit_pending = 0;	escape_char = escape_char_arg;	/* Initialize buffers. */	buffer_init(&stdin_buffer);	buffer_init(&stdout_buffer);	buffer_init(&stderr_buffer);	client_init_dispatch();	/*	 * Set signal handlers, (e.g. to restore non-blocking mode)	 * but don't overwrite SIG_IGN, matches behaviour from rsh(1)	 */	if (signal(SIGINT, SIG_IGN) != SIG_IGN)		signal(SIGINT, signal_handler);	if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)		signal(SIGQUIT, signal_handler);	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)		signal(SIGTERM, signal_handler);	if (have_pty)		signal(SIGWINCH, window_change_handler);	if (have_pty)		enter_raw_mode();	if (compat20) {		session_ident = ssh2_chan_id;		if (escape_char != SSH_ESCAPECHAR_NONE)			channel_register_filter(session_ident,			    simple_escape_filter);		if (session_ident != -1)			channel_register_cleanup(session_ident,			    client_channel_closed);	} else {		/* Check if we should immediately send eof on stdin. */		client_check_initial_eof_on_stdin();	}	/* Main loop of the client for the interactive session mode. */	while (!quit_pending) {		/* Process buffered packets sent by the server. */		client_process_buffered_input_packets();		if (compat20 && session_closed && !channel_still_open())			break;		rekeying = (xxx_kex != NULL && !xxx_kex->done);		if (rekeying) {			debug("rekeying in progress");		} else {			/*			 * Make packets of buffered stdin data, and buffer			 * them for sending to the server.			 */			if (!compat20)				client_make_packets_from_stdin_data();			/*			 * Make packets from buffered channel data, and			 * enqueue them for sending to the server.			 */			if (packet_not_very_much_data_to_write())				channel_output_poll();			/*			 * Check if the window size has changed, and buffer a			 * message about it to the server if so.			 */			client_check_window_change();			if (quit_pending)				break;		}		/*		 * Wait until we have something to do (something becomes		 * available on one of the descriptors).		 */		max_fd2 = max_fd;		client_wait_until_can_do_something(&readset, &writeset,		    &max_fd2, &nalloc, rekeying);		if (quit_pending)			break;		/* Do channel operations unless rekeying in progress. */		if (!rekeying) {			channel_after_select(readset, writeset);			if (need_rekeying) {				debug("user requests rekeying");				xxx_kex->done = 0;				kex_send_kexinit(xxx_kex);				need_rekeying = 0;			}		}		/* Buffer input from the connection.  */		client_process_net_input(readset);		if (quit_pending)			break;		if (!compat20) {			/* Buffer data from stdin */			client_process_input(readset);			/*			 * Process output to stdout and stderr.  Output to			 * the connection is processed elsewhere (above).			 */			client_process_output(writeset);		}		/* Send as much buffered packet data as possible to the sender. */		if (FD_ISSET(connection_out, writeset))			packet_write_poll();	}	if (readset)		xfree(readset);	if (writeset)		xfree(writeset);	/* Terminate the session. */	/* Stop watching for window change. */	if (have_pty)		signal(SIGWINCH, SIG_DFL);	channel_free_all();	if (have_pty)		leave_raw_mode();	/* restore blocking io */	if (!isatty(fileno(stdin)))		unset_nonblock(fileno(stdin));	if (!isatty(fileno(stdout)))		unset_nonblock(fileno(stdout));	if (!isatty(fileno(stderr)))		unset_nonblock(fileno(stderr));	if (received_signal) {		if (in_non_blocking_mode)	/* XXX */			leave_non_blocking();		fatal("Killed by signal %d.", (int) received_signal);	}	/*	 * In interactive mode (with pseudo tty) display a message indicating	 * that the connection has been closed.	 */	if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {		snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);		buffer_append(&stderr_buffer, buf, strlen(buf));	}	/* Output any buffered data for stdout. */	while (buffer_len(&stdout_buffer) > 0) {		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),		    buffer_len(&stdout_buffer));		if (len <= 0) {			error("Write failed flushing stdout buffer.");			break;		}		buffer_consume(&stdout_buffer, len);		stdout_bytes += len;	}	/* Output any buffered data for stderr. */	while (buffer_len(&stderr_buffer) > 0) {		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),		    buffer_len(&stderr_buffer));		if (len <= 0) {			error("Write failed flushing stderr buffer.");			break;		}		buffer_consume(&stderr_buffer, len);		stderr_bytes += len;	}	/* Clear and free any buffers. */	memset(buf, 0, sizeof(buf));	buffer_free(&stdin_buffer);	buffer_free(&stdout_buffer);	buffer_free(&stderr_buffer);	/* Report bytes transferred, and transfer rates. */	total_time = get_current_time() - start_time;	debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",	    stdin_bytes, stdout_bytes, stderr_bytes, total_time);	if (total_time > 0)		debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",		    stdin_bytes / total_time, stdout_bytes / total_time,		    stderr_bytes / total_time);	/* Return the exit status of the program. */	debug("Exit status %d", exit_status);	return exit_status;}