Browse Source

tty: improvements (^V, fix nlcr behaviors, enter sends ^M)

K. Lange 3 years ago
parent
commit
cc4874f90a
6 changed files with 83 additions and 28 deletions
  1. 3 0
      apps/stty.c
  2. 7 0
      apps/terminal-vga.c
  3. 6 0
      apps/terminal.c
  4. 2 0
      base/usr/include/kernel/pty.h
  5. 1 0
      base/usr/include/sys/termios.h
  6. 64 28
      kernel/fs/tty.c

+ 3 - 0
apps/stty.c

@@ -108,6 +108,7 @@ static int show_settings(int all) {
 	print_cc(&t, "kill",  VKILL,  21);
 	print_cc(&t, "eof",   VEOF,   4);
 	print_cc(&t, "eol",   VEOL,   0);
+	print_cc(&t, "lnext", VLNEXT, 22);
 	if (printed) { fprintf(stdout, "\n"); printed = 0; }
 
 	print_cc(&t, "start", VSTART, 17);
@@ -241,6 +242,7 @@ int main(int argc, char * argv[]) {
 			t.c_cc[VSTOP]  = 19; /* ^S */
 			t.c_cc[VSUSP] = 26; /* ^Z */
 			t.c_cc[VTIME]  =  0;
+			t.c_cc[VLNEXT] = 22; /* ^V */
 		}
 
 		set_char("eof",   VEOF);
@@ -252,6 +254,7 @@ int main(int argc, char * argv[]) {
 		set_char("start", VSTART);
 		set_char("stop",  VSTOP);
 		set_char("susp",  VSUSP);
+		set_char("lnext", VLNEXT);
 
 
 		set_cflag("parenb", PARENB);

+ 7 - 0
apps/terminal-vga.c

@@ -881,6 +881,13 @@ void key_event(int ret, key_event_t * event) {
 			handle_input_s("\033[Z");
 			return;
 		}
+
+		/* ENTER = reads as linefeed, should be carriage return */
+		if (event->keycode == 10) {
+			handle_input('\r');
+			return;
+		}
+
 		handle_input(event->key);
 	} else {
 		if (event->action == KEY_ACTION_UP) return;

+ 6 - 0
apps/terminal.c

@@ -1654,6 +1654,12 @@ static void key_event(int ret, key_event_t * event) {
 			return;
 		}
 
+		/* ENTER = reads as linefeed, should be carriage return */
+		if (event->keycode == 10) {
+			handle_input('\r');
+			return;
+		}
+
 		/* Pass key value to PTY */
 		handle_input(event->key);
 	} else {

+ 2 - 0
base/usr/include/kernel/pty.h

@@ -33,6 +33,8 @@ typedef struct pty {
 	void (*write_in)(struct pty *, uint8_t);
 	void (*write_out)(struct pty *, uint8_t);
 
+	int next_is_verbatim;
+
 } pty_t;
 
 void tty_output_process_slave(pty_t * pty, uint8_t c);

+ 1 - 0
base/usr/include/sys/termios.h

@@ -34,6 +34,7 @@ typedef unsigned char cc_t;
 #define VSTOP    9 /* ^S stop input */
 #define VSUSP   10 /* ^Z suspend foreground applicatioan (send SIGTSTP) */
 #define VTIME   11 /* Timeout for non-canonical read, deciseconds */
+#define VLNEXT  12 /* ^V literal next */
 
 /* flags for input modes */
 #define BRKINT  0000001

+ 64 - 28
kernel/fs/tty.c

@@ -78,7 +78,7 @@ void tty_output_process(pty_t * pty, uint8_t c) {
 	output_process_slave(pty, c);
 }
 
-static void erase_one(pty_t * pty) {
+static void erase_one(pty_t * pty, int erase) {
 	if (pty->canon_buflen > 0) {
 		/* How many do we backspace? */
 		int vwidth = 1;
@@ -88,17 +88,35 @@ static void erase_one(pty_t * pty) {
 			vwidth = 2;
 		}
 		pty->canon_buffer[pty->canon_buflen] = '\0';
-		if ((pty->tios.c_lflag & ECHO) && (pty->tios.c_lflag & ECHOE)) {
-			for (int i = 0; i < vwidth; ++i) {
-				output_process(pty, '\010');
-				output_process(pty, ' ');
-				output_process(pty, '\010');
+		if (pty->tios.c_lflag & ECHO) {
+			if (erase) {
+				for (int i = 0; i < vwidth; ++i) {
+					output_process(pty, '\010');
+					output_process(pty, ' ');
+					output_process(pty, '\010');
+				}
 			}
 		}
 	}
 }
 
 void tty_input_process(pty_t * pty, uint8_t c) {
+	if (pty->next_is_verbatim) {
+		pty->next_is_verbatim = 0;
+		if (pty->canon_buflen < pty->canon_bufsize) {
+			pty->canon_buffer[pty->canon_buflen] = c;
+			pty->canon_buflen++;
+		}
+		if (pty->tios.c_lflag & ECHO) {
+			if (c < ' ') {
+				output_process(pty, '^');
+				output_process(pty, '@'+c);
+			} else {
+				output_process(pty, c);
+			}
+		}
+		return;
+	}
 	if (pty->tios.c_lflag & ISIG) {
 		if (c == pty->tios.c_cc[VINTR]) {
 			if (pty->tios.c_lflag & ECHO) {
@@ -131,16 +149,51 @@ void tty_input_process(pty_t * pty, uint8_t c) {
 		/* VSTOP, VSTART */
 	}
 #endif
+
+	/* ISTRIP: Strip eighth bit */
+	if (pty->tios.c_iflag & ISTRIP) {
+		c &= 0x7F;
+	}
+
+	/* IGNCR: Ignore carriage return. */
+	if ((pty->tios.c_iflag & IGNCR) && c == '\r') {
+		return;
+	}
+
+	if ((pty->tios.c_iflag & INLCR) && c == '\n') {
+		/* INLCR: Translate NL to CR. */
+		c = '\r';
+	} else if ((pty->tios.c_iflag & ICRNL) && c == '\r') {
+		/* ICRNL: Convert carriage return. */
+		c = '\n';
+	}
+
 	if (pty->tios.c_lflag & ICANON) {
+
+		if (c == pty->tios.c_cc[VLNEXT] && (pty->tios.c_lflag & IEXTEN)) {
+			pty->next_is_verbatim = 1;
+			output_process(pty, '^');
+			output_process(pty, '\010');
+			return;
+		}
+
 		if (c == pty->tios.c_cc[VKILL]) {
 			while (pty->canon_buflen > 0) {
-				erase_one(pty);
+				erase_one(pty, pty->tios.c_lflag & ECHOK);
+			}
+			if ((pty->tios.c_lflag & ECHO) && ! (pty->tios.c_lflag & ECHOK)) {
+				output_process(pty, '^');
+				output_process(pty, '@' + c);
 			}
 			return;
 		}
 		if (c == pty->tios.c_cc[VERASE]) {
 			/* Backspace */
-			erase_one(pty);
+			erase_one(pty, pty->tios.c_lflag & ECHOE);
+			if ((pty->tios.c_lflag & ECHO) && ! (pty->tios.c_lflag & ECHOE)) {
+				output_process(pty, '^');
+				output_process(pty, '@' + c);
+			}
 			return;
 		}
 		if (c == pty->tios.c_cc[VEOF]) {
@@ -152,26 +205,6 @@ void tty_input_process(pty_t * pty, uint8_t c) {
 			return;
 		}
 
-		/* ISTRIP: Strip eighth bit */
-		if (pty->tios.c_iflag & ISTRIP) {
-			c &= 0x7F;
-		}
-
-		/* IGNCR: Ignore carriage return. */
-		if ((pty->tios.c_iflag & IGNCR) && c == '\r') {
-			return;
-		}
-
-		/* INLCR: Translate NL to CR. */
-		if ((pty->tios.c_iflag & INLCR) && c == '\n') {
-			c = '\r';
-		}
-
-		/* ICRNL: Convert carriage return. */
-		if ((pty->tios.c_iflag & ICRNL) && c == '\r') {
-			c = '\n';
-		}
-
 		if (pty->canon_buflen < pty->canon_bufsize) {
 			pty->canon_buffer[pty->canon_buflen] = c;
 			pty->canon_buflen++;
@@ -593,6 +626,8 @@ pty_t * pty_new(struct winsize * size) {
 
 	pty_t * pty = malloc(sizeof(pty_t));
 
+	pty->next_is_verbatim = 0;
+
 	/* stdin linkage; characters from terminal → PTY slave */
 	pty->in  = ring_buffer_create(TTY_BUFFER_SIZE);
 	pty->out = ring_buffer_create(TTY_BUFFER_SIZE);
@@ -640,6 +675,7 @@ pty_t * pty_new(struct winsize * size) {
 	pty->tios.c_cc[VSTOP]  = 19; /* ^S */
 	pty->tios.c_cc[VSUSP] = 26; /* ^Z */
 	pty->tios.c_cc[VTIME]  =  0;
+	pty->tios.c_cc[VLNEXT] = 22; /* ^V */
 
 	pty->canon_buffer  = malloc(TTY_BUFFER_SIZE);
 	pty->canon_bufsize = TTY_BUFFER_SIZE-2;