aboutsummaryrefslogtreecommitdiff
path: root/miscutils/less.c
diff options
context:
space:
mode:
author"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-09-19 10:28:43 +0000
committer"Vladimir N. Oleynik" <dzo@simtreas.ru>2005-09-19 10:28:43 +0000
commita0ae6de84811a603d2138d06d7f0b1f159074368 (patch)
treecf9b906c79f7a329cf5b170d0e32d3efe340476d /miscutils/less.c
parent4cbe45934ec2352d87118d0d7a52ff926909a1eb (diff)
downloadbusybox-w32-a0ae6de84811a603d2138d06d7f0b1f159074368.tar.gz
busybox-w32-a0ae6de84811a603d2138d06d7f0b1f159074368.tar.bz2
busybox-w32-a0ae6de84811a603d2138d06d7f0b1f159074368.zip
quick patchs: drop founded memory leak, more libbb, more C-compatibility, size reduction
Diffstat (limited to 'miscutils/less.c')
-rw-r--r--miscutils/less.c171
1 files changed, 89 insertions, 82 deletions
diff --git a/miscutils/less.c b/miscutils/less.c
index 3fd22ca19..1b993ea2c 100644
--- a/miscutils/less.c
+++ b/miscutils/less.c
@@ -20,26 +20,26 @@
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 * 02111-1307 USA 21 * 02111-1307 USA
22 * 22 *
23 * This program needs a lot of development, so consider it in a beta stage 23 * This program needs a lot of development, so consider it in a beta stage
24 * at best. 24 * at best.
25 * 25 *
26 * TODO: 26 * TODO:
27 * - Add more regular expression support - search modifiers, certain matches, etc. 27 * - Add more regular expression support - search modifiers, certain matches, etc.
28 * - Add more complex bracket searching - currently, nested brackets are 28 * - Add more complex bracket searching - currently, nested brackets are
29 * not considered. 29 * not considered.
30 * - Add support for "F" as an input. This causes less to act in 30 * - Add support for "F" as an input. This causes less to act in
31 * a similar way to tail -f. 31 * a similar way to tail -f.
32 * - Check for binary files, and prompt the user if a binary file 32 * - Check for binary files, and prompt the user if a binary file
33 * is detected. 33 * is detected.
34 * - Allow horizontal scrolling. Currently, lines simply continue onto 34 * - Allow horizontal scrolling. Currently, lines simply continue onto
35 * the next line, per the terminal's discretion 35 * the next line, per the terminal's discretion
36 * 36 *
37 * Notes: 37 * Notes:
38 * - filename is an array and not a pointer because that avoids all sorts 38 * - filename is an array and not a pointer because that avoids all sorts
39 * of complications involving the fact that something that is pointed to 39 * of complications involving the fact that something that is pointed to
40 * will be changed if the pointer is changed. 40 * will be changed if the pointer is changed.
41 * - the inp file pointer is used so that keyboard input works after 41 * - the inp file pointer is used so that keyboard input works after
42 * redirected input has been read from stdin 42 * redirected input has been read from stdin
43*/ 43*/
44 44
45#include <stdio.h> 45#include <stdio.h>
@@ -77,7 +77,7 @@
77#define NORMAL "\033[0m" 77#define NORMAL "\033[0m"
78 78
79/* The escape code to clear the screen */ 79/* The escape code to clear the screen */
80#define CLEAR "\033[2J" 80#define CLEAR "\033[H\033[J"
81 81
82/* Maximum number of lines in a file */ 82/* Maximum number of lines in a file */
83#define MAXLINES 10000 83#define MAXLINES 10000
@@ -142,13 +142,6 @@ static void set_tty_cooked(void) {
142 142
143/* Set terminal input to raw mode (taken from vi.c) */ 143/* Set terminal input to raw mode (taken from vi.c) */
144static void set_tty_raw(void) { 144static void set_tty_raw(void) {
145 tcgetattr(0, &term_orig);
146 term_vi = term_orig;
147 term_vi.c_lflag &= (~ICANON & ~ECHO);
148 term_vi.c_iflag &= (~IXON & ~ICRNL);
149 term_vi.c_oflag &= (~ONLCR);
150 term_vi.c_cc[VMIN] = 1;
151 term_vi.c_cc[VTIME] = 0;
152 tcsetattr(0, TCSANOW, &term_vi); 145 tcsetattr(0, TCSANOW, &term_vi);
153} 146}
154 147
@@ -169,36 +162,34 @@ static void tless_exit(int code) {
169 special return codes. Note that this function works best with raw input. */ 162 special return codes. Note that this function works best with raw input. */
170static int tless_getch(void) { 163static int tless_getch(void) {
171 164
165 int input;
166
172 set_tty_raw(); 167 set_tty_raw();
173 char input_key[3];
174 168
175 input_key[0] = getc(inp); 169 input = getc(inp);
176 /* Detect escape sequences (i.e. arrow keys) and handle 170 /* Detect escape sequences (i.e. arrow keys) and handle
177 them accordingly */ 171 them accordingly */
178 172
179 if (input_key[0] == '\033') { 173 if (input == '\033' && getc(inp) == '[') {
180 input_key[1] = getc(inp); 174 input = getc(inp);
181 input_key[2] = getc(inp);
182 set_tty_cooked(); 175 set_tty_cooked();
183 if (input_key[1] == '[') { 176 if (input == REAL_KEY_UP)
184 if (input_key[2] == REAL_KEY_UP) 177 return KEY_UP;
185 return KEY_UP; 178 else if (input == REAL_KEY_DOWN)
186 else if (input_key[2] == REAL_KEY_DOWN) 179 return KEY_DOWN;
187 return KEY_DOWN; 180 else if (input == REAL_KEY_RIGHT)
188 else if (input_key[2] == REAL_KEY_RIGHT) 181 return KEY_RIGHT;
189 return KEY_RIGHT; 182 else if (input == REAL_KEY_LEFT)
190 else if (input_key[2] == REAL_KEY_LEFT) 183 return KEY_LEFT;
191 return KEY_LEFT; 184 else if (input == REAL_PAGE_UP)
192 else if (input_key[2] == REAL_PAGE_UP) 185 return PAGE_UP;
193 return PAGE_UP; 186 else if (input == REAL_PAGE_DOWN)
194 else if (input_key[2] == REAL_PAGE_DOWN) 187 return PAGE_DOWN;
195 return PAGE_DOWN;
196 }
197 } 188 }
198 /* The input is a normal ASCII value */ 189 /* The input is a normal ASCII value */
199 else { 190 else {
200 set_tty_cooked(); 191 set_tty_cooked();
201 return input_key[0]; 192 return input;
202 } 193 }
203 return 0; 194 return 0;
204} 195}
@@ -222,8 +213,7 @@ static void add_linenumbers(void) {
222 213
223 for (i = 0; i <= num_flines; i++) { 214 for (i = 0; i <= num_flines; i++) {
224 safe_strncpy(current_line, flines[i], 256); 215 safe_strncpy(current_line, flines[i], 256);
225 flines[i] = xrealloc(flines[i], strlen(current_line) + 7); 216 bb_xasprintf(&flines[i],"%5d %s", i + 1, current_line);
226 sprintf(flines[i],"%5d %s", i + 1, current_line);
227 } 217 }
228} 218}
229 219
@@ -241,12 +231,12 @@ static void data_readlines(void) {
241 rewind(fp); 231 rewind(fp);
242 /* Initialise fp */ 232 /* Initialise fp */
243 flines = malloc(i * sizeof(char *)); 233 flines = malloc(i * sizeof(char *));
244 234
245 for (i = 0; (!feof(fp)) && (i <= MAXLINES); i++) { 235 for (i = 0; (!feof(fp)) && (i <= MAXLINES); i++) {
246 strcpy(current_line, ""); 236 strcpy(current_line, "");
247 fgets(current_line, 256, fp); 237 fgets(current_line, 256, fp);
248 bb_xferror(fp, filename); 238 bb_xferror(fp, filename);
249 flines[i] = (char *) bb_xstrndup(current_line, (strlen(current_line) + 1) * sizeof(char)); 239 flines[i] = bb_xstrdup(current_line);
250 } 240 }
251 num_flines = i - 2; 241 num_flines = i - 2;
252 242
@@ -258,7 +248,7 @@ static void data_readlines(void) {
258 fclose(fp); 248 fclose(fp);
259 249
260 inp = (inp_stdin) ? fopen(CURRENT_TTY, "r") : stdin; 250 inp = (inp_stdin) ? fopen(CURRENT_TTY, "r") : stdin;
261 251
262 if (ea_inp_stdin) { 252 if (ea_inp_stdin) {
263 fclose(inp); 253 fclose(inp);
264 inp = fopen(CURRENT_TTY, "r"); 254 inp = fopen(CURRENT_TTY, "r");
@@ -307,7 +297,7 @@ static void m_status_print(void) {
307 } 297 }
308 else { 298 else {
309 percentage = calc_percent(); 299 percentage = calc_percent();
310 printf("%i%s %s", percentage, "%", NORMAL); 300 printf("%i%% %s", percentage, NORMAL);
311 } 301 }
312 } 302 }
313 else { 303 else {
@@ -325,11 +315,11 @@ static void medium_status_print(void) {
325 percentage = calc_percent(); 315 percentage = calc_percent();
326 316
327 if (!line_pos) 317 if (!line_pos)
328 printf("%s%s %i%s%s", HIGHLIGHT, filename, percentage, "%", NORMAL); 318 printf("%s%s %i%%%s", HIGHLIGHT, filename, percentage, NORMAL);
329 else if (line_pos == num_flines - height + 2) 319 else if (line_pos == num_flines - height + 2)
330 printf("%s(END)%s", HIGHLIGHT, NORMAL); 320 printf("%s(END)%s", HIGHLIGHT, NORMAL);
331 else 321 else
332 printf("%s%i%s%s", HIGHLIGHT, percentage, "%", NORMAL); 322 printf("%s%i%%%s", HIGHLIGHT, percentage, NORMAL);
333} 323}
334#endif 324#endif
335 325
@@ -368,15 +358,12 @@ static void buffer_print(void) {
368 358
369 int i; 359 int i;
370 360
361 printf("%s", CLEAR);
371 if (num_flines >= height - 2) { 362 if (num_flines >= height - 2) {
372 printf("%s", CLEAR);
373 move_cursor(0,0);
374 for (i = 0; i < height - 1; i++) 363 for (i = 0; i < height - 1; i++)
375 printf("%s", buffer[i]); 364 printf("%s", buffer[i]);
376 } 365 }
377 else { 366 else {
378 printf("%s", CLEAR);
379 move_cursor(0,0);
380 for (i = 1; i < (height - 1 - num_flines); i++) 367 for (i = 1; i < (height - 1 - num_flines); i++)
381 putchar('\n'); 368 putchar('\n');
382 for (i = 0; i < height - 1; i++) 369 for (i = 0; i < height - 1; i++)
@@ -391,9 +378,14 @@ static void buffer_init(void) {
391 378
392 int i; 379 int i;
393 380
394 /* malloc the number of lines needed for the buffer */ 381 if(buffer == NULL) {
395 buffer = xrealloc(buffer, height * sizeof(char *)); 382 /* malloc the number of lines needed for the buffer */
396 383 buffer = xrealloc(buffer, height * sizeof(char *));
384 } else {
385 for (i = 0; i < (height - 1); i++)
386 free(buffer[i]);
387 }
388
397 /* Fill the buffer until the end of the file or the 389 /* Fill the buffer until the end of the file or the
398 end of the buffer is reached */ 390 end of the buffer is reached */
399 for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) { 391 for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) {
@@ -402,7 +394,7 @@ static void buffer_init(void) {
402 394
403 /* If the buffer still isn't full, fill it with blank lines */ 395 /* If the buffer still isn't full, fill it with blank lines */
404 for (; i < (height - 1); i++) { 396 for (; i < (height - 1); i++) {
405 buffer[i] = ""; 397 buffer[i] = bb_xstrdup("");
406 } 398 }
407} 399}
408 400
@@ -414,16 +406,20 @@ static void buffer_down(int nlines) {
414 if (!past_eof) { 406 if (!past_eof) {
415 if (line_pos + (height - 3) + nlines < num_flines) { 407 if (line_pos + (height - 3) + nlines < num_flines) {
416 line_pos += nlines; 408 line_pos += nlines;
417 for (i = 0; i < (height - 1); i++) 409 for (i = 0; i < (height - 1); i++) {
410 free(buffer[i]);
418 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]); 411 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
412 }
419 } 413 }
420 else { 414 else {
421 /* As the number of lines requested was too large, we just move 415 /* As the number of lines requested was too large, we just move
422 to the end of the file */ 416 to the end of the file */
423 while (line_pos + (height - 3) + 1 < num_flines) { 417 while (line_pos + (height - 3) + 1 < num_flines) {
424 line_pos += 1; 418 line_pos += 1;
425 for (i = 0; i < (height - 1); i++) 419 for (i = 0; i < (height - 1); i++) {
420 free(buffer[i]);
426 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]); 421 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
422 }
427 } 423 }
428 } 424 }
429 425
@@ -441,16 +437,20 @@ static void buffer_up(int nlines) {
441 if (!past_eof) { 437 if (!past_eof) {
442 if (line_pos - nlines >= 0) { 438 if (line_pos - nlines >= 0) {
443 line_pos -= nlines; 439 line_pos -= nlines;
444 for (i = 0; i < (height - 1); i++) 440 for (i = 0; i < (height - 1); i++) {
441 free(buffer[i]);
445 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]); 442 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
443 }
446 } 444 }
447 else { 445 else {
448 /* As the requested number of lines to move was too large, we 446 /* As the requested number of lines to move was too large, we
449 move one line up at a time until we can't. */ 447 move one line up at a time until we can't. */
450 while (line_pos != 0) { 448 while (line_pos != 0) {
451 line_pos -= 1; 449 line_pos -= 1;
452 for (i = 0; i < (height - 1); i++) 450 for (i = 0; i < (height - 1); i++) {
451 free(buffer[i]);
453 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]); 452 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
453 }
454 } 454 }
455 } 455 }
456 } 456 }
@@ -469,11 +469,12 @@ static void buffer_up(int nlines) {
469 /* We only move part of the buffer, as the rest 469 /* We only move part of the buffer, as the rest
470 is past the EOF */ 470 is past the EOF */
471 for (i = 0; i < (height - 1); i++) { 471 for (i = 0; i < (height - 1); i++) {
472 free(buffer[i]);
472 if (i < tilde_line - nlines + 1) 473 if (i < tilde_line - nlines + 1)
473 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]); 474 buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
474 else { 475 else {
475 if (line_pos >= num_flines - height + 2) 476 if (line_pos >= num_flines - height + 2)
476 buffer[i] = "~\n"; 477 buffer[i] = bb_xstrdup("~\n");
477 } 478 }
478 } 479 }
479 } 480 }
@@ -491,12 +492,15 @@ static void buffer_line(int linenum) {
491 printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL); 492 printf("%s%s%i%s", HIGHLIGHT, "Cannot seek to line number ", linenum, NORMAL);
492 } 493 }
493 else if (linenum < (num_flines - height - 2)) { 494 else if (linenum < (num_flines - height - 2)) {
494 for (i = 0; i < (height - 1); i++) 495 for (i = 0; i < (height - 1); i++) {
496 free(buffer[i]);
495 buffer[i] = (char *) bb_xstrdup(flines[linenum + i]); 497 buffer[i] = (char *) bb_xstrdup(flines[linenum + i]);
498 }
496 line_pos = linenum; 499 line_pos = linenum;
497 } 500 }
498 else { 501 else {
499 for (i = 0; i < (height - 1); i++) { 502 for (i = 0; i < (height - 1); i++) {
503 free(buffer[i]);
500 if (linenum + i < num_flines + 2) 504 if (linenum + i < num_flines + 2)
501 buffer[i] = (char *) bb_xstrdup(flines[linenum + i]); 505 buffer[i] = (char *) bb_xstrdup(flines[linenum + i]);
502 else 506 else
@@ -516,7 +520,7 @@ static void reinitialise(void) {
516 for (i = 0; i <= num_flines; i++) 520 for (i = 0; i <= num_flines; i++)
517 free(flines[i]); 521 free(flines[i]);
518 free(flines); 522 free(flines);
519 523
520 data_readlines(); 524 data_readlines();
521 buffer_init(); 525 buffer_init();
522 buffer_print(); 526 buffer_print();
@@ -629,15 +633,10 @@ static void colon_process(void) {
629 633
630static char *insert_highlights (char *line, int start, int end) { 634static char *insert_highlights (char *line, int start, int end) {
631 635
632 char *new_line = (char *) malloc((sizeof(char) * (strlen(line) + 1)) + 10); 636 char *new_line;
633
634 memset(new_line, 0, ((sizeof(char) * (strlen(line) + 1)) + 10));
635 strncat(new_line, line, start);
636 strcat(new_line, HIGHLIGHT);
637 strncat(new_line, line + start, end - start);
638 strcat(new_line, NORMAL);
639 strncat(new_line, line + end, strlen(line) - end);
640 637
638 bb_xasprintf(&new_line, "%.*s%s%.*s%s%s", start, line, HIGHLIGHT,
639 end - start, line + start, NORMAL, line + end);
641 return new_line; 640 return new_line;
642} 641}
643 642
@@ -652,7 +651,7 @@ static char *process_regex_on_line(char *line, regex_t *pattern) {
652 char sub_line[256]; 651 char sub_line[256];
653 int prev_eo = 0; 652 int prev_eo = 0;
654 regmatch_t match_structs; 653 regmatch_t match_structs;
655 654
656 memset(sub_line, 0, 256); 655 memset(sub_line, 0, 256);
657 strcpy(line2, line); 656 strcpy(line2, line);
658 657
@@ -869,7 +868,7 @@ static void show_flag_status(void) {
869 } 868 }
870 869
871 clear_line(); 870 clear_line();
872 printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val, NORMAL); 871 printf("%s%s%i%s", HIGHLIGHT, "The status of the flag is: ", flag_val != 0, NORMAL);
873} 872}
874#endif 873#endif
875 874
@@ -940,7 +939,7 @@ static void goto_mark(void) {
940 printf("Go to mark: "); 939 printf("Go to mark: ");
941 letter = tless_getch(); 940 letter = tless_getch();
942 clear_line(); 941 clear_line();
943 942
944 if (isalpha(letter)) { 943 if (isalpha(letter)) {
945 for (i = 0; i <= num_marks; i++) 944 for (i = 0; i <= num_marks; i++)
946 if (letter == mark_lines[i][0]) { 945 if (letter == mark_lines[i][0]) {
@@ -985,7 +984,7 @@ static void match_right_bracket(char bracket) {
985 int i; 984 int i;
986 985
987 clear_line(); 986 clear_line();
988 987
989 if (strchr(flines[line_pos], bracket) == NULL) 988 if (strchr(flines[line_pos], bracket) == NULL)
990 printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL); 989 printf("%s%s%s", HIGHLIGHT, "No bracket in top line", NORMAL);
991 else { 990 else {
@@ -1010,7 +1009,7 @@ static void match_left_bracket (char bracket) {
1010 int i; 1009 int i;
1011 1010
1012 clear_line(); 1011 clear_line();
1013 1012
1014 if (strchr(flines[line_pos + height - 2], bracket) == NULL) { 1013 if (strchr(flines[line_pos + height - 2], bracket) == NULL) {
1015 printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL); 1014 printf("%s%s%s", HIGHLIGHT, "No bracket in bottom line", NORMAL);
1016 printf("%s", flines[line_pos + height]); 1015 printf("%s", flines[line_pos + height]);
@@ -1168,6 +1167,14 @@ int less_main(int argc, char **argv) {
1168 1167
1169 strcpy(filename, (inp_stdin) ? "stdin" : files[0]); 1168 strcpy(filename, (inp_stdin) ? "stdin" : files[0]);
1170 tty_width_height(); 1169 tty_width_height();
1170 tcgetattr(0, &term_orig);
1171 term_vi = term_orig;
1172 term_vi.c_lflag &= (~ICANON & ~ECHO);
1173 term_vi.c_iflag &= (~IXON & ~ICRNL);
1174 term_vi.c_oflag &= (~ONLCR);
1175 term_vi.c_cc[VMIN] = 1;
1176 term_vi.c_cc[VTIME] = 0;
1177
1171 data_readlines(); 1178 data_readlines();
1172 buffer_init(); 1179 buffer_init();
1173 buffer_print(); 1180 buffer_print();