aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c69
1 files changed, 38 insertions, 31 deletions
diff --git a/miscutils/less.c b/miscutils/less.c
index d84df469c..554e54687 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -414,10 +414,10 @@ static void read_lines(void)
414 char *current_line, *p; 414 char *current_line, *p;
415 int w = width; 415 int w = width;
416 char last_terminated = terminated; 416 char last_terminated = terminated;
417 time_t last_time = 0;
418 int retry_EAGAIN = 2;
417#if ENABLE_FEATURE_LESS_REGEXP 419#if ENABLE_FEATURE_LESS_REGEXP
418 unsigned old_max_fline = max_fline; 420 unsigned old_max_fline = max_fline;
419 time_t last_time = 0;
420 int had_progress = 2;
421#endif 421#endif
422 422
423 /* (careful: max_fline can be -1) */ 423 /* (careful: max_fline can be -1) */
@@ -427,17 +427,14 @@ static void read_lines(void)
427 if (option_mask32 & FLAG_N) 427 if (option_mask32 & FLAG_N)
428 w -= 8; 428 w -= 8;
429 429
430 IF_FEATURE_LESS_REGEXP(again0:)
431
432 p = current_line = ((char*)xmalloc(w + 4)) + 4; 430 p = current_line = ((char*)xmalloc(w + 4)) + 4;
433 max_fline += last_terminated;
434 if (!last_terminated) { 431 if (!last_terminated) {
435 const char *cp = flines[max_fline]; 432 const char *cp = flines[max_fline];
436 strcpy(p, cp); 433 p = stpcpy(p, cp);
437 p += strlen(current_line); 434 free(MEMPTR(cp));
438 free(MEMPTR(flines[max_fline]));
439 /* last_line_pos is still valid from previous read_lines() */ 435 /* last_line_pos is still valid from previous read_lines() */
440 } else { 436 } else {
437 max_fline++;
441 last_line_pos = 0; 438 last_line_pos = 0;
442 } 439 }
443 440
@@ -448,15 +445,29 @@ static void read_lines(void)
448 char c; 445 char c;
449 /* if no unprocessed chars left, eat more */ 446 /* if no unprocessed chars left, eat more */
450 if (readpos >= readeof) { 447 if (readpos >= readeof) {
451 errno = 0; 448 int flags = ndelay_on(0);
452 ndelay_on(0); 449
453 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); 450 while (1) {
454 ndelay_off(0); 451 time_t t;
452
453 errno = 0;
454 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
455 if (errno != EAGAIN)
456 break;
457 t = time(NULL);
458 if (t != last_time) {
459 last_time = t;
460 if (--retry_EAGAIN < 0)
461 break;
462 }
463 sched_yield();
464 }
465 fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
455 readpos = 0; 466 readpos = 0;
456 readeof = eof_error; 467 readeof = eof_error;
457 if (eof_error <= 0) 468 if (eof_error <= 0)
458 goto reached_eof; 469 goto reached_eof;
459 IF_FEATURE_LESS_REGEXP(had_progress = 1;) 470 retry_EAGAIN = 1;
460 } 471 }
461 c = readbuf[readpos]; 472 c = readbuf[readpos];
462 /* backspace? [needed for manpages] */ 473 /* backspace? [needed for manpages] */
@@ -491,6 +502,11 @@ static void read_lines(void)
491 *p++ = c; 502 *p++ = c;
492 *p = '\0'; 503 *p = '\0';
493 } /* end of "read chars until we have a line" loop */ 504 } /* end of "read chars until we have a line" loop */
505#if 0
506//BUG: also triggers on this:
507// { printf "\nfoo\n"; sleep 1; printf "\nbar\n"; } | less
508// (resulting in lost empty line between "foo" and "bar" lines)
509// the "terminated" logic needs fixing (or explaining)
494 /* Corner case: linewrap with only "" wrapping to next line */ 510 /* Corner case: linewrap with only "" wrapping to next line */
495 /* Looks ugly on screen, so we do not store this empty line */ 511 /* Looks ugly on screen, so we do not store this empty line */
496 if (!last_terminated && !current_line[0]) { 512 if (!last_terminated && !current_line[0]) {
@@ -498,6 +514,7 @@ static void read_lines(void)
498 max_lineno++; 514 max_lineno++;
499 continue; 515 continue;
500 } 516 }
517#endif
501 reached_eof: 518 reached_eof:
502 last_terminated = terminated; 519 last_terminated = terminated;
503 flines = xrealloc_vector(flines, 8, max_fline); 520 flines = xrealloc_vector(flines, 8, max_fline);
@@ -528,24 +545,7 @@ static void read_lines(void)
528#endif 545#endif
529 } 546 }
530 if (eof_error <= 0) { 547 if (eof_error <= 0) {
531#if !ENABLE_FEATURE_LESS_REGEXP
532 break; 548 break;
533#else
534 if (wanted_match < num_matches) {
535 break;
536 } /* else: goto_match() called us */
537 if (errno == EAGAIN) {
538 time_t t = time(NULL);
539 if (t != last_time) {
540 last_time = t;
541 if (--had_progress < 0)
542 break;
543 }
544 sched_yield();
545 goto again0;
546 }
547 break;
548#endif
549 } 549 }
550 max_fline++; 550 max_fline++;
551 current_line = ((char*)xmalloc(w + 4)) + 4; 551 current_line = ((char*)xmalloc(w + 4)) + 4;
@@ -802,11 +802,18 @@ static void buffer_print(void)
802 unsigned i; 802 unsigned i;
803 803
804 move_cursor(0, 0); 804 move_cursor(0, 0);
805 for (i = 0; i <= max_displayed_line; i++) 805 for (i = 0; i <= max_displayed_line; i++) {
806 if (pattern_valid) 806 if (pattern_valid)
807 print_found(buffer[i]); 807 print_found(buffer[i]);
808 else 808 else
809 print_ascii(buffer[i]); 809 print_ascii(buffer[i]);
810 }
811 if ((option_mask32 & FLAG_E)
812 && eof_error <= 0
813 && (max_fline - cur_fline) <= max_displayed_line
814 ) {
815 less_exit(EXIT_SUCCESS);
816 }
810 status_print(); 817 status_print();
811} 818}
812 819