diff options
author | Ron Yorston <rmy@pobox.com> | 2017-02-08 20:09:29 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2017-02-08 20:09:29 +0000 |
commit | 373275a708bafb88fa4f0519de2166154f44fed9 (patch) | |
tree | 4587b4fd3f695e0f3705b2a217e199f3144df931 /util-linux/more.c | |
parent | b74b2619779b1deb903b7766261807df1e9b1f7f (diff) | |
parent | c2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff) | |
download | busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2 busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'util-linux/more.c')
-rw-r--r-- | util-linux/more.c | 106 |
1 files changed, 47 insertions, 59 deletions
diff --git a/util-linux/more.c b/util-linux/more.c index d04c17f90..a032a1e7f 100644 --- a/util-linux/more.c +++ b/util-linux/more.c | |||
@@ -41,32 +41,33 @@ | |||
41 | #include "libbb.h" | 41 | #include "libbb.h" |
42 | #include "common_bufsiz.h" | 42 | #include "common_bufsiz.h" |
43 | 43 | ||
44 | /* Support for FEATURE_USE_TERMIOS */ | ||
45 | |||
46 | struct globals { | 44 | struct globals { |
47 | int cin_fileno; | 45 | int tty_fileno; |
46 | unsigned terminal_width; | ||
47 | unsigned terminal_height; | ||
48 | struct termios initial_settings; | 48 | struct termios initial_settings; |
49 | struct termios new_settings; | ||
50 | } FIX_ALIASING; | 49 | } FIX_ALIASING; |
51 | #define G (*(struct globals*)bb_common_bufsiz1) | 50 | #define G (*(struct globals*)bb_common_bufsiz1) |
52 | #define initial_settings (G.initial_settings) | ||
53 | #define new_settings (G.new_settings ) | ||
54 | #define cin_fileno (G.cin_fileno ) | ||
55 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 51 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
56 | 52 | ||
57 | #define setTermSettings(fd, argp) \ | 53 | static void get_wh(void) |
58 | do { \ | 54 | { |
59 | if (ENABLE_FEATURE_USE_TERMIOS) \ | 55 | /* never returns w, h <= 1 */ |
60 | tcsetattr(fd, TCSANOW, argp); \ | 56 | get_terminal_width_height(G.tty_fileno, &G.terminal_width, &G.terminal_height); |
61 | } while (0) | 57 | G.terminal_height -= 1; |
62 | #define getTermSettings(fd, argp) tcgetattr(fd, argp) | 58 | } |
59 | |||
60 | static void tcsetattr_tty_TCSANOW(struct termios *settings) | ||
61 | { | ||
62 | tcsetattr(G.tty_fileno, TCSANOW, settings); | ||
63 | } | ||
63 | 64 | ||
64 | static void gotsig(int sig UNUSED_PARAM) | 65 | static void gotsig(int sig UNUSED_PARAM) |
65 | { | 66 | { |
66 | /* bb_putchar_stderr doesn't use stdio buffering, | 67 | /* bb_putchar_stderr doesn't use stdio buffering, |
67 | * therefore it is safe in signal handler */ | 68 | * therefore it is safe in signal handler */ |
68 | bb_putchar_stderr('\n'); | 69 | bb_putchar_stderr('\n'); |
69 | setTermSettings(cin_fileno, &initial_settings); | 70 | tcsetattr_tty_TCSANOW(&G.initial_settings); |
70 | _exit(EXIT_FAILURE); | 71 | _exit(EXIT_FAILURE); |
71 | } | 72 | } |
72 | 73 | ||
@@ -76,22 +77,16 @@ int more_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
76 | int more_main(int argc UNUSED_PARAM, char **argv) | 77 | int more_main(int argc UNUSED_PARAM, char **argv) |
77 | { | 78 | { |
78 | int c = c; /* for compiler */ | 79 | int c = c; /* for compiler */ |
79 | int lines; | ||
80 | int input = 0; | 80 | int input = 0; |
81 | int spaces = 0; | 81 | int spaces = 0; |
82 | int please_display_more_prompt; | 82 | int please_display_more_prompt; |
83 | struct stat st; | 83 | FILE *tty; |
84 | FILE *file; | ||
85 | FILE *cin; | ||
86 | int len; | ||
87 | unsigned terminal_width; | ||
88 | unsigned terminal_height; | ||
89 | 84 | ||
90 | INIT_G(); | 85 | INIT_G(); |
91 | 86 | ||
92 | /* Parse options */ | 87 | /* Parse options */ |
93 | /* Accepted but ignored: */ | 88 | /* Accepted but ignored: */ |
94 | /* -d Display help instead of ringing bell is pressed */ | 89 | /* -d Display help instead of ringing bell */ |
95 | /* -f Count logical lines (IOW: long lines are not folded) */ | 90 | /* -f Count logical lines (IOW: long lines are not folded) */ |
96 | /* -l Do not pause after any line containing a ^L (form feed) */ | 91 | /* -l Do not pause after any line containing a ^L (form feed) */ |
97 | /* -s Squeeze blank lines into one */ | 92 | /* -s Squeeze blank lines into one */ |
@@ -104,29 +99,25 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
104 | if (!isatty(STDOUT_FILENO)) | 99 | if (!isatty(STDOUT_FILENO)) |
105 | return bb_cat(argv); | 100 | return bb_cat(argv); |
106 | #if !ENABLE_PLATFORM_MINGW32 | 101 | #if !ENABLE_PLATFORM_MINGW32 |
107 | cin = fopen_for_read(CURRENT_TTY); | 102 | tty = fopen_for_read(CURRENT_TTY); |
108 | if (!cin) | 103 | if (!tty) |
109 | return bb_cat(argv); | 104 | return bb_cat(argv); |
110 | #else | 105 | #else |
111 | cin = stdin; | 106 | tty = stdin; |
112 | #endif | 107 | #endif |
113 | 108 | ||
114 | if (ENABLE_FEATURE_USE_TERMIOS) { | 109 | G.tty_fileno = fileno(tty); |
115 | cin_fileno = fileno(cin); | 110 | |
116 | getTermSettings(cin_fileno, &initial_settings); | 111 | /* Turn on unbuffered input; turn off echoing */ |
117 | new_settings = initial_settings; | 112 | set_termios_to_raw(G.tty_fileno, &G.initial_settings, 0); |
118 | new_settings.c_lflag &= ~(ICANON | ECHO); | 113 | bb_signals(BB_FATAL_SIGS, gotsig); |
119 | new_settings.c_cc[VMIN] = 1; | ||
120 | new_settings.c_cc[VTIME] = 0; | ||
121 | setTermSettings(cin_fileno, &new_settings); | ||
122 | bb_signals(0 | ||
123 | + (1 << SIGINT) | ||
124 | + (1 << SIGQUIT) | ||
125 | + (1 << SIGTERM) | ||
126 | , gotsig); | ||
127 | } | ||
128 | 114 | ||
129 | do { | 115 | do { |
116 | struct stat st; | ||
117 | FILE *file; | ||
118 | int len; | ||
119 | int lines; | ||
120 | |||
130 | file = stdin; | 121 | file = stdin; |
131 | if (*argv) { | 122 | if (*argv) { |
132 | file = fopen_or_warn(*argv, "r"); | 123 | file = fopen_or_warn(*argv, "r"); |
@@ -136,17 +127,20 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
136 | st.st_size = 0; | 127 | st.st_size = 0; |
137 | fstat(fileno(file), &st); | 128 | fstat(fileno(file), &st); |
138 | 129 | ||
139 | please_display_more_prompt = 0; | 130 | get_wh(); |
140 | /* never returns w, h <= 1 */ | ||
141 | get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height); | ||
142 | terminal_height -= 1; | ||
143 | 131 | ||
132 | please_display_more_prompt = 0; | ||
144 | len = 0; | 133 | len = 0; |
145 | lines = 0; | 134 | lines = 0; |
146 | while (spaces || (c = getc(file)) != EOF) { | 135 | for (;;) { |
147 | int wrap; | 136 | int wrap; |
137 | |||
148 | if (spaces) | 138 | if (spaces) |
149 | spaces--; | 139 | spaces--; |
140 | else { | ||
141 | c = getc(file); | ||
142 | if (c == EOF) break; | ||
143 | } | ||
150 | loop_top: | 144 | loop_top: |
151 | if (input != 'r' && please_display_more_prompt) { | 145 | if (input != 'r' && please_display_more_prompt) { |
152 | len = printf("--More-- "); | 146 | len = printf("--More-- "); |
@@ -158,7 +152,6 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
158 | (int) ((uoff_t)ftello(file) / d), | 152 | (int) ((uoff_t)ftello(file) / d), |
159 | st.st_size); | 153 | st.st_size); |
160 | } | 154 | } |
161 | fflush_all(); | ||
162 | 155 | ||
163 | /* | 156 | /* |
164 | * We've just displayed the "--More--" prompt, so now we need | 157 | * We've just displayed the "--More--" prompt, so now we need |
@@ -166,22 +159,23 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
166 | */ | 159 | */ |
167 | for (;;) { | 160 | for (;;) { |
168 | #if !ENABLE_PLATFORM_MINGW32 | 161 | #if !ENABLE_PLATFORM_MINGW32 |
169 | input = getc(cin); | 162 | fflush_all(); |
163 | input = getc(tty); | ||
170 | #else | 164 | #else |
171 | input = _getch(); | 165 | input = _getch(); |
172 | #endif | 166 | #endif |
173 | input = tolower(input); | 167 | input = tolower(input); |
174 | if (!ENABLE_FEATURE_USE_TERMIOS) | ||
175 | printf("\033[A"); /* cursor up */ | ||
176 | /* Erase the last message */ | 168 | /* Erase the last message */ |
177 | printf("\r%*s\r", len, ""); | 169 | printf("\r%*s\r", len, ""); |
178 | 170 | ||
171 | if (input == 'q') | ||
172 | goto end; | ||
179 | /* Due to various multibyte escape | 173 | /* Due to various multibyte escape |
180 | * sequences, it's not ok to accept | 174 | * sequences, it's not ok to accept |
181 | * any input as a command to scroll | 175 | * any input as a command to scroll |
182 | * the screen. We only allow known | 176 | * the screen. We only allow known |
183 | * commands, else we show help msg. */ | 177 | * commands, else we show help msg. */ |
184 | if (input == ' ' || input == '\n' || input == 'q' || input == 'r') | 178 | if (input == ' ' || input == '\n' || input == 'r') |
185 | break; | 179 | break; |
186 | #if ENABLE_PLATFORM_MINGW32 | 180 | #if ENABLE_PLATFORM_MINGW32 |
187 | if (input == '\r') | 181 | if (input == '\r') |
@@ -193,15 +187,9 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
193 | lines = 0; | 187 | lines = 0; |
194 | please_display_more_prompt = 0; | 188 | please_display_more_prompt = 0; |
195 | 189 | ||
196 | if (input == 'q') | ||
197 | goto end; | ||
198 | |||
199 | /* The user may have resized the terminal. | 190 | /* The user may have resized the terminal. |
200 | * Re-read the dimensions. */ | 191 | * Re-read the dimensions. */ |
201 | if (ENABLE_FEATURE_USE_TERMIOS) { | 192 | get_wh(); |
202 | get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height); | ||
203 | terminal_height -= 1; | ||
204 | } | ||
205 | } | 193 | } |
206 | 194 | ||
207 | /* Crudely convert tabs into spaces, which are | 195 | /* Crudely convert tabs into spaces, which are |
@@ -221,11 +209,11 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
221 | * see if any characters have been hit in the _input_ stream. This | 209 | * see if any characters have been hit in the _input_ stream. This |
222 | * allows the user to quit while in the middle of a file. | 210 | * allows the user to quit while in the middle of a file. |
223 | */ | 211 | */ |
224 | wrap = (++len > terminal_width); | 212 | wrap = (++len > G.terminal_width); |
225 | if (c == '\n' || wrap) { | 213 | if (c == '\n' || wrap) { |
226 | /* Then outputting this character | 214 | /* Then outputting this character |
227 | * will move us to a new line. */ | 215 | * will move us to a new line. */ |
228 | if (++lines >= terminal_height || input == '\n') | 216 | if (++lines >= G.terminal_height || input == '\n') |
229 | please_display_more_prompt = 1; | 217 | please_display_more_prompt = 1; |
230 | #if ENABLE_PLATFORM_MINGW32 | 218 | #if ENABLE_PLATFORM_MINGW32 |
231 | if (input == '\r') | 219 | if (input == '\r') |
@@ -249,6 +237,6 @@ int more_main(int argc UNUSED_PARAM, char **argv) | |||
249 | fflush_all(); | 237 | fflush_all(); |
250 | } while (*argv && *++argv); | 238 | } while (*argv && *++argv); |
251 | end: | 239 | end: |
252 | setTermSettings(cin_fileno, &initial_settings); | 240 | tcsetattr_tty_TCSANOW(&G.initial_settings); |
253 | return 0; | 241 | return 0; |
254 | } | 242 | } |