0

I'm trying to write a "more"(just like "more" instruction in Linux) program in C. Quit when "q" is pressed and show one more page when " " is pressed. But everytime I have to press Enter after the command. I tried to use setbuf() and setvbuf() but it doesn't work.Why?How should I do?

FILE *fp_tty; //read from keyboard
fp_tty = fopen("/dev/tty", "r");
setbuf(fp_tty, NULL);
see_more(fp_tty);
......
int see_more(FILE *cmd) {
    int c;
    printf("\033[7m more? \033[m"); 
    while ((c = getc(cmd)) != EOF) {
        if (c == 'q') {
            return 0; //quit
        }
        if (c == ' ') {
            return PAGELEN; //next page
        }
        if (c == '\n') {
            return 1; //1 line
        }
    }
    return 0;
}
0andriy
  • 4,183
  • 1
  • 24
  • 37
  • 2
    [Start here](https://man7.org/linux/man-pages/man3/tcflush.3.html). First make a large pot of coffee or whatever you imbibe in its place. – rici Jan 06 '22 at 07:38

1 Answers1

0

Linux shares the tty rules of most Unix systems. When a device is seen as a terminal input meaning here something that receive key presses from a human being, the input is by default line oriented. The rationale is that the user is allowed to press a wrong key, cancel it, and finaly press the correct key. In that case, the tty driver handles the fix and only present the final string to the application.

That works fine for line oriented application, but would be foolish for plain screen ones like emacs or vi (yeah, they are from the 70's too...), so the tty driver can be set in raw mode to immediately pass any character to the application (other options exist...). That what the curses library use under the hood to be able to immediately react to any key press.

TL/DR: you must put the tty driver in raw mode to be able to immediately process a character. The details are on the tcflush man page.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252