From d5aaacda5a4b6cbea654c0d0cca3c901b8dda3d3 Mon Sep 17 00:00:00 2001 From: Nguyễn Thái Ngọc Duy Date: Sat, 9 May 2009 16:52:07 +1000 Subject: introduce libbb/termios.c for terminal-related functions --- include/cygwin_termios.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++ libbb/Kbuild | 1 + libbb/lineedit.c | 68 +++-------------------------- libbb/termios.c | 73 +++++++++++++++++++++++++++++++ libbb/xfuncs.c | 21 +-------- 5 files changed, 189 insertions(+), 83 deletions(-) create mode 100644 include/cygwin_termios.h create mode 100644 libbb/termios.c diff --git a/include/cygwin_termios.h b/include/cygwin_termios.h new file mode 100644 index 000000000..b7ec2957f --- /dev/null +++ b/include/cygwin_termios.h @@ -0,0 +1,109 @@ +/* iflag bits */ +#define IGNBRK 0x00001 +#define BRKINT 0x00002 +#define IGNPAR 0x00004 +#define IMAXBEL 0x00008 +#define INPCK 0x00010 +#define ISTRIP 0x00020 +#define INLCR 0x00040 +#define IGNCR 0x00080 +#define ICRNL 0x00100 +#define IXON 0x00400 +#define IXOFF 0x01000 +#define IUCLC 0x04000 +#define IXANY 0x08000 +#define PARMRK 0x10000 + +/* oflag bits */ + +#define OPOST 0x00001 +#define OLCUC 0x00002 +#define OCRNL 0x00004 +#define ONLCR 0x00008 +#define ONOCR 0x00010 +#define ONLRET 0x00020 +#define OFILL 0x00040 +#define CRDLY 0x00180 +#define CR0 0x00000 +#define CR1 0x00080 +#define CR2 0x00100 +#define CR3 0x00180 +#define NLDLY 0x00200 +#define NL0 0x00000 +#define NL1 0x00200 +#define BSDLY 0x00400 +#define BS0 0x00000 +#define BS1 0x00400 +#define TABDLY 0x01800 +#define TAB0 0x00000 +#define TAB1 0x00800 +#define TAB2 0x01000 +#define TAB3 0x01800 +#define XTABS 0x01800 +#define VTDLY 0x02000 +#define VT0 0x00000 +#define VT1 0x02000 +#define FFDLY 0x04000 +#define FF0 0x00000 +#define FF1 0x04000 +#define OFDEL 0x08000 + +/* lflag bits */ +#define ISIG 0x0001 +#define ICANON 0x0002 +#define ECHO 0x0004 +#define ECHOE 0x0008 +#define ECHOK 0x0010 +#define ECHONL 0x0020 +#define NOFLSH 0x0040 +#define TOSTOP 0x0080 +#define IEXTEN 0x0100 +#define FLUSHO 0x0200 +#define ECHOKE 0x0400 +#define ECHOCTL 0x0800 + +#define VDISCARD 1 +#define VEOL 2 +#define VEOL2 3 +#define VEOF 4 +#define VERASE 5 +#define VINTR 6 +#define VKILL 7 +#define VLNEXT 8 +#define VMIN 9 +#define VQUIT 10 +#define VREPRINT 11 +#define VSTART 12 +#define VSTOP 13 +#define VSUSP 14 +#define VSWTC 15 +#define VTIME 16 +#define VWERASE 17 + +#define TCSAFLUSH 1 +#define TCSANOW 2 +#define TCSADRAIN 3 +#define TCSADFLUSH 4 + +typedef unsigned char cc_t; +typedef unsigned int tcflag_t; +typedef unsigned int speed_t; +typedef unsigned short otcflag_t; +typedef unsigned char ospeed_t; + +#define NCCS 18 +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + char c_line; + cc_t c_cc[NCCS]; + speed_t c_ispeed; + speed_t c_ospeed; +}; + +int tcgetattr(int fd, struct termios *t); +int tcsetattr(int fd, int mode, const struct termios *t); +int is_cygwin_tty(int fd); +int wincon_read(int fd, char *buf, int size); diff --git a/libbb/Kbuild b/libbb/Kbuild index e335a95dc..b3560bd0b 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild @@ -138,6 +138,7 @@ lib-$(CONFIG_MINGW32) += setenv.o lib-$(CONFIG_MINGW32) += strbuf.o lib-$(CONFIG_MINGW32) += strbuf_file.o lib-$(CONFIG_MINGW32) += strlcpy.o +lib-$(CONFIG_MINGW32) += termios.o lib-$(CONFIG_MINGW32) += trace.o lib-$(CONFIG_MINGW32) += usage.o lib-$(CONFIG_MINGW32) += winansi.o diff --git a/libbb/lineedit.c b/libbb/lineedit.c index b349bc6f2..e56dd20b0 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -59,28 +59,13 @@ #define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \ (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) - -static line_input_t *state; - #ifdef __MINGW32__ -struct termios { - int c_lflag; - int c_cc[3]; -}; -#define safe_read(fd,buf,n) wincon_read(fd,buf,n) -/* True value does not matter because it's emulated */ -#define ICANON 1 -#define ECHO 2 -#define ECHONL 4 -#define ISIG 8 - -#define VMIN 0 -#define VTIME 1 -#define VINTR 2 - -static int wincon_read(int fd, char *buf, int size); +#include "cygwin_termios.h" +#define safe_read(fd,buf,size) wincon_read(fd,buf,size) #endif +static line_input_t *state; + static struct termios initial_settings, new_settings; static volatile unsigned cmdedit_termw = 80; /* actual terminal width */ @@ -1227,13 +1212,10 @@ static void parse_prompt(const char *prmt_ptr) } #endif -#ifdef __MINGW32__ -#define setTermSettings(fd, argp) -#define getTermSettings(fd, argp) ((struct termios *)argp)->c_lflag = ECHO; -#else #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp) #define getTermSettings(fd, argp) tcgetattr(fd, argp); +#ifndef __MINGW32__ static sighandler_t previous_SIGWINCH_handler; #endif @@ -1770,46 +1752,6 @@ line_input_t *new_line_input_t(int flags) return n; } -#ifdef __MINGW32__ -#include -#include -#include "strbuf.h" - -#undef safe_read -static int wincon_read(int fd, char *buf, int size) -{ - static struct strbuf input = STRBUF_INIT; - HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); - static int initialized = 0; - - if (fd != 0) - die("wincon_read is for stdin only"); - if (cin == INVALID_HANDLE_VALUE) - return safe_read(fd, buf, size); - if (!initialized) { - SetConsoleMode(cin, ENABLE_ECHO_INPUT); - initialized = 1; - } - while (input.len < size) { - INPUT_RECORD record; - DWORD nevent = 0, nevent_out; - int ch; - - if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) - return -1; - if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) - continue; - ch = record.Event.KeyEvent.uChar.AsciiChar; - /* Ctrl-X is handled by ReadConsoleInput, Alt-X is not needed anyway */ - strbuf_addch(&input, ch); - } - memcpy(buf, input.buf, size); - memcpy(input.buf, input.buf+size, input.len-size+1); - strbuf_setlen(&input, input.len-size); - return size; -} -#endif - #else #undef read_line_input diff --git a/libbb/termios.c b/libbb/termios.c new file mode 100644 index 000000000..f47593a49 --- /dev/null +++ b/libbb/termios.c @@ -0,0 +1,73 @@ +#include "libbb.h" +#include +#include +#include "strbuf.h" +#include "cygwin_termios.h" + +int tcgetattr(int fd, struct termios *t) +{ + t->c_lflag = ECHO; + return 0; +} + + +int tcsetattr(int fd, int mode, const struct termios *t) +{ + return 0; +} + +static int get_wincon_width_height(const int fd, int *width, int *height) +{ + HANDLE console; + CONSOLE_SCREEN_BUFFER_INFO sbi; + + console = GetStdHandle(STD_OUTPUT_HANDLE); + if (console == INVALID_HANDLE_VALUE || !console) + return -1; + + GetConsoleScreenBufferInfo(console, &sbi); + + if (width) + *width = sbi.srWindow.Right - sbi.srWindow.Left; + if (height) + *height = sbi.srWindow.Bottom - sbi.srWindow.Top; + return 0; +} + +int get_terminal_width_height(const int fd, int *width, int *height) +{ + return get_wincon_width_height(fd, width, height); +} + +int wincon_read(int fd, char *buf, int size) +{ + static struct strbuf input = STRBUF_INIT; + HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); + static int initialized = 0; + + if (fd != 0) + die("wincon_read is for stdin only"); + if (cin == INVALID_HANDLE_VALUE || is_cygwin_tty(fd)) + return safe_read(fd, buf, size); + if (!initialized) { + SetConsoleMode(cin, ENABLE_ECHO_INPUT); + initialized = 1; + } + while (input.len < size) { + INPUT_RECORD record; + DWORD nevent_out; + int ch; + + if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) + return -1; + if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) + continue; + ch = record.Event.KeyEvent.uChar.AsciiChar; + /* Ctrl-X is handled by ReadConsoleInput, Alt-X is not needed anyway */ + strbuf_addch(&input, ch); + } + memcpy(buf, input.buf, size); + memcpy(input.buf, input.buf+size, input.len-size+1); + strbuf_setlen(&input, input.len-size); + return size; +} diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 06bba0fe3..3d0bec7ac 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -625,26 +625,7 @@ void selinux_or_die(void) /* It is perfectly ok to pass in a NULL for either width or for * height, in which case that value will not be set. */ -#ifdef __MINGW32__ -#include -int get_terminal_width_height(const int fd, int *width, int *height) -{ - HANDLE console; - CONSOLE_SCREEN_BUFFER_INFO sbi; - - console = GetStdHandle(STD_OUTPUT_HANDLE); - if (console == INVALID_HANDLE_VALUE || !console) - return -1; - - GetConsoleScreenBufferInfo(console, &sbi); - - if (width) - *width = sbi.srWindow.Right - sbi.srWindow.Left; - if (height) - *height = sbi.srWindow.Bottom - sbi.srWindow.Top; - return 0; -} -#else +#ifndef __MINGW32__ int get_terminal_width_height(const int fd, int *width, int *height) { struct winsize win = { 0, 0, 0, 0 }; -- cgit v1.2.3-55-g6feb