21 febrero 2009

Desactivar eco en Linux

Hola,
habran notado que las funciones de entrada y salida estandar por la consola son todas con eco, es decir, que lo que el usuario escribe en la consola es visualizado, por lo que por ejemplo si le pedimos una contraseña al usuario es algo inseguro usar fgets porque otras personas pueden ver la contraseña.

la primera opcion es obsoleta
sacado de "man"


SYNOPSIS
#include unistd.h (los signos de mayor y menor faltan aca..)

char *getpass( const char * prompt );

DESCRIPTION
This function is obsolete. Do not use it.

getpass lo que hace es imprimir "prompt", desactivar el eco, obtener una cadena y retornar esa cadena, por ejemplo

char contra[30];
strncpy(contra, getpass("Ingrese la conrtaseña"), 30);

aunque se llame getPASS no significa que necesariamente tiene que ser una contraseña...

pero hay otra forma de obtener una cadena sin el eco.
este metodo es cambiando las opciones de tty (la consola actual) obteniendo la cadena y volver las opciones de tty a como estaban
para eso tenemos 2 funciones
vamos a necesitar a
termios.h
unistd.h
para poder usarlas:

int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

el primero obtiene las opciones (o atributos) de tty y la segunda especifica las opciones
en fd ponemos 0 (que seria la entrada estandar), la estructura termios contiene flags

tcflag_t c_iflag; /* input modes */
tcflag_t c_oflag; /* output modes */
tcflag_t c_cflag; /* control modes */
tcflag_t c_lflag; /* local modes */
cc_t c_cc[NCCS]; /* control chars */

nosotros tenemos que modificar c_lflag, sacandole el bit ECHO
y para tcsetattr el segundo argumento usamos TCSANOW para que se haga en el momento los efectos

la idea es obtener las opciones de tty y guardarlas en una estructura, cambiar c_lflag sacandole ECHO, poner las opciones con el flag modificado, obtener la cadena, volver a colocar ECHO en el flag y poner las opciones nuevamente:

#include stdio.h /*como sabran, aca tienen que colocar los signos de mayor y menor...*/
#include termios.h
#include unistd.h

int main(void)
{
struct termios tty;
char s[200];
tcgetattr(0, &tty);/*obtenemos*/
tty.c_lflag &= ~ECHO;/*sacamos eco*/
tcsetattr(0, TCSANOW, &tty);/*ponemos*/
fgets(s, 200, stdin);/*obtenemos la cadena*/
tty.c_lflag |= ECHO;/*ponemos eco*/
tcsetattr(0, TCSANOW, &tty);/*ponemos*/
return 0;
}
fijense que con tcgetattr ponemos 0 y en fgets usamos stdin, eso es porque tcgetattr espera el identificador del archivo y fgets espera una estructura FILE *

bueno, con eso podemos obtener algo del teclado sin eco

salu2!