more correction for getopt_ulflags() documentation by author of this fuck logic
[oweals/busybox.git] / miscutils / less.c
index 1b993ea2c226a5ca4c7912b821694861211b4d0e..189b886f712c5480e35516db3d4f0014c16936e4 100644 (file)
@@ -108,11 +108,6 @@ static unsigned long flags;
 /* This is needed so that program behaviour changes when input comes from
    stdin */
 static int inp_stdin;
-/* This is required so that when a file is requested to be examined after
-   input has come from stdin (e.g. dmesg | less), the input stream from
-   the keyboard still stays the same. If it switched back to stdin, keyboard
-   input wouldn't work. */
-static int ea_inp_stdin;
 
 #ifdef CONFIG_FEATURE_LESS_MARKS
 static int mark_lines[15][2];
@@ -137,12 +132,12 @@ static FILE *inp;
 /* Reset terminal input to normal */
 static void set_tty_cooked(void) {
        fflush(stdout);
-       tcsetattr(0, TCSANOW, &term_orig);
+       tcsetattr(fileno(inp), TCSANOW, &term_orig);
 }
 
 /* Set terminal input to raw mode  (taken from vi.c) */
 static void set_tty_raw(void) {
-       tcsetattr(0, TCSANOW, &term_vi);
+       tcsetattr(fileno(inp), TCSANOW, &term_vi);
 }
 
 /* Exit the program gracefully */
@@ -213,7 +208,7 @@ static void add_linenumbers(void) {
 
        for (i = 0; i <= num_flines; i++) {
                safe_strncpy(current_line, flines[i], 256);
-               bb_xasprintf(&flines[i],"%5d %s", i + 1, current_line);
+               flines[i] = bb_xasprintf("%5d %s", i + 1, current_line);
        }
 }
 
