diff cli-chansession.c @ 40:b4874d772210

- Added terminal mode handling etc for the client, and window change - Refactored the terminal-mode handling for the server - Improved session closing for the client
author Matt Johnston <matt@ucc.asn.au>
date Sun, 01 Aug 2004 08:54:01 +0000
parents 0883c0906870
children 18eccbfb9641
line wrap: on
line diff
--- a/cli-chansession.c	Fri Jul 30 12:29:53 2004 +0000
+++ b/cli-chansession.c	Sun Aug 01 08:54:01 2004 +0000
@@ -6,6 +6,7 @@
 #include "channel.h"
 #include "ssh.h"
 #include "runopts.h"
+#include "termcodes.h"
 
 static void cli_closechansess(struct Channel *channel);
 static int cli_initchansess(struct Channel *channel);
@@ -16,7 +17,7 @@
 static void send_chansess_shell_req(struct Channel *channel);
 
 static void cli_tty_setup();
-static void cli_tty_cleanup();
+void cli_tty_cleanup();
 
 static const struct ChanType clichansess = {
 	0, /* sepfds */
@@ -50,7 +51,6 @@
 
 }
 
-
 /* Taken from OpenSSH's sshtty.c:
  * RCSID("OpenBSD: sshtty.c,v 1.5 2003/09/19 17:43:35 markus Exp "); */
 static void cli_tty_setup() {
@@ -91,12 +91,13 @@
 	TRACE(("leave cli_tty_setup"));
 }
 
-static void cli_tty_cleanup() {
+void cli_tty_cleanup() {
 
 	TRACE(("enter cli_tty_cleanup"));
 
 	if (cli_ses.tty_raw_mode == 0) {
 		TRACE(("leave cli_tty_cleanup: not in raw mode"));
+		return;
 	}
 
 	if (tcsetattr(STDIN_FILENO, TCSADRAIN, &cli_ses.saved_tio) == -1) {
@@ -108,30 +109,123 @@
 	TRACE(("leave cli_tty_cleanup"));
 }
 
+static void put_termcodes() {
+
+	TRACE(("enter put_termcodes"));
+
+	struct termios tio;
+	unsigned int sshcode;
+	const struct TermCode *termcode;
+	unsigned int value;
+	unsigned int mapcode;
+
+	unsigned int bufpos1, bufpos2;
+
+	if (tcgetattr(STDIN_FILENO, &tio) == -1) {
+		dropbear_log(LOG_WARNING, "Failed reading termmodes");
+		buf_putint(ses.writepayload, 1); /* Just the terminator */
+		buf_putbyte(ses.writepayload, 0); /* TTY_OP_END */
+		return;
+	}
+
+	bufpos1 = ses.writepayload->pos;
+	buf_putint(ses.writepayload, 0); /* A placeholder for the final length */
+
+	/* As with Dropbear server, we ignore baud rates for now */
+	for (sshcode = 1; sshcode < MAX_TERMCODE; sshcode++) {
+
+		termcode = &termcodes[sshcode];
+		mapcode = termcode->mapcode;
+
+		switch (termcode->type) {
+
+			case TERMCODE_NONE:
+				continue;
+
+			case TERMCODE_CONTROLCHAR:
+				value = tio.c_cc[mapcode];
+				break;
+
+			case TERMCODE_INPUT:
+				value = tio.c_iflag & mapcode;
+				break;
+
+			case TERMCODE_OUTPUT:
+				value = tio.c_oflag & mapcode;
+				break;
+
+			case TERMCODE_LOCAL:
+				value = tio.c_lflag & mapcode;
+				break;
+
+			case TERMCODE_CONTROL:
+				value = tio.c_cflag & mapcode;
+				break;
+
+			default:
+				continue;
+
+		}
+
+		/* If we reach here, we have something to say */
+		buf_putbyte(ses.writepayload, sshcode);
+		buf_putint(ses.writepayload, value);
+	}
+
+	buf_putbyte(ses.writepayload, 0); /* THE END, aka TTY_OP_END */
+
+	/* Put the string length at the start of the buffer */
+	bufpos2 = ses.writepayload->pos;
+
+	buf_setpos(ses.writepayload, bufpos1); /* Jump back */
+	buf_putint(ses.writepayload, bufpos2 - bufpos1); /* len(termcodes) */
+	buf_setpos(ses.writepayload, bufpos2); /* Back where we were */
+
+	TRACE(("leave put_termcodes"));
+}
+
+static void put_winsize() {
+
+	struct winsize ws;
+
+	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {
+		/* Some sane defaults */
+		ws.ws_row = 25;
+		ws.ws_col = 80;
+		ws.ws_xpixel = 0;
+		ws.ws_ypixel = 0;
+	}
+
+	buf_putint(ses.writepayload, ws.ws_col); /* Cols */
+	buf_putint(ses.writepayload, ws.ws_row); /* Rows */
+	buf_putint(ses.writepayload, ws.ws_xpixel); /* Width */
+	buf_putint(ses.writepayload, ws.ws_ypixel); /* Height */
+
+}
+
 static void send_chansess_pty_req(struct Channel *channel) {
 
-	unsigned char* termmodes = "\0";
 	unsigned char* term = NULL;
-	int termc = 80, termr = 25, termw = 0, termh = 0; /* XXX TODO matt */
 
 	TRACE(("enter send_chansess_pty_req"));
+
 	start_channel_request(channel, "pty-req");
 
+	/* Don't want replies */
+	buf_putbyte(ses.writepayload, 0);
+
+	/* Get the terminal */
 	term = getenv("TERM");
 	if (term == NULL) {
-		term = "vt100";
+		term = "vt100"; /* Seems a safe default */
 	}
-
-	/* XXX TODO */
-	buf_putbyte(ses.writepayload, 0); /* Don't want replies */
 	buf_putstring(ses.writepayload, term, strlen(term));
-	buf_putint(ses.writepayload, termc); /* Cols */
-	buf_putint(ses.writepayload, termr); /* Rows */
-	buf_putint(ses.writepayload, termw); /* Width */
-	buf_putint(ses.writepayload, termh); /* Height */
 
-	buf_putstring(ses.writepayload, termmodes, 1); /* XXX TODO */
-	//m_free(termmodes);
+	/* Window size */
+	put_winsize();
+
+	/* Terminal mode encoding */
+	put_termcodes();
 
 	encrypt_packet();
 	TRACE(("leave send_chansess_pty_req"));
@@ -171,7 +265,6 @@
 		send_chansess_pty_req(channel);
 	}
 
-	cli_opts.cmd = "df";
 	send_chansess_shell_req(channel);
 
 	if (cli_opts.wantpty) {