rdate: make it do something remotely sane, facing 32-bit time overflow
[oweals/busybox.git] / miscutils / less.c
index d7076dbbc78b66d284abc2fdffdc3d1306318d23..0b0a9aed4be26e7290d9813cf946e5b25e2d44ca 100644 (file)
@@ -87,7 +87,6 @@
 //config:        this option makes less perform a last-ditch effort to find it:
 //config:        position cursor to 999,999 and ask terminal to report real
 //config:        cursor position using "ESC [ 6 n" escape sequence, then read stdin.
-//config:
 //config:        This is not clean but helps a lot on serial lines and such.
 //config:
 //config:config FEATURE_LESS_DASHCMD
 //config:        less itself ('-' keyboard command).
 //config:
 //config:config FEATURE_LESS_LINENUMS
-//config:      bool "Enable dynamic switching of line numbers"
+//config:      bool "Enable -N (dynamic switching of line numbers)"
 //config:      default y
 //config:      depends on FEATURE_LESS_DASHCMD
-//config:      help
-//config:        Enables "-N" command.
+
+//applet:IF_LESS(APPLET(less, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_LESS) += less.o
 
 //usage:#define less_trivial_usage
 //usage:       "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
@@ -169,6 +170,7 @@ enum { pattern_valid = 0 };
 struct globals {
        int cur_fline; /* signed */
        int kbd_fd;  /* fd to get input from */
+       int kbd_fd_orig_flags;
        int less_gets_pos;
 /* last position in last line, taking into account tabs */
        size_t last_line_pos;
@@ -304,6 +306,8 @@ static void print_statusline(const char *str)
 static void less_exit(int code)
 {
        set_tty_cooked();
+       if (!(G.kbd_fd_orig_flags & O_NONBLOCK))
+               ndelay_off(kbd_fd);
        clear_line();
        if (code < 0)
                kill_myself_with_sig(- code); /* does not return */
@@ -1589,16 +1593,23 @@ static char opp_bracket(char bracket)
 
 static void match_right_bracket(char bracket)
 {
-       unsigned i;
+       unsigned i = cur_fline;
 
-       if (strchr(flines[cur_fline], bracket) == NULL) {
+       if (i >= max_fline
+        || strchr(flines[i], bracket) == NULL
+       ) {
                print_statusline("No bracket in top line");
                return;
        }
+
        bracket = opp_bracket(bracket);
-       for (i = cur_fline + 1; i < max_fline; i++) {
+       for (; i < max_fline; i++) {
                if (strchr(flines[i], bracket) != NULL) {
-                       buffer_line(i);
+                       /*
+                        * Line with matched right bracket becomes
+                        * last visible line
+                        */
+                       buffer_line(i - max_displayed_line);
                        return;
                }
        }
@@ -1607,16 +1618,22 @@ static void match_right_bracket(char bracket)
 
 static void match_left_bracket(char bracket)
 {
-       int i;
+       int i = cur_fline + max_displayed_line;
 
-       if (strchr(flines[cur_fline + max_displayed_line], bracket) == NULL) {
+       if (i >= max_fline
+        || strchr(flines[i], bracket) == NULL
+       ) {
                print_statusline("No bracket in bottom line");
                return;
        }
 
        bracket = opp_bracket(bracket);
-       for (i = cur_fline + max_displayed_line; i >= 0; i--) {
+       for (; i >= 0; i--) {
                if (strchr(flines[i], bracket) != NULL) {
+                       /*
+                        * Line with matched left bracket becomes
+                        * first visible line
+                        */
                        buffer_line(i);
                        return;
                }
@@ -1784,9 +1801,10 @@ int less_main(int argc, char **argv)
        /* Some versions of less can survive w/o controlling tty,
         * try to do the same. This also allows to specify an alternative
         * tty via "less 1<>TTY".
-        * We don't try to use STDOUT_FILENO directly,
+        *
+        * We prefer not to use STDOUT_FILENO directly,
         * since we want to set this fd to non-blocking mode,
-        * and not bother with restoring it on exit.
+        * and not interfere with other processes which share stdout with us.
         */
        tty_name = xmalloc_ttyname(STDOUT_FILENO);
        if (tty_name) {
@@ -1798,10 +1816,12 @@ int less_main(int argc, char **argv)
                /* Try controlling tty */
  try_ctty:
                tty_fd = open(CURRENT_TTY, O_RDONLY);
-               if (tty_fd < 0)
-                       return bb_cat(argv);
+               if (tty_fd < 0) {
+                       /* If all else fails, less 481 uses stdout. Mimic that */
+                       tty_fd = STDOUT_FILENO;
+               }
        }
-       ndelay_on(tty_fd);
+       G.kbd_fd_orig_flags = ndelay_on(tty_fd);
        kbd_fd = tty_fd; /* save in a global */
 
        tcgetattr(kbd_fd, &term_orig);