common: Minor rework of tty_get.

* common/ttyio.c (do_get): Re-indent and remove the checking for char
values larger than 0xa0.  Use explicy control character checking.
--

The code is really old (mid 1998) and with the checking for 0xa0 it
has an implicit assumption of utf-8 or latin-1.  Worse, the check was
for c > 0xa0 and not c == 0xa0 so it never worked as intended.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-03-07 14:11:46 +01:00
parent 134c3c1652
commit b7de105e0a
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 141 additions and 117 deletions

View File

@ -404,163 +404,187 @@ tty_print_utf8_string( const byte *p, size_t n )
static char * static char *
do_get( const char *prompt, int hidden ) do_get( const char *prompt, int hidden )
{ {
char *buf; char *buf;
#ifndef __riscos__ #ifndef __riscos__
byte cbuf[1]; byte cbuf[1];
#endif #endif
int c, n, i; int c, n, i;
if( batchmode ) { if (batchmode)
log_error("Sorry, we are in batchmode - can't get input\n"); {
exit(2); log_error ("Sorry, we are in batchmode - can't get input\n");
exit (2);
} }
if (no_terminal) { if (no_terminal)
log_error("Sorry, no terminal at all requested - can't get input\n"); {
exit(2); log_error ("Sorry, no terminal at all requested - can't get input\n");
exit (2);
} }
if( !initialized ) if (!initialized)
init_ttyfp(); init_ttyfp ();
last_prompt_len = 0; last_prompt_len = 0;
tty_printf( "%s", prompt ); tty_printf ("%s", prompt);
buf = xmalloc((n=50)); buf = xmalloc ((n=50));
i = 0; i = 0;
#ifdef USE_W32_CONSOLE #ifdef USE_W32_CONSOLE
if( hidden ) if (hidden)
SetConsoleMode(con.in, HID_INPMODE ); SetConsoleMode(con.in, HID_INPMODE );
for(;;) { for (;;)
DWORD nread; {
DWORD nread;
if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) ) if (!ReadConsoleA( con.in, cbuf, 1, &nread, NULL))
log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() ); log_fatal ("ReadConsole failed: rc=%d", (int)GetLastError ());
if( !nread ) if (!nread)
continue; continue;
if( *cbuf == '\n' ) if (*cbuf == '\n')
break; break;
if( !hidden ) if (!hidden)
last_prompt_len++; last_prompt_len++;
c = *cbuf; c = *cbuf;
if( c == '\t' ) if (c == '\t')
c = ' '; c = ' ';
else if( c > 0xa0 ) else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
; /* we don't allow 0xa0, as this is a protected blank which may continue;
* confuse the user */ if (!(i < n-1))
else if( iscntrl(c) ) {
continue; n += 50;
if( !(i < n-1) ) { buf = xrealloc (buf, n);
n += 50; }
buf = xrealloc (buf, n); buf[i++] = c;
}
buf[i++] = c;
} }
if( hidden ) if (hidden)
SetConsoleMode(con.in, DEF_INPMODE ); SetConsoleMode(con.in, DEF_INPMODE );
#elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM) #elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
do { do
{
#ifdef HAVE_W32CE_SYSTEM #ifdef HAVE_W32CE_SYSTEM
/* Using getchar is not a correct solution but for now it /* Using getchar is not a correct solution but for now it
doesn't matter because we have no real console at all. We doesn't matter because we have no real console at all. We
should rework this as soon as we have switched this entire should rework this as soon as we have switched this entire
module to estream. */ module to estream. */
c = getchar(); c = getchar();
#else #else
c = riscos_getchar(); c = riscos_getchar();
#endif #endif
if (c == 0xa || c == 0xd) { /* Return || Enter */ if (c == 0xa || c == 0xd) /* Return || Enter */
c = (int) '\n'; {
} else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */ c = (int) '\n';
if (i>0) { }
i--; else if (c == 0x8 || c == 0x7f) /* Backspace || Delete */
if (!hidden) { {
last_prompt_len--; if (i>0)
fputc(8, ttyfp); {
fputc(32, ttyfp); i--;
fputc(8, ttyfp); if (!hidden)
fflush(ttyfp); {
last_prompt_len--;
fputc(8, ttyfp);
fputc(32, ttyfp);
fputc(8, ttyfp);
fflush(ttyfp);
} }
} else {
fputc(7, ttyfp);
fflush(ttyfp);
} }
continue; else
} else if (c == (int) '\t') { /* Tab */ {
c = ' '; fputc(7, ttyfp);
} else if (c > 0xa0) { fflush(ttyfp);
; /* we don't allow 0xa0, as this is a protected blank which may }
* confuse the user */ continue;
} else if (iscntrl(c)) {
continue;
} }
if(!(i < n-1)) { else if (c == (int) '\t') /* Tab */
n += 50; {
buf = xrealloc (buf, n); c = ' ';
} }
buf[i++] = c; else if (c > 0xa0)
if (!hidden) { {
last_prompt_len++; ; /* we don't allow 0xa0, as this is a protected blank which may
fputc(c, ttyfp); * confuse the user */
fflush(ttyfp);
} }
} while (c != '\n'); else if (iscntrl(c))
i = (i>0) ? i-1 : 0; {
#else /* Other systems. */ continue;
if( hidden ) { }
#ifdef HAVE_TCGETATTR if (!(i < n-1))
struct termios term; {
n += 50;
buf = xrealloc (buf, n);
}
buf[i++] = c;
if (!hidden)
{
last_prompt_len++;
fputc(c, ttyfp);
fflush(ttyfp);
}
}
while (c != '\n');
i = (i>0) ? i-1 : 0;
if( tcgetattr(fileno(ttyfp), &termsave) ) #else /* Other systems. */
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
restore_termios = 1; if (hidden)
term = termsave; {
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); #ifdef HAVE_TCGETATTR
if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) ) struct termios term;
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
if (tcgetattr(fileno(ttyfp), &termsave))
log_fatal("tcgetattr() failed: %s\n", strerror(errno));
restore_termios = 1;
term = termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if (tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno));
#endif #endif
} }
/* fixme: How can we avoid that the \n is echoed w/o disabling /* fixme: How can we avoid that the \n is echoed w/o disabling
* canonical mode - w/o this kill_prompt can't work */ * canonical mode - w/o this kill_prompt can't work */
while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) { while (read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n')
if( !hidden ) {
last_prompt_len++; if (!hidden)
c = *cbuf; last_prompt_len++;
if( c == CONTROL_D ) c = *cbuf;
log_info("control d found\n"); if (c == CONTROL_D)
if( c == '\t' ) log_info ("Control-D detected\n");
c = ' ';
else if( c > 0xa0 ) if (c == '\t') /* Map tab to a space. */
; /* we don't allow 0xa0, as this is a protected blank which may c = ' ';
* confuse the user */ else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
else if( iscntrl(c) ) continue; /* Skip all other ASCII control characters. */
continue; if (!(i < n-1))
if( !(i < n-1) ) { {
n += 50; n += 50;
buf = xrealloc (buf, n ); buf = xrealloc (buf, n);
} }
buf[i++] = c; buf[i++] = c;
} }
if( *cbuf != '\n' ) { if (*cbuf != '\n')
buf[0] = CONTROL_D; {
i = 1; buf[0] = CONTROL_D;
i = 1;
} }
if( hidden ) { if (hidden)
{
#ifdef HAVE_TCGETATTR #ifdef HAVE_TCGETATTR
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) ) if (tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave))
log_error("tcsetattr() failed: %s\n", strerror(errno) ); log_error ("tcsetattr() failed: %s\n", strerror(errno));
restore_termios = 0; restore_termios = 0;
#endif #endif
} }
#endif /* end unix version */ #endif /* end unix version */
buf[i] = 0;
return buf; buf[i] = 0;
return buf;
} }