aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2014-04-07 23:32:29 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2014-04-13 16:02:59 +0200
commit69b114fb8a2566e14ce125f7736add9dacf6e18d (patch)
tree0cc71c61e0fc30d3349e686fbee545e6d56e528e /miscutils/less.c
parent32afd3aa6039b911816a68972b2366095cb777de (diff)
downloadbusybox-w32-69b114fb8a2566e14ce125f7736add9dacf6e18d.tar.gz
busybox-w32-69b114fb8a2566e14ce125f7736add9dacf6e18d.tar.bz2
busybox-w32-69b114fb8a2566e14ce125f7736add9dacf6e18d.zip
less: fix bugs discovered with "git log -p | less -m" on kernel tree
function old new delta read_lines 685 733 +48 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/miscutils/less.c b/miscutils/less.c
index 574f222e0..36d0a0bd9 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -404,6 +404,9 @@ static void fill_match_lines(unsigned pos);
404 * last_line_pos - screen line position of next char to be read 404 * last_line_pos - screen line position of next char to be read
405 * (takes into account tabs and backspaces) 405 * (takes into account tabs and backspaces)
406 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error 406 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
407 *
408 * "git log -p | less -m" on the kernel git tree is a good test for EAGAINs,
409 * "/search on very long input" and "reaching max line count" corner cases.
407 */ 410 */
408static void read_lines(void) 411static void read_lines(void)
409{ 412{
@@ -414,9 +417,13 @@ static void read_lines(void)
414#if ENABLE_FEATURE_LESS_REGEXP 417#if ENABLE_FEATURE_LESS_REGEXP
415 unsigned old_max_fline = max_fline; 418 unsigned old_max_fline = max_fline;
416 time_t last_time = 0; 419 time_t last_time = 0;
417 unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */ 420 int had_progress = 2;
418#endif 421#endif
419 422
423 /* (careful: max_fline can be -1) */
424 if (max_fline + 1 > MAXLINES)
425 return;
426
420 if (option_mask32 & FLAG_N) 427 if (option_mask32 & FLAG_N)
421 w -= 8; 428 w -= 8;
422 429
@@ -441,6 +448,7 @@ static void read_lines(void)
441 char c; 448 char c;
442 /* if no unprocessed chars left, eat more */ 449 /* if no unprocessed chars left, eat more */
443 if (readpos >= readeof) { 450 if (readpos >= readeof) {
451 errno = 0;
444 ndelay_on(0); 452 ndelay_on(0);
445 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); 453 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
446 ndelay_off(0); 454 ndelay_off(0);
@@ -448,6 +456,7 @@ static void read_lines(void)
448 readeof = eof_error; 456 readeof = eof_error;
449 if (eof_error <= 0) 457 if (eof_error <= 0)
450 goto reached_eof; 458 goto reached_eof;
459 had_progress = 1;
451 } 460 }
452 c = readbuf[readpos]; 461 c = readbuf[readpos];
453 /* backspace? [needed for manpages] */ 462 /* backspace? [needed for manpages] */
@@ -519,31 +528,23 @@ static void read_lines(void)
519#endif 528#endif
520 } 529 }
521 if (eof_error <= 0) { 530 if (eof_error <= 0) {
522 if (eof_error < 0) {
523 if (errno == EAGAIN) {
524 /* not yet eof or error, reset flag (or else
525 * we will hog CPU - select() will return
526 * immediately */
527 eof_error = 1;
528 } else {
529 print_statusline(bb_msg_read_error);
530 }
531 }
532#if !ENABLE_FEATURE_LESS_REGEXP 531#if !ENABLE_FEATURE_LESS_REGEXP
533 break; 532 break;
534#else 533#else
535 if (wanted_match < num_matches) { 534 if (wanted_match < num_matches) {
536 break; 535 break;
537 } else { /* goto_match called us */ 536 } /* else: goto_match() called us */
537 if (errno == EAGAIN) {
538 time_t t = time(NULL); 538 time_t t = time(NULL);
539 if (t != last_time) { 539 if (t != last_time) {
540 last_time = t; 540 last_time = t;
541 if (--seconds_p1 == 0) 541 if (--had_progress < 0)
542 break; 542 break;
543 } 543 }
544 sched_yield(); 544 sched_yield();
545 goto again0; /* go loop again (max 2 seconds) */ 545 goto again0;
546 } 546 }
547 break;
547#endif 548#endif
548 } 549 }
549 max_fline++; 550 max_fline++;
@@ -551,6 +552,15 @@ static void read_lines(void)
551 p = current_line; 552 p = current_line;
552 last_line_pos = 0; 553 last_line_pos = 0;
553 } /* end of "read lines until we reach cur_fline" loop */ 554 } /* end of "read lines until we reach cur_fline" loop */
555
556 if (eof_error < 0) {
557 if (errno == EAGAIN) {
558 eof_error = 1;
559 } else {
560 print_statusline(bb_msg_read_error);
561 }
562 }
563
554 fill_match_lines(old_max_fline); 564 fill_match_lines(old_max_fline);
555#if ENABLE_FEATURE_LESS_REGEXP 565#if ENABLE_FEATURE_LESS_REGEXP
556 /* prevent us from being stuck in search for a match */ 566 /* prevent us from being stuck in search for a match */