@@ -224,35 +219,26 @@ static void data_readlines(void) {
        FILE *fp;
 
        fp = (inp_stdin) ? stdin : bb_xfopen(filename, "rt");
-
-       /* First of all, we need to know the number of lines so that flines can be initialised. */
-       for (i = 0; (!feof(fp)) && (i <= MAXLINES); i++)
-               fgets(current_line, 256, fp);
-       rewind(fp);
-       /* Initialise fp */
-       flines = malloc(i * sizeof(char *));
-
-       for (i = 0; (!feof(fp)) && (i <= MAXLINES); i++) {
+       flines = NULL;
+       for (i = 0; (feof(fp)==0) && (i <= MAXLINES); i++) {
                strcpy(current_line, "");
                fgets(current_line, 256, fp);
-               bb_xferror(fp, filename);
+               if(fp != stdin)
+                       bb_xferror(fp, filename);
+               flines = xrealloc(flines, (i+1) * sizeof(char *));
                flines[i] = bb_xstrdup(current_line);
        }
        num_flines = i - 2;
 
-/* Reset variables for a new file */
+       /* Reset variables for a new file */
 
        line_pos = 0;
        past_eof = 0;
 
        fclose(fp);
 
-       inp = (inp_stdin) ? fopen(CURRENT_TTY, "r") : stdin;
-
-       if (ea_inp_stdin) {
-               fclose(inp);
-               inp = fopen(CURRENT_TTY, "r");
-       }
+       if(inp == NULL)
+               inp = (inp_stdin) ? fopen(CURRENT_TTY, "r") : stdin;
 
        if (flags & FLAG_N)
                add_linenumbers();
@@ -346,7 +332,7 @@ static void status_print(void) {
                                printf("%s%s%s%s", HIGHLIGHT, "- Next: ", files[current_file], NORMAL);
                }
                else {
-                       printf("%c", ':');
+                       putchar(':');
                }
 #ifdef CONFIG_FEATURE_LESS_FLAGS
        }
@@ -389,7 +375,7 @@ static void buffer_init(void) {
        /* Fill the buffer until the end of the file or the
           end of the buffer is reached */
        for (i = 0; (i < (height - 1)) && (i <= num_flines); i++) {
-               buffer[i] = (char *) bb_xstrdup(flines[i]);
+               buffer[i] = bb_xstrdup(flines[i]);
        }
 
        /* If the buffer still isn't full, fill it with blank lines */
@@ -408,7 +394,7 @@ static void buffer_down(int nlines) {
                        line_pos += nlines;
                        for (i = 0; i < (height - 1); i++) {
                                free(buffer[i]);
-                               buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
+                               buffer[i] = bb_xstrdup(flines[line_pos + i]);
                        }
                }
                else {
@@ -418,7 +404,7 @@ static void buffer_down(int nlines) {
                                line_pos += 1;
                                for (i = 0; i < (height - 1); i++) {
                                        free(buffer[i]);
-                                       buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
+                                       buffer[i] = bb_xstrdup(flines[line_pos + i]);
                                }
                        }
                }
@@ -439,7 +425,7 @@ static void buffer_up(int nlines) {
                        line_pos -= nlines;
                        for (i = 0; i < (height - 1); i++) {
                                free(buffer[i]);
-                               buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
+                               buffer[i] = bb_xstrdup(flines[line_pos + i]);
                        }
                }
                else {
@@ -449,7 +435,7 @@ static void buffer_up(int nlines) {
                                line_pos -= 1;
                                for (i = 0; i < (height - 1); i++) {
                                        free(buffer[i]);
-                                       buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
+                                       buffer[i] = bb_xstrdup(flines[line_pos + i]);
                                }
                        }
                }
@@ -471,7 +457,7 @@ static void buffer_up(int nlines) {
                        for (i = 0; i < (height - 1); i++) {
                                free(buffer[i]);
                                if (i < tilde_line - nlines + 1)
-                                       buffer[i] = (char *) bb_xstrdup(flines[line_pos + i]);
+                                       buffer[i] = bb_xstrdup(flines[line_pos + i]);
                                else {
                                        if (line_pos >= num_flines - height + 2)
                                                buffer[i] = bb_xstrdup("~\n");
@@ -494,7 +480,7 @@ static void buffer_line(int linenum) {
        else if (linenum < (num_flines - height - 2)) {
                for (i = 0; i < (height - 1); i++) {
                        free(buffer[i]);
-                       buffer[i] = (char *) bb_xstrdup(flines[linenum + i]);
+                       buffer[i] = bb_xstrdup(flines[linenum + i]);
                }
                line_pos = linenum;
        }
@@ -502,9 +488,9 @@ static void buffer_line(int linenum) {
                for (i = 0; i < (height - 1); i++) {
                        free(buffer[i]);
                        if (linenum + i < num_flines + 2)
-                               buffer[i] = (char *) bb_xstrdup(flines[linenum + i]);
+                               buffer[i] = bb_xstrdup(flines[linenum + i]);
                        else
-                               buffer[i] = (char *) bb_xstrdup((flags & FLAG_TILDE) ? "\n" : "~\n");
+                               buffer[i] = bb_xstrdup((flags & FLAG_TILDE) ? "\n" : "~\n");
                }
                line_pos = linenum;
                /* Set past_eof so buffer_down and buffer_up act differently */
@@ -539,12 +525,11 @@ static void examine_file(void) {
        newline_offset = strlen(filename) - 1;
        filename[newline_offset] = '\0';
 
-       files[num_files] = bb_xstrndup(filename, (strlen(filename) + 1) * sizeof(char));
+       files[num_files] = bb_xstrdup(filename);
        current_file = num_files + 1;
        num_files++;
 
        inp_stdin = 0;
-       ea_inp_stdin = 1;
        reinitialise();
 }
 
@@ -633,11 +618,8 @@ static void colon_process(void) {
 
 static char *insert_highlights (char *line, int start, int end) {
 
-       char *new_line;
-
-       bb_xasprintf(&new_line, "%.*s%s%.*s%s%s", start, line, HIGHLIGHT,
+       return bb_xasprintf("%.*s%s%.*s%s%s", start, line, HIGHLIGHT,
                        end - start, line + start, NORMAL, line + end);
-       return new_line;
 }
 
 static char *process_regex_on_line(char *line, regex_t *pattern) {
@@ -696,7 +678,15 @@ static void regex_process(void) {
        /* Get the uncompiled regular expression from the user */
        clear_line();
        putchar((match_backwards) ? '?' : '/');
-       scanf("%s", uncomp_regex);
+       uncomp_regex[0] = 0;
+       fgets(uncomp_regex, sizeof(uncomp_regex), stdin);
+       i = strlen(uncomp_regex);
+       if(i > 0) {
+               if(uncomp_regex[i-1] == '\n')
+                       uncomp_regex[i-1] = '\0';
+               else
+                       while((i = getchar()) != '\n' && i != EOF);
+       }
 
        /* Compile the regex and check for errors */
        xregcomp(pattern, uncomp_regex, 0);
@@ -704,7 +694,7 @@ static void regex_process(void) {
        /* Run the regex on each line of the current file here */
        for (i = 0; i <= num_flines; i++) {
                strcpy(current_line, process_regex_on_line(flines[i], pattern));
-               flines[i] = (char *) bb_xstrndup(current_line, sizeof(char) * (strlen(current_line)+1));
+               flines[i] = bb_xstrdup(current_line);
                if (match_found) {
                        match_lines[j] = i;
                        j++;
@@ -712,7 +702,6 @@ static void regex_process(void) {
        }
 
        num_matches = j;
-
        if ((match_lines[0] != -1) && (num_flines > height - 2))
                buffer_line(match_lines[0]);
        else
@@ -757,23 +746,26 @@ static void number_process(int first_digit) {
        int num;
        char num_input[80];
        char keypress;
+       char *endptr;
+
        num_input[0] = first_digit;
 
        /* Clear the current line, print a prompt, and then print the digit */
        clear_line();
        printf(":%c", first_digit);
 
-       /* Receive input until a letter is given */
-       while((num_input[i] = tless_getch()) && isdigit(num_input[i])) {
-               printf("%c", num_input[i]);
+       /* Receive input until a letter is given (max 80 chars)*/
+       while((i < 80) && (num_input[i] = tless_getch()) && isdigit(num_input[i])) {
+               putchar(num_input[i]);
                i++;
        }
 
        /* Take the final letter out of the digits string */
        keypress = num_input[i];
        num_input[i] = '\0';
-       i--;
-       num = atoi(num_input);
+       num = strtol(num_input, &endptr, 10);
+       if (endptr==num_input || *endptr!='\0' || num < 1 || num > MAXLINES)
+               goto END;
 
        /* We now know the number and the letter entered, so we process them */
        switch (keypress) {
@@ -806,7 +798,7 @@ static void number_process(int first_digit) {
                default:
                        break;
        }
-
+END:
        buffer_print();
 }
 
@@ -821,16 +813,16 @@ static void flag_change(void) {
 
        switch (keypress) {
                case 'M':
-                       flags &= ~FLAG_M;
+                       flags ^= FLAG_M;
                        break;
                case 'm':
-                       flags &= ~FLAG_m;
+                       flags ^= FLAG_m;
                        break;
                case 'E':
-                       flags &= ~FLAG_E;
+                       flags ^= FLAG_E;
                        break;
                case '~':
-                       flags &= ~FLAG_TILDE;
+                       flags ^= FLAG_TILDE;
                        break;
                default:
                        break;
@@ -1165,17 +1157,16 @@ int less_main(int argc, char **argv) {
                }
        }
 
-       strcpy(filename, (inp_stdin) ? "stdin" : files[0]);
+       strcpy(filename, (inp_stdin) ? bb_msg_standard_input : files[0]);
        tty_width_height();
-       tcgetattr(0, &term_orig);
+       data_readlines();
+       tcgetattr(fileno(inp), &term_orig);
        term_vi = term_orig;
        term_vi.c_lflag &= (~ICANON & ~ECHO);
        term_vi.c_iflag &= (~IXON & ~ICRNL);
        term_vi.c_oflag &= (~ONLCR);
        term_vi.c_cc[VMIN] = 1;
        term_vi.c_cc[VTIME] = 0;
-
-       data_readlines();
        buffer_init();
        buffer_print();