Revise terminal control code to use ioctls supported by GNO instead of termios calls that aren't supported.

This commit is contained in:
Stephen Heumann 2014-11-04 19:53:40 -06:00
parent 7e5a584f0c
commit a3c32aaa73
4 changed files with 66 additions and 6 deletions

View File

@ -35,6 +35,16 @@
#undef basename
#define basename dont_use_basename
#include "poll.h"
/* Don't include termios.h in GNO because termios isn't actually implemented,
* but the header has a define for ECHO that conflicts with the one needed for
* the ioctls that we use instead. Do define USE_OLD_TTY before including
* <sys/ioctl.h>, which is needed to get defines for those ioctls.
*/
#ifndef __GNO__
# include <termios.h>
#else
# define USE_OLD_TTY
#endif
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
@ -44,7 +54,6 @@
# include <sys/sysmacros.h>
#endif
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <sys/param.h>
#include <pwd.h>
@ -119,9 +128,6 @@
#ifndef HAVE_FDATASYNC
# define fdatasync fsync
#endif
#ifndef HAVE_XTABS
# define XTABS TAB3
#endif
/* Some libc's forget to declare these, do it ourself */
@ -1115,8 +1121,6 @@ extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC;
extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC;
#endif
extern void erase_mtab(const char * name) FAST_FUNC;
extern unsigned int tty_baud_to_value(speed_t speed) FAST_FUNC;
extern speed_t tty_value_to_baud(unsigned int value) FAST_FUNC;
#if ENABLE_DESKTOP
extern void bb_warn_ignoring_args(char *arg) FAST_FUNC;
#else
@ -1269,7 +1273,9 @@ char *xmalloc_ttyname(int fd) FAST_FUNC RETURNS_MALLOC;
/* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */
int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC;
#ifndef __GNO__
int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
#endif
/* NB: "unsigned request" is crucial! "int request" will break some arches! */
int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC;

View File

@ -2247,14 +2247,24 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
#if ENABLE_FEATURE_EDITING_VI
smallint vi_cmdmode = 0;
#endif
#ifndef __GNO__
struct termios initial_settings;
struct termios new_settings;
#else
struct sgttyb initial_settings;
struct sgttyb new_settings;
#endif
char read_key_buffer[KEYCODE_BUFFER_SIZE];
INIT_S();
#ifndef __GNO__
if (tcgetattr(STDIN_FILENO, &initial_settings) < 0
|| !(initial_settings.c_lflag & ECHO)
#else
if (ioctl(STDIN_FILENO, TIOCGETP, &initial_settings) < 0
|| !(initial_settings.sg_flags & ECHO)
#endif
) {
/* Happens when e.g. stty -echo was run before */
parse_and_put_prompt(prompt);
@ -2298,6 +2308,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
#define command command_must_not_be_used
new_settings = initial_settings;
#ifndef __GNO__
/* ~ICANON: unbuffered input (most c_cc[] are disabled, VMIN/VTIME are enabled) */
/* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
/* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
@ -2310,6 +2321,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
/* Turn off CTRL-C */
/* new_settings.c_cc[VINTR] = _POSIX_VDISABLE; */
tcsetattr_stdin_TCSANOW(&new_settings);
#else
new_settings.sg_flags |= CBREAK;
new_settings.sg_flags &= ~ECHO;
ioctl(STDIN_FILENO, TIOCSETN, &new_settings);
#endif
#if ENABLE_USERNAME_OR_HOMEDIR
{
@ -2682,8 +2698,12 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
break;
default:
#ifndef __GNO__
if (initial_settings.c_cc[VINTR] != 0
&& ic_raw == initial_settings.c_cc[VINTR]
#else
if (ic_raw == CINTR
#endif
) {
/* Ctrl-C (usually) - stop gathering input */
goto_new_line();
@ -2691,8 +2711,12 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
break_out = -1; /* "do not append '\n'" */
break;
}
#ifndef __GNO__
if (initial_settings.c_cc[VEOF] != 0
&& ic_raw == initial_settings.c_cc[VEOF]
#else
if (ic_raw == CEOF
#endif
) {
/* Ctrl-D (usually) - delete one character,
* or exit if len=0 and no chars to delete */
@ -2806,7 +2830,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
#endif
/* restore initial_settings */
#ifndef __GNO__
tcsetattr_stdin_TCSANOW(&initial_settings);
#else
ioctl(STDIN_FILENO, TIOCSETN, &initial_settings);
#endif
/* restore SIGWINCH handler */
signal(SIGWINCH, previous_SIGWINCH_handler);
fflush_all();

View File

@ -277,10 +277,12 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
return err;
}
#ifndef __GNO__
int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
{
return tcsetattr(STDIN_FILENO, TCSANOW, tp);
}
#endif
pid_t FAST_FUNC safe_waitpid(pid_t pid, wait_status_t *wstat, int options)
{

View File

@ -62,7 +62,11 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
int nchars; /* -n NUM */
char **pp;
char *buffer;
#ifndef __GNO__
struct termios tty, old_tty;
#else
struct sgttyb tty, old_tty;
#endif
const char *retval;
int bufpos; /* need to be able to hold -1 */
int startword;
@ -134,9 +138,14 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
ifs = defifs;
if (nchars || (read_flags & BUILTIN_READ_SILENT)) {
#ifndef __GNO__
tcgetattr(fd, &tty);
#else
ioctl(fd, TIOCGETP, &tty);
#endif
old_tty = tty;
if (nchars) {
#ifndef __GNO__
tty.c_lflag &= ~ICANON;
// Setting it to more than 1 breaks poll():
// it blocks even if there's data. !??
@ -145,15 +154,26 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
tty.c_cc[VMIN] = 1;
/* no timeout (reads block forever) */
tty.c_cc[VTIME] = 0;
#else
tty.sg_flags |= CBREAK;
#endif
}
if (read_flags & BUILTIN_READ_SILENT) {
#ifndef __GNO__
tty.c_lflag &= ~(ECHO | ECHOK | ECHONL);
#else
tty.sg_flags &= ~ECHO;
#endif
}
/* This forces execution of "restoring" tcgetattr later */
read_flags |= BUILTIN_READ_SILENT;
/* if tcgetattr failed, tcsetattr will fail too.
* Ignoring, it's harmless. */
#ifndef __GNO__
tcsetattr(fd, TCSANOW, &tty);
#else
ioctl(fd, TIOCSETN, &tty);
#endif
}
retval = (const char *)(uintptr_t)0;
@ -267,7 +287,11 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
ret:
free(buffer);
if (read_flags & BUILTIN_READ_SILENT)
#ifndef __GNO__
tcsetattr(fd, TCSANOW, &old_tty);
#else
ioctl(fd, TIOCSETN, &old_tty);
#endif
errno = err;
return retval;