.pt zine - Função getpass

Função getpass (Escondendo passwords):
(digitação de caracteres sem eco para o stdout)
-----------------------------------------------------------------
by Elektro

Quantas vezes ja li ou ouvi, algures pessoal, a perguntar "como é que se faz", para que as teclas digitadas, não aparecam no ecra?? Montes de vezes.

Obviamente que este artigo esta mais orientado, para SysAdm, que produzem as próprias aplicacoes, para o seu sistema.

É mais bonitinho ainda, que tal criar uma função, que cada vez que uma tecla é premida, aparece no ecra um asterisco (*), tipo Windows!!

As libraries do C, contem uma função chamada getpass, cuja função é essa mesmo, porem, não está definida nenhuma função, em que cada tecla premida um asteriso é imprimido para o stdout. Esta situação, acontece tanto em sistemas Linux como outros (Turbo C, Borland...).

POREM EM LINUX uma função destas não será "doce" de criar e vai muito alem, do nivel de programação que aqui se pretende. Porem em sistemas MS-DOS, é possivel, com relativa facilidade, criar uma função deste tipo.

O facto de aparecer ou não no ecra quando uma tecla, e pressionada, esta relacionado com o facto de se tratar ou nao de um buffered output! Por exemplo (toda a gente deve saber o que e um buffer, quem não sabe, pode-se dizer que se trata de uma especie de memória intermediária, onde dados são guardados, até serem colocados no seu destino):

  Num unbuffered output os dados são directamente enviados para o destino, (em linguagem de design de sistema, pode-se considerar um ficheiro), um ficheiro.

  Num buffered output, os dados são guardados num buffer, e apenas quando este está "cheio", ou se efectua um "flush", é que os dados são mandados para o ficheiro.

  As vantagens de usar um buffered ou unbuffered output, vão alem do que é necessário para este artigo.

  Existem pré-definidos nos sistemas três unbuffered ficheiros (apontadores):

  - Stdin (standart input)
  - Stdout (standart output)
  - Stderr (standart error)

  Já estão a começar a perceber, porque é que quando carregamos numa tecla, o caracter correspondente é imediatamente imprimido no stdout!!!!

  Como então já perceberam, para não aparecer imediatamente, uma tecla no ecra basta "atribuir" um buffer aos apontadores de ficheiros que nos interessam (em linux fazer "man setbuf").

  No entanto, tanto em sistemas Linux como MS-DOS, não é necessário ir tão longe, visto ser possivel, obter resultados satisfatorios, utilizando algumas funções já definidas.:-))

  EM SISTEMAS MS-DOS

  Em sistemas MS-DOS, podemos usar a função getch(), que "bufferiza" o stdout Porém ao construir uma função deste tipo é preciso ter certo tipo de atenções:

           #include <conio.h>
           #include <stdio.h>
           #include <string.h>

           char *my_getpass(const char *prompt, int tamanho){

           static char password[15];
           char *apontador=password;
           int caracter;

           printf("%s", prompt);
           for(;;){
                   caracter=getch();

                   if( caracter == '\r' )  /* ENTER sai do ciclo (fim passwd) */
                      break;

                   if( caracter == '\b' ){ /* Caso uma pessoa se engane a escrever
                     apontador--;             esta funcao lida com o backspace */
                     putch('\b');
                     putch(' ');
                     putch('\b');
                     continue;
                     }

                   *apontador++= (char) caracter;

                   putch('*');

                   if( apontador == password+tamanho ) /* Caso a password exceda o
                      break;                              tamanho definido, sai do
                   }                                      ciclo */
           *apontador='\0';
           return password;
           }

  É preciso ter em consideracao, aspectos como o tamanho da password, lidar com o backspace etc...

  EM SISTEMAS LINUX

  Em sistemas Linux, assim a primeira mão, não é possivel criar uma função tao "bonitinha", porem usando chamadas ao sistema operativo e possivel fazer com que os caracteres "teclados", não apareçam no ecra:

         #include <stdio.h>
         #include <string.h>

         char *my_getpass_linux(const char *prompt, int tamanho){

         static char password[15];
         static char temporario[15];

         system ("stty -echo > /dev/console");
         scanf("%s", &temporario);
         system ("stty echo > /dev/console");
         strncpy(password, temporario, tamanho);

         return password;
         }

  Apesar de não ter sido descrito aqui como criar uma função em cada "teclar" e substituido por asterisco, criou-se aqui uma que tambem cumpre a sua função.