Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/util-linux/more.c

    r821 r1765  
    1212 * Termios corrects by Vladimir Oleynik <dzo@simtreas.ru>
    1313 *
    14  * This program is free software; you can redistribute it and/or modify
    15  * it under the terms of the GNU General Public License as published by
    16  * the Free Software Foundation; either version 2 of the License, or
    17  * (at your option) any later version.
    18  *
    19  * This program is distributed in the hope that it will be useful,
    20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    22  * General Public License for more details.
    23  *
    24  * You should have received a copy of the GNU General Public License
    25  * along with this program; if not, write to the Free Software
    26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    27  *
     14 * Licensed under GPLv2 or later, see file License in this tarball for details.
    2815 */
    2916
    30 #include <stdio.h>
    31 #include <fcntl.h>
    32 #include <signal.h>
    33 #include <stdlib.h>
    34 #include <unistd.h>
    35 #include <sys/ioctl.h>
    36 #include "busybox.h"
    37 
    38 
    39 #ifdef CONFIG_FEATURE_USE_TERMIOS
    40 static int cin_fileno;
     17#include "libbb.h"
     18#if ENABLE_FEATURE_USE_TERMIOS
    4119#include <termios.h>
    42 #define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
    43 #define getTermSettings(fd,argp) tcgetattr(fd, argp);
    44 
    45 static struct termios initial_settings, new_settings;
    46 
    47 static void set_tty_to_initial_mode(void)
    48 {
    49     setTermSettings(cin_fileno, &initial_settings);
    50 }
     20#endif /* FEATURE_USE_TERMIOS */
     21
     22
     23#if ENABLE_FEATURE_USE_TERMIOS
     24
     25struct globals {
     26    int cin_fileno;
     27    struct termios initial_settings;
     28    struct termios new_settings;
     29};
     30#define G (*(struct globals*)bb_common_bufsiz1)
     31//#define G (*ptr_to_globals)
     32#define INIT_G() ((void)0)
     33//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
     34#define initial_settings (G.initial_settings)
     35#define new_settings     (G.new_settings    )
     36#define cin_fileno       (G.cin_fileno      )
     37
     38#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
     39#define getTermSettings(fd, argp) tcgetattr(fd, argp)
    5140
    5241static void gotsig(int sig)
    5342{
    5443    putchar('\n');
     44    setTermSettings(cin_fileno, &initial_settings);
    5545    exit(EXIT_FAILURE);
    5646}
    57 #endif /* CONFIG_FEATURE_USE_TERMIOS */
    58 
    59 
     47
     48#else /* !FEATURE_USE_TERMIOS */
     49#define INIT_G() ((void)0)
     50#define setTermSettings(fd, argp) ((void)0)
     51#endif /* FEATURE_USE_TERMIOS */
     52
     53#define CONVERTED_TAB_SIZE 8
     54
     55int more_main(int argc, char **argv);
    6056int more_main(int argc, char **argv)
    6157{
    62     int c, lines, input = 0;
    63     int please_display_more_prompt = 0;
     58    int c = c; /* for gcc */
     59    int lines;
     60    int input = 0;
     61    int spaces = 0;
     62    int please_display_more_prompt;
    6463    struct stat st;
    6564    FILE *file;
    6665    FILE *cin;
    67     int len, page_height;
     66    int len;
    6867    int terminal_width;
    6968    int terminal_height;
    7069
    71     argc--;
     70    INIT_G();
     71
    7272    argv++;
    73 
    74 
    75     /* not use inputing from terminal if usage: more > outfile */
    76     if(isatty(STDOUT_FILENO)) {
    77         cin = fopen(CURRENT_TTY, "r");
    78         if (!cin)
    79             cin = bb_xfopen(CONSOLE_DEV, "r");
    80         please_display_more_prompt = 2;
    81 #ifdef CONFIG_FEATURE_USE_TERMIOS
    82         cin_fileno = fileno(cin);
    83         getTermSettings(cin_fileno, &initial_settings);
    84         new_settings = initial_settings;
    85         new_settings.c_lflag &= ~ICANON;
    86         new_settings.c_lflag &= ~ECHO;
    87         new_settings.c_cc[VMIN] = 1;
    88         new_settings.c_cc[VTIME] = 0;
    89         setTermSettings(cin_fileno, &new_settings);
    90         atexit(set_tty_to_initial_mode);
    91         (void) signal(SIGINT, gotsig);
    92         (void) signal(SIGQUIT, gotsig);
    93         (void) signal(SIGTERM, gotsig);
     73    /* Another popular pager, most, detects when stdout
     74     * is not a tty and turns into cat. This makes sense. */
     75    if (!isatty(STDOUT_FILENO))
     76        return bb_cat(argv);
     77    cin = fopen(CURRENT_TTY, "r");
     78    if (!cin)
     79        return bb_cat(argv);
     80
     81#if ENABLE_FEATURE_USE_TERMIOS
     82    cin_fileno = fileno(cin);
     83    getTermSettings(cin_fileno, &initial_settings);
     84    new_settings = initial_settings;
     85    new_settings.c_lflag &= ~ICANON;
     86    new_settings.c_lflag &= ~ECHO;
     87    new_settings.c_cc[VMIN] = 1;
     88    new_settings.c_cc[VTIME] = 0;
     89    setTermSettings(cin_fileno, &new_settings);
     90    signal(SIGINT, gotsig);
     91    signal(SIGQUIT, gotsig);
     92    signal(SIGTERM, gotsig);
    9493#endif
    95     } else {
    96         cin = stdin;
    97     }
    9894
    9995    do {
    100         if (argc == 0) {
    101             file = stdin;
    102         } else
    103             file = bb_wfopen(*argv, "r");
    104         if(file==0)
    105             goto loop;
    106 
     96        file = stdin;
     97        if (*argv) {
     98            file = fopen_or_warn(*argv, "r");
     99            if (!file)
     100                continue;
     101        }
    107102        st.st_size = 0;
    108103        fstat(fileno(file), &st);
    109104
    110         please_display_more_prompt &= ~1;
    111 
     105        please_display_more_prompt = 0;
     106        /* never returns w, h <= 1 */
    112107        get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
    113         if (terminal_height > 4)
    114             terminal_height -= 2;
    115         if (terminal_width > 0)
    116             terminal_width -= 1;
    117 
    118         len=0;
     108        terminal_height -= 1;
     109
     110        len = 0;
    119111        lines = 0;
    120         page_height = terminal_height;
    121         while ((c = getc(file)) != EOF) {
    122 
    123             if ((please_display_more_prompt & 3) == 3) {
     112        while (spaces || (c = getc(file)) != EOF) {
     113            int wrap;
     114            if (spaces)
     115                spaces--;
     116 loop_top:
     117            if (input != 'r' && please_display_more_prompt) {
    124118                len = printf("--More-- ");
    125                 if (file != stdin && st.st_size > 0) {
    126 #if _FILE_OFFSET_BITS == 64
    127                     len += printf("(%d%% of %lld bytes)",
    128                            (int) (100 * ((double) ftell(file) /
    129                            (double) st.st_size)), (long long)st.st_size);
    130 #else
    131                     len += printf("(%d%% of %ld bytes)",
    132                            (int) (100 * ((double) ftell(file) /
    133                            (double) st.st_size)), (long)st.st_size);
    134 #endif
     119                if (st.st_size > 0) {
     120                    len += printf("(%d%% of %"OFF_FMT"d bytes)",
     121                        (int) (ftello(file)*100 / st.st_size),
     122                        st.st_size);
    135123                }
    136 
    137124                fflush(stdout);
    138125
     
    141128                 * to get input from the user.
    142129                 */
    143                 input = getc(cin);
    144 #ifndef CONFIG_FEATURE_USE_TERMIOS
    145                 printf("\033[A"); /* up cursor */
     130                for (;;) {
     131                    input = getc(cin);
     132                    input = tolower(input);
     133#if !ENABLE_FEATURE_USE_TERMIOS
     134                    printf("\033[A"); /* up cursor */
    146135#endif
    147                 /* Erase the "More" message */
    148                 putc('\r', stdout);
    149                 while (--len >= 0)
    150                     putc(' ', stdout);
    151                 putc('\r', stdout);
    152                 len=0;
     136                    /* Erase the last message */
     137                    printf("\r%*s\r", len, "");
     138
     139                    /* Due to various multibyte escape
     140                     * sequences, it's not ok to accept
     141                     * any input as a command to scroll
     142                     * the screen. We only allow known
     143                     * commands, else we show help msg. */
     144                    if (input == ' ' || input == '\n' || input == 'q' || input == 'r')
     145                        break;
     146                    len = printf("(Enter:next line Space:next page Q:quit R:show the rest)");
     147                }
     148                len = 0;
    153149                lines = 0;
    154                 page_height = terminal_height;
    155                 please_display_more_prompt &= ~1;
     150                please_display_more_prompt = 0;
    156151
    157152                if (input == 'q')
    158153                    goto end;
     154
     155                /* The user may have resized the terminal.
     156                 * Re-read the dimensions. */
     157#if ENABLE_FEATURE_USE_TERMIOS
     158                get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
     159                terminal_height -= 1;
     160#endif
    159161            }
     162
     163            /* Crudely convert tabs into spaces, which are
     164             * a bajillion times easier to deal with. */
     165            if (c == '\t') {
     166                spaces = CONVERTED_TAB_SIZE - 1;
     167                c = ' ';
     168            }
    160169
    161170            /*
    162171             * There are two input streams to worry about here:
    163172             *
    164              * c     : the character we are reading from the file being "mored"
    165              * input : a character received from the keyboard
     173             * c    : the character we are reading from the file being "mored"
     174             * input: a character received from the keyboard
    166175             *
    167176             * If we hit a newline in the _file_ stream, we want to test and
     
    169178             * allows the user to quit while in the middle of a file.
    170179             */
    171             if (c == '\n') {
    172                 /* increment by just one line if we are at
    173                  * the end of this line */
    174                 if (input == '\n')
    175                     please_display_more_prompt |= 1;
    176                 /* Adjust the terminal height for any overlap, so that
    177                  * no lines get lost off the top. */
    178                 if (len >= terminal_width) {
    179                     int quot, rem;
    180                     quot = len / terminal_width;
    181                     rem  = len - (quot * terminal_width);
    182                     if (quot) {
    183                         if (rem)
    184                             page_height-=quot;
    185                         else
    186                             page_height-=(quot-1);
    187                     }
    188                 }
    189                 if (++lines >= page_height) {
    190                     please_display_more_prompt |= 1;
    191                 }
    192                 len=0;
     180            wrap = (++len > terminal_width);
     181            if (c == '\n' || wrap) {
     182                /* Then outputting this character
     183                 * will move us to a new line. */
     184                if (++lines >= terminal_height || input == '\n')
     185                    please_display_more_prompt = 1;
     186                len = 0;
    193187            }
    194             /*
    195              * If we just read a newline from the file being 'mored' and any
    196              * key other than a return is hit, scroll by one page
    197              */
    198             putc(c, stdout);
    199             len++;
     188            if (c != '\n' && wrap) {
     189                /* Then outputting this will also put a character on
     190                 * the beginning of that new line. Thus we first want to
     191                 * display the prompt (if any), so we skip the putchar()
     192                 * and go back to the top of the loop, without reading
     193                 * a new character. */
     194                goto loop_top;
     195            }
     196            /* My small mind cannot fathom backspaces and UTF-8 */
     197            putchar(c);
    200198        }
    201199        fclose(file);
    202200        fflush(stdout);
    203 loop:
    204         argv++;
    205     } while (--argc > 0);
    206   end:
     201    } while (*argv && *++argv);
     202 end:
     203    setTermSettings(cin_fileno, &initial_settings);
    207204    return 0;
    208205}
Note: See TracChangeset for help on using the changeset viewer.