/*----------------------------------------------------------------
termio
Tramite la system call ioctl e' possibile modificare le caratte-
ristiche di un terminale. Ad esempio e' possibile sopprimere
l'echo dei caratteri digitati sulla tastiera. E' possibile pure
effettuare l'input puntuale. Se ad esempio e' necessario immet-
tere 1 solo carattere, e' possibile far si' che non sia neces-
sario battere il tasto di invio. La chiamata:
ioctl (0, TCGETS, &termbuf)
salva in struct termio termbuf le caratteristiche del terminale
mentre la chiamata:
ioctl (0, TCSETS, &termbuf)
posiziona le caratteristiche come stabilito in termbuf. Per il
ripristino la chiamata con le caratteristiche originali e':
ioctl (0, TCSETSF, &termbuf)
ove la F finale del 2^ parametro signica Force.
Normalmente sono attivate certe caratteristiche quali:
* l'echo dei tasti battuti sulla tastiera
* l'uso del tasto Invio (o Enter) per rendere disponibile quanto
battuto sulla tastiera.
Per cambiare le impostazione e' necessario passare nella cosid-
detta modalita' NON canonica e togliere l'echo dei tasti. Sempre
im modalita' non canonica e' necessario specificare 2 quantita'
(tempo e caratteri). Trascorsa una delle quali l'input e' reso
disponibile al programma senza che sia necessario battere Invio.
Per passare in modalita' non canonica e togliere l'echo e' neces-
sario azzerare i bit che le attivano. Si agisce sul membro
c_lflag della struttura che contiene le caratteristiche dell'in-
put:
xxxx.c_flags &= ~ (ICANON | ECHO)
Con ICANON | ECHO si specificano su quali bit agire. La tilde
opera il complemento, quindi tutti i bit, eccetto quelli specifi-
cati, verranno posti ad 1. Infine si esegue un AND con la
maschera dei flag. Il risultato e' che quelli della modalita'
canonica e dell'echo sono stati azzerati.
Si passa a modificare 2 voci del vettore c_cc, quelle individuate
da VTIME e VMIN. Vanno poste ad un valore > 0. Con:
xxxx.c_cc [VMIN] =
xxxx.c_cc [VTIME] =
si specificano rispettivamente il numero minimo di caratteri ed
il timeout in decimi di secondo. Battuti un numero di caratteri
pari ad almeno c_cc [VMIN] oppure se e' trascorso un tempo pari
ad almeno c_cc [VTIME] decimi di secondo, la lettura termina e
l'input passa al programma.
Messaggistica
errore ioctl
la system call ha restituito un errore
errore ripristino
ripristino delle caratteristiche fallito
errore settaggio terminale
modifica delle caratteristiche fallita
----------------------------------------------------------------*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
/*-----configurazione-----*/
const int dimpw = 16;
/*---fineconfigurazione---*/
int main (void)
{
struct termios orig, save (void), tmp;
void modify (struct termios), restore (struct termios);
void typepwd (int);
orig = save ();
tmp = orig;
modify (tmp);
typepwd (dimpw);
restore (orig);
exit (EXIT_SUCCESS);
}
struct termios save (void)
{
struct termios termbuf;
if ((ioctl (0, TCGETS, &termbuf)) == -1)
{
fprintf (stderr, "errore ioctl\n");
exit (EXIT_FAILURE);
}
return termbuf;
}
void restore (struct termios termbuf)
{
if ((ioctl (0, TCSETSF, &termbuf)) == -1)
{
fprintf (stderr, "errore ripristino\n");
exit (EXIT_FAILURE);
}
}
void modify (struct termios termbuf)
{
termbuf.c_lflag &= ~ (ICANON | ECHO);
termbuf.c_cc [VMIN] = 1;
termbuf.c_cc [VTIME] = 1;
if ((ioctl (0, TCSETS, &termbuf)) == -1)
{
fprintf (stderr, "errore settaggio terminale\n");
exit (EXIT_FAILURE);
}
}
void typepwd (const int dimpw)
{
char *pw;
int i = 0, unchar;
pw = (char *) calloc (dimpw, 1);
printf ("immettere la password (backspace = CTRL/H) > ");
do
{
fflush ((FILE *) NULL);
unchar = fgetc (stdin);
switch (unchar)
{
case '\n':
case '\0':
break;
case '\b':
if (i > 0 && i < dimpw)
{
printf ("\b \b");
pw [--i] = '\0';
}
break;
default:
if (! isprint (unchar))
break;
if (i >= 0 && i < dimpw)
{
pw [i++] = unchar;
printf ("*");
}
break;
}
}
while (unchar != '\n');
printf ("\npassword immessa: %s\n", pw);
free ((void *) pw);
}