Skip to content

Instantly share code, notes, and snippets.

@emandret
Created November 15, 2021 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emandret/9ad3066e10523c80804d3345b91adcc2 to your computer and use it in GitHub Desktop.
Save emandret/9ad3066e10523c80804d3345b91adcc2 to your computer and use it in GitHub Desktop.
Compare the canonical vs. noncanonical input modes of the TTY line driver
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#define MAX_BUFSIZE 4096
int main(int argc, char *argv[])
{
struct termios old_termios;
struct termios new_termios;
char *tty_devfile;
char buf[MAX_BUFSIZE];
int bytes_read;
if ( argc < 2 ) {
dprintf(2, "Pass argument 1 for canonical mode, 0 for noncanonical\n");
return 1;
}
if ( !isatty(0) ) {
dprintf(2, "STDIN is not a terminal device\n");
return 1;
}
if ( (tty_devfile = ttyname(0)) ) {
dprintf(2, "Using terminal device %s\n", tty_devfile);
}
if ( tcgetattr(0, &old_termios) == -1 ) {
perror("Error while getting old terminal settings");
return 1;
}
new_termios = old_termios;
switch ( argv[1][0] ) {
case '0':
// If MIN > 0 then a pending read is not satisfied until MIN bytes are received. A program that uses this case
// to read record-based terminal I/O may block indefinitely in the read operation. If MIN = 0 and no characters
// are available, read is nonblocking and returns a value of zero, having read no data.
new_termios.c_lflag &= ~(ICANON | ECHO);
new_termios.c_cc[VMIN] = 0;
new_termios.c_cc[VTIME] = 0;
break;
case '1':
new_termios.c_lflag &= ICANON | ECHO | ECHOE;
new_termios.c_cc[VMIN] = 0;
new_termios.c_cc[VTIME] = 0;
break;
default:
dprintf(2, "Invalid argument\n");
return 1;
}
if ( tcsetattr(0, TCSADRAIN, &new_termios) == -1 ) {
perror("Error while setting new terminal settings");
return 1;
}
while ( (bytes_read = read(0, buf, sizeof(buf) - 1)) != -1 ) {
if ( bytes_read > 0 ) {
buf[bytes_read] = '\0';
if ( buf[0] == 'q' ) {
dprintf(2, "Exiting...\n");
break;
}
dprintf(2, "Bytes read: %d\n", bytes_read);
dprintf(2, "Buffer content: %s\n", buf);
}
}
if ( tcsetattr(0, TCSADRAIN, &old_termios) == -1 ) {
perror("Error while resetting old terminal settings");
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment