From e1237bfefdf8085732c00908b78aac9b3573121c Mon Sep 17 00:00:00 2001 From: Ken Pettit Date: Tue, 8 Jan 2019 08:21:39 -0600 Subject: [PATCH] apps/graphics/pdcurs34/nuttx and system/termcurses: This commit fixes two issues: 1. A memory corruption issue that occurs from a paste operation that would overflow the fixed buffer size for keyboard processing. 2. A stall in getch() processing when there are cached keycodes in the termcurses emulation (tcurses_vt100.c). --- graphics/pdcurs34/nuttx/pdckbd.c | 10 ++++++- include/system/termcurses.h | 14 +++++++++ system/termcurses/tcurses_vt100.c | 48 +++++++++++++++++++++++++++++-- system/termcurses/termcurses.c | 22 ++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/graphics/pdcurs34/nuttx/pdckbd.c b/graphics/pdcurs34/nuttx/pdckbd.c index 618564e62..acfcabc81 100644 --- a/graphics/pdcurs34/nuttx/pdckbd.c +++ b/graphics/pdcurs34/nuttx/pdckbd.c @@ -167,12 +167,20 @@ bool PDC_check_key(void) fd_set rfds; struct timeval tv; + /* Test the registered tcurs interface for cached characters */ + + ret = termcurses_checkkey(termstate->tcurs); + if (ret) + { + return true; + } + /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(termstate->in_fd, &rfds); - /* Wait up to five seconds. */ + /* Do not wait. */ tv.tv_sec = 0; tv.tv_usec = 0; diff --git a/include/system/termcurses.h b/include/system/termcurses.h index f3209bcff..26233be71 100644 --- a/include/system/termcurses.h +++ b/include/system/termcurses.h @@ -117,6 +117,10 @@ struct termcurses_ops_s /* Get a keycode value */ CODE int (*getkeycode)(FAR struct termcurses_s *dev, int *specialkey, int *keymodifers); + + /* Check for cached keycode value */ + + CODE bool (*checkkey)(FAR struct termcurses_s *dev); }; struct termcurses_dev_s @@ -229,6 +233,16 @@ int termcurses_getwinsize(FAR struct termcurses_s *term, FAR struct winsize *win int termcurses_getkeycode(FAR struct termcurses_s *term, FAR int *specialkey, FAR int *keymodifiers); +/************************************************************************************ + * Name: termcurses_checkkey + * + * Description: + * Check if there is a key waiting to be processed. + * + ************************************************************************************/ + +bool termcurses_checkkey(FAR struct termcurses_s *term); + #undef EXTERN #ifdef __cplusplus } diff --git a/system/termcurses/tcurses_vt100.c b/system/termcurses/tcurses_vt100.c index c49353d0b..b196ae989 100644 --- a/system/termcurses/tcurses_vt100.c +++ b/system/termcurses/tcurses_vt100.c @@ -107,6 +107,7 @@ static int tcurses_vt100_setattributes(FAR struct termcurses_s *dev, unsigned long attrib); static int tcurses_vt100_getkeycode(FAR struct termcurses_s *dev, FAR int *specialkey, FAR int *keymodifers); +static bool tcurses_vt100_checkkey(FAR struct termcurses_s *dev); /************************************************************************************ * Private Data @@ -120,7 +121,8 @@ static const struct termcurses_ops_s g_vt100_ops = tcurses_vt100_getwinsize, tcurses_vt100_setcolors, tcurses_vt100_setattributes, - tcurses_vt100_getkeycode + tcurses_vt100_getkeycode, + tcurses_vt100_checkkey }; /* VT100 terminal codes */ @@ -831,7 +833,7 @@ static int tcurses_vt100_getkeycode(FAR struct termcurses_s *dev, FAR int *speci { /* Get next bytes from input stream */ - priv->keycount = read(fd, priv->keybuf, sizeof(priv->keybuf)); + priv->keycount = read(fd, priv->keybuf, sizeof(priv->keybuf)-1); if (priv->keycount <= 0) { return -1; @@ -1047,6 +1049,48 @@ static int tcurses_vt100_getkeycode(FAR struct termcurses_s *dev, FAR int *speci return keycode; } +/************************************************************************************ + * Check if a key is cached for processing. + * + ************************************************************************************/ + +static bool tcurses_vt100_checkkey(FAR struct termcurses_s *dev) +{ + FAR struct tcurses_vt100_s *priv; + int ret; + int fd; + fd_set rfds; + struct timeval tv; + + priv = (FAR struct tcurses_vt100_s *) dev; + fd = priv->in_fd; + + /* Test for queued characters */ + + if (priv->keycount > 0) + { + return true; + } + + /* Watch stdin (fd 0) to see when it has input. */ + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + /* Wait up to 1000us for next character after ESC */ + + tv.tv_sec = 0; + tv.tv_usec = 0; + + ret = select(1, &rfds, NULL, NULL, &tv); + if (ret > 0) + { + return true; + } + + return false; +} + /************************************************************************************ * Public Functions ************************************************************************************/ diff --git a/system/termcurses/termcurses.c b/system/termcurses/termcurses.c index 898172bb1..71e9cbbef 100644 --- a/system/termcurses/termcurses.c +++ b/system/termcurses/termcurses.c @@ -272,3 +272,25 @@ int termcurses_getkeycode(FAR struct termcurses_s *term, FAR int *specialkey, return -1; } + +/************************************************************************************ + * Name: termcurses_checkkey + * + * Description: + * Check if there is a key waiting to be processed. + * + ************************************************************************************/ + +bool termcurses_checkkey(FAR struct termcurses_s *term) +{ + FAR struct termcurses_dev_s *dev = (FAR struct termcurses_dev_s *) term; + + /* Call the dev function */ + + if (dev->ops->checkkey) + { + return dev->ops->checkkey(term); + } + + return 0; +}