Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/miscutils/less.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/miscutils/less.c

    r3232 r3621  
    4848//config:   help
    4949//config:     The -M/-m flag enables a more sophisticated status line.
     50//config:
     51//config:config FEATURE_LESS_TRUNCATE
     52//config:   bool "Enable -S"
     53//config:   default y
     54//config:   depends on LESS
     55//config:   help
     56//config:     The -S flag causes long lines to be truncated rather than
     57//config:     wrapped.
    5058//config:
    5159//config:config FEATURE_LESS_MARKS
     
    99107
    100108//usage:#define less_trivial_usage
    101 //usage:       "[-E" IF_FEATURE_LESS_FLAGS("Mm") "Nh~I?] [FILE]..."
     109//usage:       "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm")
     110//usage:       "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..."
    102111//usage:#define less_full_usage "\n\n"
    103112//usage:       "View FILE (or stdin) one screenful at a time\n"
    104113//usage:     "\n    -E  Quit once the end of a file is reached"
     114//usage:    IF_FEATURE_LESS_REGEXP(
     115//usage:     "\n    -I  Ignore case in all searches"
     116//usage:    )
    105117//usage:    IF_FEATURE_LESS_FLAGS(
    106118//usage:     "\n    -M,-m   Display status line with line numbers"
     
    108120//usage:    )
    109121//usage:     "\n    -N  Prefix line number to each line"
    110 //usage:     "\n    -I  Ignore case in all searches"
     122//usage:    IF_FEATURE_LESS_TRUNCATE(
     123//usage:     "\n    -S  Truncate long lines"
     124//usage:    )
    111125//usage:     "\n    -~  Suppress ~s displayed past EOF"
    112126
     
    114128
    115129#include "libbb.h"
     130#include "common_bufsiz.h"
    116131#if ENABLE_FEATURE_LESS_REGEXP
    117132#include "xregex.h"
     
    143158    FLAG_TILDE = 1 << 4,
    144159    FLAG_I = 1 << 5,
    145     FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD,
     160    FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE,
    146161/* hijack command line options variable for internal state vars */
    147162    LESS_STATE_MATCH_BACKWARDS = 1 << 15,
     
    175190    char *filename;
    176191    char **files;
     192#if ENABLE_FEATURE_LESS_FLAGS
     193    int num_lines; /* a flag if < 0, line count if >= 0 */
     194# define REOPEN_AND_COUNT (-1)
     195# define REOPEN_STDIN     (-2)
     196# define NOT_REGULAR_FILE (-3)
     197#endif
    177198#if ENABLE_FEATURE_LESS_MARKS
    178199    unsigned num_marks;
     
    216237#define filename            (G.filename          )
    217238#define files               (G.files             )
     239#define num_lines           (G.num_lines         )
    218240#define num_marks           (G.num_marks         )
    219241#define mark_lines          (G.mark_lines        )
     
    318340        if (*d != '\0') {
    319341            new_line_pos++;
    320             if (*d == '\t') /* tab */
     342            if (*d == '\t') { /* tab */
    321343                new_line_pos += 7;
     344                new_line_pos &= (~7);
     345            }
    322346            s++;
    323347            d++;
     
    381405#endif
    382406
     407static int at_end(void)
     408{
     409    return (option_mask32 & FLAG_S)
     410        ? !(cur_fline <= max_fline &&
     411            max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
     412        : !(max_fline > cur_fline + max_displayed_line);
     413}
     414
    383415/* Devilishly complex routine.
    384416 *
     
    403435 *      (takes into account tabs and backspaces)
    404436 * eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
     437 *
     438 * "git log -p | less -m" on the kernel git tree is a good test for EAGAINs,
     439 * "/search on very long input" and "reaching max line count" corner cases.
    405440 */
    406441static void read_lines(void)
    407442{
    408 #define readbuf bb_common_bufsiz1
    409443    char *current_line, *p;
    410444    int w = width;
    411445    char last_terminated = terminated;
     446    time_t last_time = 0;
     447    int retry_EAGAIN = 2;
    412448#if ENABLE_FEATURE_LESS_REGEXP
    413449    unsigned old_max_fline = max_fline;
    414     time_t last_time = 0;
    415     unsigned seconds_p1 = 3; /* seconds_to_loop + 1 */
    416 #endif
     450#endif
     451
     452#define readbuf bb_common_bufsiz1
     453    setup_common_bufsiz();
     454
     455    /* (careful: max_fline can be -1) */
     456    if (max_fline + 1 > MAXLINES)
     457        return;
    417458
    418459    if (option_mask32 & FLAG_N)
    419460        w -= 8;
    420461
    421  IF_FEATURE_LESS_REGEXP(again0:)
    422 
    423     p = current_line = ((char*)xmalloc(w + 4)) + 4;
    424     max_fline += last_terminated;
     462    p = current_line = ((char*)xmalloc(w + 5)) + 4;
    425463    if (!last_terminated) {
    426464        const char *cp = flines[max_fline];
    427         strcpy(p, cp);
    428         p += strlen(current_line);
    429         free(MEMPTR(flines[max_fline]));
     465        p = stpcpy(p, cp);
     466        free(MEMPTR(cp));
    430467        /* last_line_pos is still valid from previous read_lines() */
    431468    } else {
     469        max_fline++;
    432470        last_line_pos = 0;
    433471    }
     
    440478            /* if no unprocessed chars left, eat more */
    441479            if (readpos >= readeof) {
    442                 ndelay_on(0);
    443                 eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf));
    444                 ndelay_off(0);
     480                int flags = ndelay_on(0);
     481
     482                while (1) {
     483                    time_t t;
     484
     485                    errno = 0;
     486                    eof_error = safe_read(STDIN_FILENO, readbuf, COMMON_BUFSIZE);
     487                    if (errno != EAGAIN)
     488                        break;
     489                    t = time(NULL);
     490                    if (t != last_time) {
     491                        last_time = t;
     492                        if (--retry_EAGAIN < 0)
     493                            break;
     494                    }
     495                    sched_yield();
     496                }
     497                fcntl(0, F_SETFL, flags); /* ndelay_off(0) */
    445498                readpos = 0;
    446499                readeof = eof_error;
    447500                if (eof_error <= 0)
    448501                    goto reached_eof;
     502                retry_EAGAIN = 1;
    449503            }
    450504            c = readbuf[readpos];
     
    465519                    new_last_line_pos &= (~7);
    466520                }
    467                 if ((int)new_last_line_pos >= w)
     521                if ((int)new_last_line_pos > w)
    468522                    break;
    469523                last_line_pos = new_last_line_pos;
     
    481535            *p = '\0';
    482536        } /* end of "read chars until we have a line" loop */
     537#if 0
     538//BUG: also triggers on this:
     539// { printf "\nfoo\n"; sleep 1; printf "\nbar\n"; } | less
     540// (resulting in lost empty line between "foo" and "bar" lines)
     541// the "terminated" logic needs fixing (or explaining)
    483542        /* Corner case: linewrap with only "" wrapping to next line */
    484543        /* Looks ugly on screen, so we do not store this empty line */
     
    488547            continue;
    489548        }
     549#endif
    490550 reached_eof:
    491551        last_terminated = terminated;
     
    501561            break;
    502562        }
    503         if (!(option_mask32 & FLAG_S)
    504           ? (max_fline > cur_fline + max_displayed_line)
    505           : (max_fline >= cur_fline
    506              && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
    507         ) {
     563        if (!at_end()) {
    508564#if !ENABLE_FEATURE_LESS_REGEXP
    509565            break;
     
    518574        }
    519575        if (eof_error <= 0) {
    520             if (eof_error < 0) {
    521                 if (errno == EAGAIN) {
    522                     /* not yet eof or error, reset flag (or else
    523                      * we will hog CPU - select() will return
    524                      * immediately */
    525                     eof_error = 1;
    526                 } else {
    527                     print_statusline(bb_msg_read_error);
    528                 }
    529             }
    530 #if !ENABLE_FEATURE_LESS_REGEXP
    531576            break;
    532 #else
    533             if (wanted_match < num_matches) {
    534                 break;
    535             } else { /* goto_match called us */
    536                 time_t t = time(NULL);
    537                 if (t != last_time) {
    538                     last_time = t;
    539                     if (--seconds_p1 == 0)
    540                         break;
    541                 }
    542                 sched_yield();
    543                 goto again0; /* go loop again (max 2 seconds) */
    544             }
    545 #endif
    546577        }
    547578        max_fline++;
    548         current_line = ((char*)xmalloc(w + 4)) + 4;
     579        current_line = ((char*)xmalloc(w + 5)) + 4;
    549580        p = current_line;
    550581        last_line_pos = 0;
    551582    } /* end of "read lines until we reach cur_fline" loop */
     583
     584    if (eof_error < 0) {
     585        if (errno == EAGAIN) {
     586            eof_error = 1;
     587        } else {
     588            print_statusline(bb_msg_read_error);
     589        }
     590    }
     591#if ENABLE_FEATURE_LESS_FLAGS
     592    else if (eof_error == 0)
     593        num_lines = max_lineno;
     594#endif
     595
    552596    fill_match_lines(old_max_fline);
    553597#if ENABLE_FEATURE_LESS_REGEXP
     
    559603
    560604#if ENABLE_FEATURE_LESS_FLAGS
    561 /* Interestingly, writing calc_percent as a function saves around 32 bytes
    562  * on my build. */
    563 static int calc_percent(void)
    564 {
    565     unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1);
    566     return p <= 100 ? p : 100;
     605static int safe_lineno(int fline)
     606{
     607    if (fline >= max_fline)
     608        fline = max_fline - 1;
     609
     610    /* also catches empty file (max_fline == 0) */
     611    if (fline < 0)
     612        return 0;
     613
     614    return LINENO(flines[fline]) + 1;
     615}
     616
     617/* count number of lines in file */
     618static void update_num_lines(void)
     619{
     620    int count, fd;
     621    struct stat stbuf;
     622    ssize_t len, i;
     623    char buf[4096];
     624
     625    /* only do this for regular files */
     626    if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) {
     627        count = 0;
     628        fd = open("/proc/self/fd/0", O_RDONLY);
     629        if (fd < 0 && num_lines == REOPEN_AND_COUNT) {
     630            /* "filename" is valid only if REOPEN_AND_COUNT */
     631            fd = open(filename, O_RDONLY);
     632        }
     633        if (fd < 0) {
     634            /* somebody stole my file! */
     635            num_lines = NOT_REGULAR_FILE;
     636            return;
     637        }
     638        if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) {
     639            num_lines = NOT_REGULAR_FILE;
     640            goto do_close;
     641        }
     642        while ((len = safe_read(fd, buf, sizeof(buf))) > 0) {
     643            for (i = 0; i < len; ++i) {
     644                if (buf[i] == '\n' && ++count == MAXLINES)
     645                    goto done;
     646            }
     647        }
     648 done:
     649        num_lines = count;
     650 do_close:
     651        close(fd);
     652    }
    567653}
    568654
     
    570656static void m_status_print(void)
    571657{
    572     int percentage;
     658    int first, last;
     659    unsigned percent;
    573660
    574661    if (less_gets_pos >= 0) /* don't touch statusline while input is done! */
     
    579666    if (num_files > 1)
    580667        printf(" (file %i of %i)", current_file, num_files);
    581     printf(" lines %i-%i/%i ",
    582             cur_fline + 1, cur_fline + max_displayed_line + 1,
    583             max_fline + 1);
    584     if (cur_fline >= (int)(max_fline - max_displayed_line)) {
    585         printf("(END)"NORMAL);
     668
     669    first = safe_lineno(cur_fline);
     670    last = (option_mask32 & FLAG_S)
     671            ? MIN(first + max_displayed_line, max_lineno)
     672            : safe_lineno(cur_fline + max_displayed_line);
     673    printf(" lines %i-%i", first, last);
     674
     675    update_num_lines();
     676    if (num_lines >= 0)
     677        printf("/%i", num_lines);
     678
     679    if (at_end()) {
     680        printf(" (END)");
    586681        if (num_files > 1 && current_file != num_files)
    587             printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]);
    588         return;
    589     }
    590     percentage = calc_percent();
    591     printf("%i%%"NORMAL, percentage);
     682            printf(" - next: %s", files[current_file]);
     683    } else if (num_lines > 0) {
     684        percent = (100 * last + num_lines/2) / num_lines;
     685        printf(" %i%%", percent <= 100 ? percent : 100);
     686    }
     687    printf(NORMAL);
    592688}
    593689#endif
     
    611707
    612708    clear_line();
    613     if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) {
     709    if (cur_fline && !at_end()) {
    614710        bb_putchar(':');
    615711        return;
     
    624720    }
    625721    print_hilite(p);
    626 }
    627 
    628 static void cap_cur_fline(int nlines)
    629 {
    630     int diff;
    631     if (cur_fline < 0)
    632         cur_fline = 0;
    633     if (cur_fline + max_displayed_line > max_fline + TILDES) {
    634         cur_fline -= nlines;
    635         if (cur_fline < 0)
    636             cur_fline = 0;
    637         diff = max_fline - (cur_fline + max_displayed_line) + TILDES;
    638         /* As the number of lines requested was too large, we just move
    639          * to the end of the file */
    640         if (diff > 0)
    641             cur_fline += diff;
    642     }
    643722}
    644723
     
    654733    "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
    655734
    656 static void lineno_str(char *nbuf9, const char *line)
    657 {
    658     nbuf9[0] = '\0';
    659     if (option_mask32 & FLAG_N) {
    660         const char *fmt;
    661         unsigned n;
    662 
    663         if (line == empty_line_marker) {
    664             memset(nbuf9, ' ', 8);
    665             nbuf9[8] = '\0';
    666             return;
    667         }
     735static void print_lineno(const char *line)
     736{
     737    const char *fmt = "        ";
     738    unsigned n = n; /* for compiler */
     739
     740    if (line != empty_line_marker) {
    668741        /* Width of 7 preserves tab spacing in the text */
    669742        fmt = "%7u ";
    670743        n = LINENO(line) + 1;
    671         if (n > 9999999) {
     744        if (n > 9999999 && MAXLINES > 9999999) {
    672745            n %= 10000000;
    673746            fmt = "%07u ";
    674747        }
    675         sprintf(nbuf9, fmt, n);
    676     }
     748    }
     749    printf(fmt, n);
    677750}
    678751
     
    686759    regmatch_t match_structs;
    687760
    688     char buf[width];
    689     char nbuf9[9];
     761    char buf[width+1];
    690762    const char *str = line;
    691763    char *p = buf;
     
    737809    }
    738810
    739     lineno_str(nbuf9, line);
    740     if (!growline) {
    741         printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
    742         return;
    743     }
    744     printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
     811    printf("%s%s\n", growline ? growline : "", str);
    745812    free(growline);
    746813}
     
    751818static void print_ascii(const char *str)
    752819{
    753     char buf[width];
    754     char nbuf9[9];
     820    char buf[width+1];
    755821    char *p;
    756822    size_t n;
    757 
    758     lineno_str(nbuf9, str);
    759     printf(CLEAR_2_EOL"%s", nbuf9);
    760823
    761824    while (*str) {
     
    791854
    792855    move_cursor(0, 0);
    793     for (i = 0; i <= max_displayed_line; i++)
     856    for (i = 0; i <= max_displayed_line; i++) {
     857        printf(CLEAR_2_EOL);
     858        if (option_mask32 & FLAG_N)
     859            print_lineno(buffer[i]);
    794860        if (pattern_valid)
    795861            print_found(buffer[i]);
    796862        else
    797863            print_ascii(buffer[i]);
     864    }
     865    if ((option_mask32 & FLAG_E)
     866     && eof_error <= 0
     867     && (max_fline - cur_fline) <= max_displayed_line
     868    ) {
     869        less_exit(EXIT_SUCCESS);
     870    }
    798871    status_print();
    799872}
     
    802875{
    803876    unsigned i;
    804 #if ENABLE_FEATURE_LESS_DASHCMD
     877#if ENABLE_FEATURE_LESS_TRUNCATE
    805878    int fpos = cur_fline;
    806879
     
    834907}
    835908
     909/* move cur_fline to a given line number, reading lines if necessary */
     910static void goto_lineno(int target)
     911{
     912    if (target <= 0 ) {
     913        cur_fline = 0;
     914    }
     915    else if (target > LINENO(flines[cur_fline])) {
     916 retry:
     917        while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline)
     918            ++cur_fline;
     919        /* target not reached but more input is available */
     920        if (LINENO(flines[cur_fline]) != target && eof_error > 0) {
     921            read_lines();
     922            goto retry;
     923        }
     924    }
     925    else {
     926        /* search backwards through already-read lines */
     927        while (LINENO(flines[cur_fline]) != target && cur_fline > 0)
     928            --cur_fline;
     929    }
     930}
     931
     932static void cap_cur_fline(void)
     933{
     934    if ((option_mask32 & FLAG_S)) {
     935        if (cur_fline > max_fline)
     936            cur_fline = max_fline;
     937        if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) {
     938            goto_lineno(max_lineno - max_displayed_line + TILDES);
     939            read_lines();
     940        }
     941    }
     942    else {
     943        if (cur_fline + max_displayed_line > max_fline + TILDES)
     944            cur_fline = max_fline - max_displayed_line + TILDES;
     945        if (cur_fline < 0)
     946            cur_fline = 0;
     947    }
     948}
     949
    836950/* Move the buffer up and down in the file in order to scroll */
    837951static void buffer_down(int nlines)
    838952{
    839     cur_fline += nlines;
     953    if ((option_mask32 & FLAG_S))
     954        goto_lineno(LINENO(flines[cur_fline]) + nlines);
     955    else
     956        cur_fline += nlines;
    840957    read_lines();
    841     cap_cur_fline(nlines);
     958    cap_cur_fline();
    842959    buffer_fill_and_print();
    843960}
     
    845962static void buffer_up(int nlines)
    846963{
    847     cur_fline -= nlines;
    848     if (cur_fline < 0) cur_fline = 0;
     964    if ((option_mask32 & FLAG_S)) {
     965        goto_lineno(LINENO(flines[cur_fline]) - nlines);
     966    }
     967    else {
     968        cur_fline -= nlines;
     969        if (cur_fline < 0)
     970            cur_fline = 0;
     971    }
    849972    read_lines();
    850973    buffer_fill_and_print();
    851974}
    852975
     976/* display a given line where the argument can be either an index into
     977 * the flines array or a line number */
     978static void buffer_to_line(int linenum, int is_lineno)
     979{
     980    if (linenum <= 0)
     981        cur_fline = 0;
     982    else if (is_lineno)
     983        goto_lineno(linenum);
     984    else
     985        cur_fline = linenum;
     986    read_lines();
     987    cap_cur_fline();
     988    buffer_fill_and_print();
     989}
     990
    853991static void buffer_line(int linenum)
    854992{
    855     if (linenum < 0)
    856         linenum = 0;
    857     cur_fline = linenum;
    858     read_lines();
    859     if (linenum + max_displayed_line > max_fline)
    860         linenum = max_fline - max_displayed_line + TILDES;
    861     if (linenum < 0)
    862         linenum = 0;
    863     cur_fline = linenum;
    864     buffer_fill_and_print();
     993    buffer_to_line(linenum, FALSE);
     994}
     995
     996static void buffer_lineno(int lineno)
     997{
     998    buffer_to_line(lineno, TRUE);
    865999}
    8661000
     
    8691003    if (filename) {
    8701004        xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
     1005#if ENABLE_FEATURE_LESS_FLAGS
     1006        num_lines = REOPEN_AND_COUNT;
     1007#endif
    8711008    } else {
    8721009        /* "less" with no arguments in argv[] */
    8731010        /* For status line only */
    8741011        filename = xstrdup(bb_msg_standard_input);
     1012#if ENABLE_FEATURE_LESS_FLAGS
     1013        num_lines = REOPEN_STDIN;
     1014#endif
    8751015    }
    8761016    readpos = 0;
     
    9241064    rd = 1;
    9251065    /* Are we interested in stdin? */
    926 //TODO: reuse code for determining this
    927     if (!(option_mask32 & FLAG_S)
    928        ? !(max_fline > cur_fline + max_displayed_line)
    929        : !(max_fline >= cur_fline
    930            && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
    931     ) {
     1066    if (at_end()) {
    9321067        if (eof_error > 0) /* did NOT reach eof yet */
    9331068            rd = 0; /* yes, we are interested in stdin */
     
    12401375    while (i < sizeof(num_input)-1) {
    12411376        keypress = less_getch(i + 1);
    1242         if ((unsigned)keypress > 255 || !isdigit(num_input[i]))
     1377        if ((unsigned)keypress > 255 || !isdigit(keypress))
    12431378            break;
    12441379        num_input[i] = keypress;
     
    12641399        break;
    12651400    case 'g': case '<': case 'G': case '>':
    1266         cur_fline = num + max_displayed_line;
    1267         read_lines();
    1268         buffer_line(num - 1);
     1401        buffer_lineno(num - 1);
    12691402        break;
    12701403    case 'p': case '%':
    1271         num = num * (max_fline / 100); /* + max_fline / 2; */
    1272         cur_fline = num + max_displayed_line;
    1273         read_lines();
    1274         buffer_line(num);
     1404#if ENABLE_FEATURE_LESS_FLAGS
     1405        update_num_lines();
     1406        num = num * (num_lines > 0 ? num_lines : max_lineno) / 100;
     1407#else
     1408        num = num * max_lineno / 100;
     1409#endif
     1410        buffer_lineno(num);
    12751411        break;
    12761412#if ENABLE_FEATURE_LESS_REGEXP
     
    13121448        option_mask32 ^= FLAG_TILDE;
    13131449        break;
     1450#if ENABLE_FEATURE_LESS_TRUNCATE
    13141451    case 'S':
    13151452        option_mask32 ^= FLAG_S;
    13161453        buffer_fill_and_print();
    13171454        break;
     1455#endif
    13181456#if ENABLE_FEATURE_LESS_LINENUMS
    13191457    case 'N':
     
    16091747int less_main(int argc, char **argv)
    16101748{
     1749    char *tty_name;
     1750    int tty_fd;
     1751
    16111752    INIT_G();
    16121753
    1613     /* TODO: -x: do not interpret backspace, -xx: tab also */
    1614     /* -xxx: newline also */
    1615     /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
    1616     getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S"));
     1754    /* TODO: -x: do not interpret backspace, -xx: tab also
     1755     * -xxx: newline also
     1756     * -w N: assume width N (-xxx -w 32: hex viewer of sorts)
     1757     * -s: condense many empty lines to one
     1758     *     (used by some setups for manpage display)
     1759     */
     1760    getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s");
    16171761    argc -= optind;
    16181762    argv += optind;
     
    16381782        empty_line_marker = "";
    16391783
    1640     kbd_fd = open(CURRENT_TTY, O_RDONLY);
    1641     if (kbd_fd < 0)
    1642         return bb_cat(argv);
    1643     ndelay_on(kbd_fd);
     1784    /* Some versions of less can survive w/o controlling tty,
     1785     * try to do the same. This also allows to specify an alternative
     1786     * tty via "less 1<>TTY".
     1787     * We don't try to use STDOUT_FILENO directly,
     1788     * since we want to set this fd to non-blocking mode,
     1789     * and not bother with restoring it on exit.
     1790     */
     1791    tty_name = xmalloc_ttyname(STDOUT_FILENO);
     1792    if (tty_name) {
     1793        tty_fd = open(tty_name, O_RDONLY);
     1794        free(tty_name);
     1795        if (tty_fd < 0)
     1796            goto try_ctty;
     1797    } else {
     1798        /* Try controlling tty */
     1799 try_ctty:
     1800        tty_fd = open(CURRENT_TTY, O_RDONLY);
     1801        if (tty_fd < 0)
     1802            return bb_cat(argv);
     1803    }
     1804    ndelay_on(tty_fd);
     1805    kbd_fd = tty_fd; /* save in a global */
    16441806
    16451807    tcgetattr(kbd_fd, &term_orig);
     
    18061968        or from within less by using the - or -- command.
    18071969        Options may be given in one of two forms: either a single
    1808         character preceded by a -, or a name preceeded by --.
     1970        character preceded by a -, or a name preceded by --.
    18091971  -?  ........  --help
    18101972                  Display help (from command line).
Note: See TracChangeset for help on using the changeset viewer.