Une chaine de caractères peut être lue sur l’entrée standard
du terminal par l’appel système Linux READ mais il est aussi intéressant
d’avoir une fonction permettant l’attente et la saisie d’une seule touche. Hélas,
il n’y a pas d’appel système qui effectue cette tâche et j’avais déjà cherché
une solution il y a plus d’un an pour résoudre ce problème. J’avais été rebuté
car des exemples en C montrait qu’il fallait utiliser la fonction tcgetattr et
je n’avais pas trouver la correspondance avec un appel système.
Mais récemment j’ai trouvé un post sur stackoverflow qui
donnait une solution en C et qui expliquait que la fonction tcgetattr pouvait
être remplacée par l’appel système IOCTL que nous avons déjà utilisé.
J’ai donc traduit le programme C donné en exemple en
assembleur ARM et cela fonctionne bien.
Dans ce programme, nous commençons à décrire les constantes
nécessaires puis les structures TERMIOS, SIGATION et POLL qui permettent de
gérer l’état du terminal, le traitement des signaux et la lecture du terminal
puis dans la partie code, nous récupérons l’état initial du terminal avec
l’appel système IOCTL et le code action TCGETS qui donc effectue la même action
que tcgetaatr.
Ensuite à l’aide de l’appel système SIGACTION, nous
déroutons les signaux SIGINT,SIGQUIT et SIGTERM vers une routine qui
positionnera la variable iEnd à 1 pour terminer la boucle de lecture. Si nous
n’avions pas fait cela, l’appui sur les touches ctrl-c terminerait le programme
alors qu’il faut sortir de la boucle pour effectuer éventuellemnt des tâches.
Toujours à l’aide de SIGACTION, nous positionnons la non
prise en compte du signal SIGTOUT qui concerne si j’ai bien compris les signaux
provenant de process tournant à l’arrière-plan.
Puis nous récupérons à nouveau l’état du terminal et nous
modifions les flags de la structure TERMIOS pour ne plus afficher la touche à
l’écran (flag ECHO) et n’autoriser la saisie que d’une seule touche (flag
ICANON).
Enfin, nous entrons dans une boucle qui va tester la
variable iEnd pour se terminer puis préparer ‘appel système SYS_POOL qui va
prendre en compte l’évènement appui sur une touche de la console standard
d’entrée (STDIN). Si le code retour est supérieur à zéro, une touche a été
appuyée et nous utilisons l’appel système READ pour lire le contenu dans un
buffer. Ce buffer doit être d’une taille supérieure à un octet car certaines
touches peuvent être codées sur 4 octets (flèches de direction par exemple).
Nous affichons le contenu du buffer pour vérifier les frappes et nous testons
aussi les codes q et Q pour terminer la boucle.
Enfin le programme se termine en restaurant le terminal à
son état du début.
Il ne reste plus qu’à améliorer ce programme pour le
transformer en fonction et ajouter dans la boucle lle ou les traitements
appropriés.