This is a slightly modified version of my getLine() function, used for reliable user input. Here you can see the details of the original, but this one has been modified to use termios material, which allows you to control the degree of input.
Since termios operates at a lower level than standard C input, this also affects this.
First, the required headers and return values ββfrom the getLine() function:
#include <termios.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #define OK 0 #define NO_INPUT 1 #define TOO_LONG 2 #define TERM_PROB 3
Further, an auxiliary function for returning the terminal to its original state, this makes it easy to return a value from getLine() , knowing that the terminal will remain in its original state.
static int revertTerm (int fd, struct termios *ptio, int old, int rc) {
Next, the actual getLine() function getLine() , which modifies the terminal's attributes to make the ESC kill character, then calls fgets() along with all the additional functions to request, detect buffer overflows, enter a flush at the end of the line, etc.
During the time that the user is within fgets() as part of this function, the changed behavior of the terminal is active, and you can use ESC to clear the line.
static int getLine (char *prmpt, char *buff, size_t sz) { int old, fd, ch, extra; struct termios tio; // Modify teminal so ESC is KILL character. fd = open ("/dev/tty", O_RDWR); if (fd < 0) return TERM_PROB; tcgetattr (fd, &tio); old = tio.c_cc[VKILL]; tio.c_cc[VKILL] = 0x1b; tcsetattr (fd, TCSANOW, &tio); // Get line with buffer overrun protection. if (prmpt != NULL) { printf ("%s", prmpt); fflush (stdout); } if (fgets (buff, sz, stdin) == NULL) return revertTerm (fd, &tio, old, NO_INPUT); // If it was too long, there'll be no newline. In that case, we flush // to end of line so that excess doesn't affect the next call. if (buff[strlen(buff)-1] != '\n') { extra = 0; while (((ch = getchar()) != '\n') && (ch != EOF)) extra = 1; return revertTerm (fd, &tio, old, (extra == 1) ? TOO_LONG : OK); } // Otherwise remove newline and give string back to caller. buff[strlen(buff)-1] = '\0'; return revertTerm (fd, &tio, old, OK); }
And finally, a test program so you can test its behavior. Basically, this will allow you to enter lines of up to twenty characters, then prints them with status (too long, no input, etc.).
If at any time during the input process you press ESC , it will kill the line and start again.
Entering exit will exit the program.
// Test program for getLine(). int main (void) { int rc, done = 0; char buff[21]; while (!done) { rc = getLine ("Enter string (ESC to clear, exit to stop)> ", buff, sizeof(buff)); if (rc == NO_INPUT) { // Extra NL since my system doesn't output that on EOF. printf ("\nNo input\n"); } else if (rc == TOO_LONG) { printf ("Input too long [%s]\n", buff); } else { done = (strcmp (buff, "exit") == 0); if (!done) printf ("OK [%s]\n", buff); } } return 0; }