Programación de la terminal de Linux
Modo canónico vs. no-canónico
Por defecto, la entrada por teclado desde la terminal no se envía al programa hasta que el usuario presiona la tecla Enter. En la mayoría de los casos, esto es un beneficio dado que permite al usuario corregir errores de escritura usando la tecla Backspace, y solo cuando se está satisfecho con lo escrito en pantalla, se presiona Enter para enviar dicha cadena de texto al programa.
Este comportamiento se llama modo canónico o estándar. Toda la entrada se procesa en términos de líneas. Hasta que se complete una línea de entrada (generalmente cuando el usuario presiona Enter), la interfaz del terminal gestiona todas las pulsaciones de teclas, incluido el Backspace, y la aplicación no puede leer ningún carácter. El comportamiento contrario es el modo no canónico, donde la aplicación tiene un control mucho mayor sobre el procesamiento de los caracteres de entrada.
Entre otras cosas, el controlador de la terminal de Linux ayuda al traducir caracteres de interrupción a señales (por ejemplo, deteniendo el programa cuando presiona Ctrl-C) y procesa de forma automática las teclas Backspace y Delete, para no tener que volver a implementar su comportamiento en cada programa que se escribe.
Estructura termios
La configuración de la terminal se realiza mediante la estructura termios (archivo de cabecera termios.h):
1 struct termios
2 {
3 tcflag_t c_iflag; /* input mode flags */
4 tcflag_t c_oflag; /* output mode flags */
5 tcflag_t c_cflag; /* control mode flags */
6 tcflag_t c_lflag; /* local mode flags */
7 cc_t c_line; /* line discipline */
8 cc_t c_cc[NCCS]; /* control characters */
9 speed_t c_ispeed; /* input speed */
10 speed_t c_ospeed; /* output speed */
11 };
Para anular el modo canónico y el eco, se debe modificar campo c_lflag. Para ello se útilizaran las siguientes banderas
ECHO repite los carácter en la terminal (eco).
ICANON entrada canónica o modo linea, los caracteres no son enviados a la aplicación hasta que se presiona enter
para mas información [Local Modes](https://www.gnu.org/software/libc/manual/html_node/Local-Modes.html#Local-Modes)
Funciones
tcgetattr: para obtener los parámetros actuales de la terminal. Prototipo de función: int tcgetattr(int fd, struct termios *termios_p);
tcsetattr: para configurar los parámetros a una terminal. Prototipo de función: int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
(para más ayuda > man 3 tcsetattr).
Ejemplo: imprimir el carácter y su código
1 #include <stdio.h>
2 #include <termios.h>
3
4 #define FD_STDIN 0
5
6 int main()
7 {
8 char tec;
9 struct termios t_old, t_new;
10 tcgetattr(FD_STDIN, &t_old); // lee atributos del teclado
11 t_new = t_old;
12 t_new.c_lflag &= ~(ECHO | ICANON); // anula entrada canónica y eco
13 tcsetattr(FD_STDIN,TCSANOW,&t_new); // actualiza con los valores nuevos de la config. TCSANOW = activar la modificación inmediatamente
14 tec = 0;
15 while (tec!=10){ // Ingresar hasta oprimir enter
16 tec=getchar();
17 printf("%c - %d\n",tec,tec);
18 }
19 tcsetattr(FD_STDIN, TCSANOW, &t_old); // actualiza con los valores previos
20 }