summaryrefslogtreecommitdiff
path: root/util-linux/more.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
committerRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
commit373275a708bafb88fa4f0519de2166154f44fed9 (patch)
tree4587b4fd3f695e0f3705b2a217e199f3144df931 /util-linux/more.c
parentb74b2619779b1deb903b7766261807df1e9b1f7f (diff)
parentc2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff)
downloadbusybox-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.c106
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
46struct globals { 44struct 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) \ 53static void get_wh(void)
58do { \ 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
60static void tcsetattr_tty_TCSANOW(struct termios *settings)
61{
62 tcsetattr(G.tty_fileno, TCSANOW, settings);
63}
63 64
64static void gotsig(int sig UNUSED_PARAM) 65static 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;
76int more_main(int argc UNUSED_PARAM, char **argv) 77int 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}