Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751515AbdDAJnm (ORCPT ); Sat, 1 Apr 2017 05:43:42 -0400 Received: from tartarus.angband.pl ([89.206.35.136]:50625 "EHLO tartarus.angband.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751440AbdDAJnk (ORCPT ); Sat, 1 Apr 2017 05:43:40 -0400 From: Adam Borowski To: linux-kernel@vger.kernel.org Cc: Adam Borowski Date: Sat, 1 Apr 2017 11:43:34 +0200 Message-Id: <20170401094337.4367-1-kilobyte@angband.pl> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170401094231.cimb5lz43eo34jfp@angband.pl> References: <20170401094231.cimb5lz43eo34jfp@angband.pl> X-SA-Exim-Connect-IP: 2001:6a0:118::6 X-SA-Exim-Mail-From: kilobyte@angband.pl Subject: [PATCH 1/4] n_tty: don't mangle tty codes in OLCUC mode X-SA-Exim-Version: 4.2.1 (built Tue, 02 Aug 2016 21:08:31 +0000) X-SA-Exim-Scanned: Yes (on tartarus.angband.pl) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3345 Lines: 120 Any terminal younger than ~40 years requires lowercase commands, thus they need to be exempt from uppercasing. And Linux doesn't really support ancient all-uppercase terminals anyway (no XCASE, etc) even if someone made the effort to somehow connect them electrically. This bug is reproducible as of Linux 0.11 and I see it in 0.01 sources (whose images fail to boot for me, I didn't try very hard). It was less of a failure then as the shell didn't produce tty codes for normal operation. Signed-off-by: Adam Borowski --- drivers/tty/n_tty.c | 58 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index bdf0e6e89991..bbc9f07c19fa 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -87,6 +87,8 @@ # define n_tty_trace(f, args...) #endif +enum { ESnormal, ESesc, EScsi, ESsetG }; + struct n_tty_data { /* producer-published */ size_t read_head; @@ -121,6 +123,7 @@ struct n_tty_data { unsigned int column; unsigned int canon_column; size_t echo_tail; + unsigned int vt_state; struct mutex atomic_read_lock; struct mutex output_lock; @@ -392,6 +395,40 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty) return I_IUTF8(tty) && is_utf8_continuation(c); } +/* process one OLCUC char (possibly partial unicode) + * + * We need to partially parse ANSI sequences to avoid uppercasing them; + * only some commands require lowercase. + */ + +static int do_olcuc_char(unsigned char c, struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + switch (ldata->vt_state) { + case ESesc: + ldata->vt_state = (c == '[') ? EScsi : + strchr("%()*+-./", c) ? ESsetG : ESnormal; + break; + case EScsi: + if (!strchr("?;0123456789>!c$\" \\", c)) + ldata->vt_state = ESnormal; + break; + case ESsetG: + ldata->vt_state = ESnormal; + break; + default: + if (c == '\e') + ldata->vt_state = ESesc; + else if (c >= 'a' && c <= 'z') + c -= 32; + } + if (!iscntrl(c) && !is_continuation(c, tty)) + ldata->column++; + tty_put_char(tty, c); + return 1; +} + /** * do_output_char - output one character * @c: character (or partial unicode symbol) @@ -462,12 +499,10 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space) ldata->column--; break; default: - if (!iscntrl(c)) { - if (O_OLCUC(tty)) - c = toupper(c); - if (!is_continuation(c, tty)) - ldata->column++; - } + if (O_OLCUC(tty)) + return do_olcuc_char(c, tty); + if (!iscntrl(c) && !is_continuation(c, tty)) + ldata->column++; break; } @@ -568,12 +603,10 @@ static ssize_t process_output_block(struct tty_struct *tty, ldata->column--; break; default: - if (!iscntrl(c)) { - if (O_OLCUC(tty)) - goto break_out; - if (!is_continuation(c, tty)) - ldata->column++; - } + if (O_OLCUC(tty)) + goto break_out; + if (!iscntrl(c) && !is_continuation(c, tty)) + ldata->column++; break; } } @@ -1895,6 +1928,7 @@ static int n_tty_open(struct tty_struct *tty) ldata->num_overrun = 0; ldata->no_room = 0; ldata->lnext = 0; + ldata->vt_state = ESnormal; tty->closing = 0; /* indicate buffer work may resume */ clear_bit(TTY_LDISC_HALTED, &tty->flags); -- 2.11.0