Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/util-linux/more.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/util-linux/more.c
r821 r1765 12 12 * Termios corrects by Vladimir Oleynik <dzo@simtreas.ru> 13 13 * 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. 28 15 */ 29 16 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 41 19 #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 25 struct 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) 51 40 52 41 static void gotsig(int sig) 53 42 { 54 43 putchar('\n'); 44 setTermSettings(cin_fileno, &initial_settings); 55 45 exit(EXIT_FAILURE); 56 46 } 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 55 int more_main(int argc, char **argv); 60 56 int more_main(int argc, char **argv) 61 57 { 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; 64 63 struct stat st; 65 64 FILE *file; 66 65 FILE *cin; 67 int len , page_height;66 int len; 68 67 int terminal_width; 69 68 int terminal_height; 70 69 71 argc--; 70 INIT_G(); 71 72 72 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); 94 93 #endif 95 } else {96 cin = stdin;97 }98 94 99 95 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 } 107 102 st.st_size = 0; 108 103 fstat(fileno(file), &st); 109 104 110 please_display_more_prompt &= ~1;111 105 please_display_more_prompt = 0; 106 /* never returns w, h <= 1 */ 112 107 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; 119 111 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) { 124 118 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); 135 123 } 136 137 124 fflush(stdout); 138 125 … … 141 128 * to get input from the user. 142 129 */ 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 */ 146 135 #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; 153 149 lines = 0; 154 page_height = terminal_height; 155 please_display_more_prompt &= ~1; 150 please_display_more_prompt = 0; 156 151 157 152 if (input == 'q') 158 153 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 159 161 } 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 } 160 169 161 170 /* 162 171 * There are two input streams to worry about here: 163 172 * 164 * c 165 * input 173 * c : the character we are reading from the file being "mored" 174 * input: a character received from the keyboard 166 175 * 167 176 * If we hit a newline in the _file_ stream, we want to test and … … 169 178 * allows the user to quit while in the middle of a file. 170 179 */ 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; 193 187 } 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); 200 198 } 201 199 fclose(file); 202 200 fflush(stdout); 203 loop: 204 argv++; 205 } while (--argc > 0); 206 end: 201 } while (*argv && *++argv); 202 end: 203 setTermSettings(cin_fileno, &initial_settings); 207 204 return 0; 208 205 }
Note:
See TracChangeset
for help on using the changeset viewer.