libbb: consolidate the code to set termios unbuffered mode
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 11 Jan 2017 15:17:59 +0000 (16:17 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 11 Jan 2017 15:17:59 +0000 (16:17 +0100)
function                                             old     new   delta
set_termios_to_raw                                     -     116    +116
count_lines                                           72      74      +2
powertop_main                                       1458    1430     -28
top_main                                             943     914     -29
more_main                                            759     714     -45
fsck_minix_main                                     2969    2921     -48
conspy_main                                         1197    1135     -62
rawmode                                               99      36     -63
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/6 up/down: 118/-275)         Total: -157 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
15 files changed:
editors/vi.c
include/libbb.h
libbb/lineedit.c
libbb/xfuncs.c
loginutils/getty.c
loginutils/vlock.c
miscutils/chat.c
miscutils/conspy.c
miscutils/microcom.c
miscutils/rx.c
procps/powertop.c
procps/top.c
shell/shell_common.c
util-linux/fsck_minix.c
util-linux/more.c

index b56b04bdd5e1f7c0eda63740c6fc105164d655fe..1e5ef44fb51804612c4a8e40073745d74cd7ce2c 100644 (file)
@@ -354,7 +354,7 @@ struct globals {
 #if ENABLE_FEATURE_VI_USE_SIGNALS
        sigjmp_buf restart;     // catch_sig()
 #endif
-       struct termios term_orig, term_vi; // remember what the cooked mode was
+       struct termios term_orig; // remember what the cooked mode was
 #if ENABLE_FEATURE_VI_COLON
        char *initial_cmds[3];  // currently 2 entries, NULL terminated
 #endif
@@ -462,7 +462,6 @@ struct globals {
 #define context_end    (G.context_end   )
 #define restart        (G.restart       )
 #define term_orig      (G.term_orig     )
-#define term_vi        (G.term_vi       )
 #define initial_cmds   (G.initial_cmds  )
 #define readbuffer     (G.readbuffer    )
 #define scr_out_buf    (G.scr_out_buf   )
@@ -2731,15 +2730,9 @@ static char *swap_context(char *p) // goto new context for '' command make this
 //----- Set terminal attributes --------------------------------
 static void rawmode(void)
 {
-       tcgetattr(0, &term_orig);
-       term_vi = term_orig;
-       term_vi.c_lflag &= (~ICANON & ~ECHO);   // leave ISIG on - allow intr's
-       term_vi.c_iflag &= (~IXON & ~ICRNL);
-       term_vi.c_oflag &= (~ONLCR);
-       term_vi.c_cc[VMIN] = 1;
-       term_vi.c_cc[VTIME] = 0;
-       erase_char = term_vi.c_cc[VERASE];
-       tcsetattr_stdin_TCSANOW(&term_vi);
+       // no TERMIOS_CLEAR_ISIG: leave ISIG on - allow signals
+       set_termios_to_raw(STDIN_FILENO, &term_orig, TERMIOS_RAW_CRNL);
+       erase_char = term_orig.c_cc[VERASE];
 }
 
 static void cookmode(void)
index abdc8c2b82174c9ac82c0b107d4bcca4ee021466..87f89c76d41aa7b738eac1d2c542b49a0c2bf9e3 100644 (file)
@@ -1438,6 +1438,10 @@ int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FU
 int get_terminal_width(int fd) FAST_FUNC;
 
 int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
+#define TERMIOS_CLEAR_ISIG (1 << 0)
+#define TERMIOS_RAW_CRNL   (1 << 1)
+#define TERMIOS_RAW_INPUT  (1 << 2)
+int set_termios_to_raw(int fd, struct termios *oldterm, int flags) FAST_FUNC;
 
 /* 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;
index 31e3921479b20f7d484b6eaf8a3dfcee16b8379a..2a5d4e704ac62a98634bd7034741f14e735e4019 100644 (file)
@@ -2325,7 +2325,7 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
        /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
        /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
        new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
-       /* reads would block only if < 1 char is available */
+       /* reads will block only if < 1 char is available */
        new_settings.c_cc[VMIN] = 1;
        /* no timeout (reads block forever) */
        new_settings.c_cc[VTIME] = 0;
index 45650edba528c58168656adacc314b71275f3062..98d3531d6221064d35f1f0daa5b56a4117a00176 100644 (file)
@@ -311,6 +311,43 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
        return tcsetattr(STDIN_FILENO, TCSANOW, tp);
 }
 
+int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags)
+{
+//TODO: lineedit, microcom and less might be adapted to use this too:
+// grep for "tcsetattr"
+
+       struct termios newterm;
+
+       tcgetattr(fd, oldterm);
+       newterm = *oldterm;
+
+       /* Turn off buffered input (ICANON)
+        * Turn off echoing (ECHO)
+        * and separate echoing of newline (ECHONL, normally off anyway)
+        */
+       newterm.c_lflag &= ~(ICANON | ECHO | ECHONL);
+       if (flags & TERMIOS_CLEAR_ISIG) {
+               /* dont recognize INT/QUIT/SUSP chars */
+               newterm.c_lflag &= ~ISIG;
+       }
+       /* reads will block only if < 1 char is available */
+       newterm.c_cc[VMIN] = 1;
+       /* no timeout (reads block forever) */
+       newterm.c_cc[VTIME] = 0;
+       if (flags & TERMIOS_RAW_CRNL) {
+               /* dont convert CR to NL on input */
+               newterm.c_iflag &= ~(IXON | ICRNL);
+               /* dont convert NL to CR on output */
+               newterm.c_oflag &= ~(ONLCR);
+       }
+       if (flags & TERMIOS_RAW_INPUT) {
+               /* dont convert anything on input */
+               newterm.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL);
+       }
+
+       return tcsetattr(fd, TCSANOW, &newterm);
+}
+
 pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
 {
        pid_t r;
index 162c1697edcdef0895c60b4b94b1afd9e71eebae..ba6c784a39dad84b65082b7f6d0f547269b6ff45 100644 (file)
@@ -316,7 +316,7 @@ static void init_tty_attrs(int speed)
        /* non-raw output; add CR to each NL */
        G.tty_attrs.c_oflag = OPOST | ONLCR;
 
-       /* reads would block only if < 1 char is available */
+       /* reads will block only if < 1 char is available */
        G.tty_attrs.c_cc[VMIN] = 1;
        /* no timeout (reads block forever) */
        G.tty_attrs.c_cc[VTIME] = 0;
index 52ae607c9e4717fc3d2251d6846e13b574607abd..5ba6a8780d610046148b47e6eb5fe37e4730091a 100644 (file)
@@ -105,12 +105,12 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
        ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
 #endif
 
+//TODO: use set_termios_to_raw()
        tcgetattr(STDIN_FILENO, &oterm);
        term = oterm;
-       term.c_iflag &= ~BRKINT;
-       term.c_iflag |= IGNBRK;
-       term.c_lflag &= ~ISIG;
-       term.c_lflag &= ~(ECHO | ECHOCTL);
+       term.c_iflag |= IGNBRK; /* ignore serial break (why? VTs don't have breaks, right?) */
+       term.c_iflag &= ~BRKINT; /* redundant? "dont translate break to SIGINT" */
+       term.c_lflag &= ~(ISIG | ECHO | ECHOCTL); /* ignore ^C ^Z, echo off */
        tcsetattr_stdin_TCSANOW(&term);
 
        while (1) {
index dc85f82fbaab219cdd556237045b69f46b28d18e..8df194534181e557f898f8a5431dfc074827902b 100644 (file)
@@ -213,6 +213,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
                , signal_handler);
 
 #if ENABLE_FEATURE_CHAT_TTY_HIFI
+//TODO: use set_termios_to_raw()
        tcgetattr(STDIN_FILENO, &tio);
        tio0 = tio;
        cfmakeraw(&tio);
index d9d09d482bae75e72c300131ee950893a0d34091..1f0278b47b87fe065739f5963db348e6e89d1f2e 100644 (file)
@@ -363,7 +363,6 @@ int conspy_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int conspy_main(int argc UNUSED_PARAM, char **argv)
 {
        char tty_name[sizeof(DEV_TTY "NN")];
-       struct termios termbuf;
        unsigned opts;
        unsigned ttynum;
        int poll_timeout_ms;
@@ -414,16 +413,14 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 
        bb_signals(BB_FATAL_SIGS, cleanup);
 
-       // All characters must be passed through to us unaltered
        G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY);
-       tcgetattr(G.kbd_fd, &G.term_orig);
-       termbuf = G.term_orig;
-       termbuf.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL);
-       //termbuf.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n
-       termbuf.c_lflag &= ~(ISIG|ICANON|ECHO);
-       termbuf.c_cc[VMIN] = 1;
-       termbuf.c_cc[VTIME] = 0;
-       tcsetattr(G.kbd_fd, TCSANOW, &termbuf);
+
+       // All characters must be passed through to us unaltered
+       set_termios_to_raw(G.kbd_fd, &G.term_orig, 0
+               | TERMIOS_CLEAR_ISIG // no signals on ^C ^Z etc
+               | TERMIOS_RAW_INPUT  // turn off all input conversions
+       );
+       //Note: termios.c_oflag &= ~(OPOST); - no, we still want \n -> \r\n
 
        poll_timeout_ms = 250;
        while (1) {
index 04605d883a83e9802e65890290422c635d1cd9d8..5a4bbefa92425aeb02964b7df844a2849083ef24 100644 (file)
@@ -33,6 +33,7 @@
 // set raw tty mode
 static void xget1(int fd, struct termios *t, struct termios *oldt)
 {
+//TODO: use set_termios_to_raw()
        tcgetattr(fd, oldt);
        *t = *oldt;
        cfmakeraw(t);
index 660f66a89d70df4ac46ce4177ee3f7c4f950614f..36fc20a72e978270ad3e158475d0bf4ccd0ec87c 100644 (file)
@@ -263,6 +263,7 @@ int rx_main(int argc UNUSED_PARAM, char **argv)
 
        termios_err = tcgetattr(read_fd, &tty);
        if (termios_err == 0) {
+//TODO: use set_termios_to_raw()
                orig_tty = tty;
                cfmakeraw(&tty);
                tcsetattr(read_fd, TCSAFLUSH, &tty);
index ce85f4191e0f605dfd67e1f00f072956201a4b92..ee806161f3a47fd835020e31b8c7cc7d4803ebe9 100644 (file)
@@ -683,7 +683,6 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
        ullong cur_duration[MAX_CSTATE_COUNT];
        char cstate_lines[MAX_CSTATE_COUNT + 2][64];
 #if ENABLE_FEATURE_USE_TERMIOS
-       struct termios new_settings;
        struct pollfd pfd[1];
 
        pfd[0].fd = 0;
@@ -707,14 +706,11 @@ int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
        puts("Collecting data for "DEFAULT_SLEEP_STR" seconds");
 
 #if ENABLE_FEATURE_USE_TERMIOS
-       tcgetattr(0, (void *)&G.init_settings);
-       memcpy(&new_settings, &G.init_settings, sizeof(new_settings));
-       /* Turn on unbuffered input, turn off echoing */
-       new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
+       /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */
+       set_termios_to_raw(STDIN_FILENO, &G.init_settings, TERMIOS_CLEAR_ISIG);
+       bb_signals(BB_FATAL_SIGS, sig_handler);
        /* So we don't forget to reset term settings */
        atexit(reset_term);
-       bb_signals(BB_FATAL_SIGS, sig_handler);
-       tcsetattr_stdin_TCSANOW(&new_settings);
 #endif
 
        /* Collect initial data */
index 491acb574938c95bb9f086a0fe3bf654ed8376ff..91bb8a88379cdf7a9c1c233f79c959cf97bbfd19 100644 (file)
@@ -1089,9 +1089,6 @@ int top_main(int argc UNUSED_PARAM, char **argv)
        unsigned interval;
        char *str_interval, *str_iterations;
        unsigned scan_mask = TOP_MASK;
-#if ENABLE_FEATURE_USE_TERMIOS
-       struct termios new_settings;
-#endif
 
        INIT_G();
 
@@ -1141,11 +1138,8 @@ int top_main(int argc UNUSED_PARAM, char **argv)
        }
 #if ENABLE_FEATURE_USE_TERMIOS
        else {
-               tcgetattr(0, (void *) &initial_settings);
-               memcpy(&new_settings, &initial_settings, sizeof(new_settings));
-               /* unbuffered input, turn off echo */
-               new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
-               tcsetattr_stdin_TCSANOW(&new_settings);
+               /* Turn on unbuffered input; turn off echoing, ^C ^Z etc */
+               set_termios_to_raw(STDIN_FILENO, &initial_settings, TERMIOS_CLEAR_ISIG);
        }
 
        bb_signals(BB_FATAL_SIGS, sig_catcher);
index 98d862744432d25be36bceeac57e3de12a612a5f..549b17ca11252b86c9aed8c17482a2e085a937ea 100644 (file)
@@ -143,7 +143,7 @@ shell_builtin_read(void FAST_FUNC (*setvar)(const char *name, const char *val),
                        // Setting it to more than 1 breaks poll():
                        // it blocks even if there's data. !??
                        //tty.c_cc[VMIN] = nchars < 256 ? nchars : 255;
-                       /* reads would block only if < 1 char is available */
+                       /* reads will block only if < 1 char is available */
                        tty.c_cc[VMIN] = 1;
                        /* no timeout (reads block forever) */
                        tty.c_cc[VTIME] = 0;
index 0eaac17c0f1871562485e3613c6d174d45110b9d..2ab7530ea2057c596caca2e069bfad43fa0763c8 100644 (file)
@@ -1226,7 +1226,6 @@ void check2(void);
 int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
 {
-       struct termios tmp;
        int retcode = 0;
 
        xfunc_error_retval = 8;
@@ -1271,10 +1270,7 @@ int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
        read_tables();
 
        if (OPT_manual) {
-               tcgetattr(0, &sv_termios);
-               tmp = sv_termios;
-               tmp.c_lflag &= ~(ICANON | ECHO);
-               tcsetattr_stdin_TCSANOW(&tmp);
+               set_termios_to_raw(STDIN_FILENO, &sv_termios, 0);
                termios_set = 1;
        }
 
index 7fa60bdba56f87625fe1b0c27496e8e7a19a83f7..debad81bd8e84b75d8eff695e43680794f8c0dd8 100644 (file)
@@ -43,7 +43,6 @@ struct globals {
        unsigned terminal_width;
        unsigned terminal_height;
        struct termios initial_settings;
-       struct termios new_settings;
 } FIX_ALIASING;
 #define G (*(struct globals*)bb_common_bufsiz1)
 #define INIT_G() do { setup_common_bufsiz(); } while (0)
@@ -101,12 +100,9 @@ int more_main(int argc UNUSED_PARAM, char **argv)
                return bb_cat(argv);
 
        G.tty_fileno = fileno(tty);
-       tcgetattr(G.tty_fileno, &G.initial_settings);
-       G.new_settings = G.initial_settings;
-       G.new_settings.c_lflag &= ~(ICANON | ECHO);
-       G.new_settings.c_cc[VMIN] = 1;
-       G.new_settings.c_cc[VTIME] = 0;
-       tcsetattr_tty_TCSANOW(&G.new_settings);
+
+       /* Turn on unbuffered input; turn off echoing */
+       set_termios_to_raw(G.tty_fileno, &G.initial_settings, 0);
        bb_signals(BB_FATAL_SIGS, gotsig);
 
        do {