Los caracteres de control especial, son una colección de caracteres, como CTRL-C, que actúan de un modo en particular cuando el usuario lo escribe. El miembro c_cc
de la estructura termios
contiene los caracteres relacionados con cada una de las funciones aceptadas. La posición de cada carácter (su índice de cada matriz) lo define una macro, pero no hay limitación que diga que deban ser caracteres de control.
La matriz c_cc
se usa de dos maneras muy diferentes, dependiendo de si la terminal está configurada con modo canónico (es decir, la configuración del indicador ICANON
en el miembro c_iflag
de termios
).
Hay que tener en cuenta cierta coincidencia en el modo de empleo de los valores de índice de las matrices para los modos diferentes. Por ello, no debería mezclarse nunca los valores de estos dos modos.
Caracteres
Como los caracteres especiales y los valores no canónicos son tan importantes para el procesamiento de caracteres de entrada más avanzado, en la siguiente tabla se explica con más detalle:
Los valores TIME y MIN
Los valores TIME
y MIN
se usan, con los modos no canónicos y actúan conjuntamente para controlar la lectura de las entradas.Juntos, controlan lo que ocurre cuando un programa intenta leer un descriptor de archivo asociado a una terminal.
Existen cuatro:
MIN = 0
yTIME = 0
.- En este caso, unread
se enviará de inmediato. Si están disponibles algunos caracteres, serán retornados, si no está disponible ninguno,read
enviará cero y no se habrá leído ningún carácter.MIN = 0
yTIME > 0
.- En este caso,read
aparecerá cuando esté disponible para la lectura cualquier carácter o cuando haya pasado una décima de segundo deTIME
. Si no leyó ningún carácter porque se pasó el tiempo,read
enviará cero. Sino, enviará el número de caracteres leídos.MIN > 0
yTIME = 0
.- En este caso.read
esperará hasta que se puedan leer caracteresMIN
y después enviará el número de caracteres leídos. Al final del archivo se envía cero.MIN > 0
yTIME > 0
.- Éste es el caso más complejo. Cuando se llama aread
, éste espera a que se reciba un carácter. Cuando se recibe el primer carácter, y siempre que se reciba un carácter, se inicia un contador de caracteres interno (o se vuelve a iniciar si ya estaba funcionando).read
se enviará cuando se puedan leer caracteresMIN
o cuando se pase el tiempo de caracteres internos de una décima de segundo deTIME
. Puede resultar útil para indicar la diferencia entre presionar una sola vez la tecla Escape e iniciar una secuencia de función de teclas de escape. Tenga presente, sin embargo, que la comunicación en red o las cargas de procesadores superiores eliminan con ingenio dicha información de sincronización.
Acceso a los modos de terminal desde la shell
Si desea ver la configuración de termios empleada mientras esté usando la shell, puede obtener una lista usando el comando:
En mi sistema Linux, la salida es:
Vemos que el carácter EOF
es CTRL-D y permiten los ecos. Si estamos experimentando con el control del terminal, es muy fácil dejar a la terminal en un estado no estándar, lo cual dificultara mucho su uso. Tenemos varios modos de solucionarlo:
- El primer método, si su versión de
stty
lo acepta, es usar el comandostty sane
. - Si ha perdido el mapa de las teclas de retorno de carro para el carácter nueva línea (que finaliza la línea), es posible que tenga que introducir
stty sane
, pero en vez de presionar Intro, tendrá que presionar CTRL-J (que es el carácter de nueva línea). - El segundo método es usar el comando
stty -g
para escribir la configuraciónstty
actual en un formulario listo para volver a leerlo. En la línea de comandos podemos usar: - Podemos usar la misma técnica en un script shell:
- Otro método, si nos quedamos atascados, es ir a un terminal diferente, usar el comando
ps
para encontrar la shell que había inutilizado, y después usarkill HUP <id proceso>
para que la shell finalice. Como los parámetros stty se reinician siempre antes de proporcionar un incitador de registro, debería ser capaz de registrarse con toda normalidad.
Configuración de los modos de terminal desde el incitador de comandos
Podemos configurar los modos de terminal directamente desde el incitador de comandos. Para establecer un modo en el cual su script shell pudiese ejecutar lecturas de caracteres únicos, tendría que desactivar el modo canónico y configurarlo en 1 y en 0. El comando sería:
Con el terminal configurado para leer los caracteres inmediatamente, podemos intentar ejecutar el primer programa que creamos, menu1
, de nuevo. Debería funcionar tal como se pensó desde el primer momento.
También podría mejorar su intento de comprobación de contraseña (Capítulo 2) desactivando los ecos antes de solicitar la contraseña.
El comando que lo hace es:
VELOCIDAD DE TERMINAL
La última función que proporciona la estructura termios
es la manipulación de la velocidad de línea. Para la velocidad de la terminal no se define ningún miembro, sino que se configura mediante llamadas a funciones. Las velocidades de entrada y de salida se gestionan por separado.
Los cuatro prototipos son:
Tenga en cuenta que todos actúan en una estructura termios
, no directamente en el puerto. Esto significa que para configurar una nueva velocidad, debe leer las configuraciones actuales con tcgetattr
, configurar la velocidad usando una de las llamadas anteriores y después volver a escribir la estructura termios
usando tcsetattr
. Únicamente después de la llamada a tcsetattr
se modificará la velocidad de la nueva línea.
FUNCIONES ADICIONALES
Existe un pequeño número de funciones adicionales para el control de terminales. Trabajan directamente con los descriptores de archivos sin tener que obtener y configurar las estructuras termios
. Estas definiciones son:
Las funciones tienen las siguientes finalidades:
tcdrain
..- Hace que el programa de llamada espere hasta que se envíe una salida que estuviese haciéndola sola.tcflow
.- Se usa para suspender o reinicia una salida.tcflush
.- Se puede usar para vaciar las salidas, las entradas o ambas.
Ahora que ya hemos profundizado en el tema de la estructura termios
, vamos a ver varios ejemplos prácticos. Es posible que lo más sencillo sea deshabilitar el eco para leer una contraseña. Hágalo desactivando el indicador ECHO
.
UN PROGRAMA DE CONTRASEÑA CON TERMIOS
- Comience su programa de contraseña,
password.c
, con las siguientes definiciones: - A continuación, añada una línea para obtener las opciones actuales de la entrada estándar, y cópielos en la estructura
termios
que creó previamente: - Haga una copia de las opciones originales para reemplazar al final. Desactive el indicador
ECHO
ennewrsettings
y pregunte al usuario su contraseña. - A continuación, establezca los atributos de la terminal en
newrsettings
y lea la contraseña. Por último, reinicie los atributos originales de la terminal y muestre la contraseña para que todos los esfuerzos de seguridad previos sean inútiles.
Cuando ejecute el programa, debería ver:
COMO FUNCIONA
En este ejemplo , escribimos la contraseña 1234567
, pero no se envía hasta el incitador Entra la contraseña:
. Hasta que el usuario no presiona Intro no se produce ningún dato de salida.
Tenga cuidado y modifique únicamente los indicadores que tenga que modificar, use la estructura X &= ~FlAG
(que vacía el bit definido por FLAG
en la variable X
). Si fuese necesario, podría usar X | = FlAG
para configurar un único bit definido por FLAG
, a pesar de que no fue necesario para el ejemplo anterior.
Al configurar los atributos usa TCSAFLUSH
para desechar cualquier carácter o escritura que el usuario haya introducido antes de que el programa esté listo para leerlos. Es un buen modo que los usuarios no empiecen a escribir sus contraseñas hasta que se hayan desactivado los ecos
. También restablecerá la configuración previa, antes de que finalice su programa.
Otro uso común de la estructura termios
es introducir a la terminal en un estado en el que pueda leer cada carácter en cuanto se escriba. Para hacerlo, desactive el modo canónico
y use las opciones MIN
y TIME
.
LEER CADA CARÁCTER
Gracias a los nuevos conocimientos adquiridos, puede realizar cambios en el programa menu
. el siguiente programa (que llamaremos menu4.c
, se basa en menu3.c
y contiene gran parte del código de password.c
. Los cambios se explican en los siguientes pasos:
- Para empezar, debe incluir un nuevo archivo de cabecera en la parte superior del programa:
- Después tiene que declarar un par de variables nuevas en la función principal:
- Tiene que modificar las características de la terminal antes de llamar a la función
getchoice
. Tiene que colocar las siguientes líneas aquí: - También debería retornar las opciones a sus valores originales antes de salir:
- Ahora que está en el modo no
canónico
tiene que comprobar los retornos de carro, porque el trazado predeterminado de CR a LF ya no se va a ejecutar.
A menos que lo disponga de otra manera, si el usuario escribe ahora CTRL-C en su programa, el programa se finalizará. Puede deshabilitar el procedimiento de estos caracteres especiales vaciando el indicador ISIG
en los modos locales. Para hacerlo, se incluye la siguiente línea en main
, tal como muestra el paso anterior.
new_settings.c_lflag &= ~ISIG;
Si introduce estos cambios en su programa de menú, obtendrá una respuesta inmediata y los caracteres escritos no se transmitirán mediante echo.
Si escribe CTRL-C, se transmite directamente al programa y será tratado como una elección.
Debe estar conectado para enviar un comentario.