*/
//config:config LESS
-//config: bool "less"
+//config: bool "less (15 kb)"
//config: default y
//config: help
//config: 'less' is a pager, meaning that it displays text files. It possesses
//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")
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;
/* flines[] are lines read from stdin, each in malloc'ed buffer.
* Line numbers are stored as uint32_t prepended to each line.
* Pointer is adjusted so that flines[i] points directly past
- * line number. Accesor: */
+ * line number. Accessor: */
#define MEMPTR(p) ((char*)(p) - 4)
#define LINENO(p) (*(uint32_t*)((p) - 4))
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 */
*/
static void read_lines(void)
{
-#define readbuf bb_common_bufsiz1
-#define sizeof_readbuf COMMON_BUFSIZE
char *current_line, *p;
int w = width;
char last_terminated = terminated;
unsigned old_max_fline = max_fline;
#endif
+#define readbuf bb_common_bufsiz1
+ setup_common_bufsiz();
+
/* (careful: max_fline can be -1) */
if (max_fline + 1 > MAXLINES)
return;
time_t t;
errno = 0;
- eof_error = safe_read(STDIN_FILENO, readbuf, sizeof_readbuf);
+ eof_error = safe_read(STDIN_FILENO, readbuf, COMMON_BUFSIZE);
if (errno != EAGAIN)
break;
t = time(NULL);
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;
}
}
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;
}
/* 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) {
/* 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);