Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ANSI C No-echo keyboard input

Tags:

c

I've been Googling around with no luck. I'm looking for a way to do getc() or gets() or whatever that does not echo to the terminal. I saw kbhit() but this doesn't appear to be part of ANSI. Ideally, I'd like code that looks like

char s[100];
no_echo_gets(s); /* Won't echo to screen while being typed */
printf("%s\n", s);

Does anybody know a good ANSI compliant way to do this?

like image 710
Scott Avatar asked Nov 30 '22 20:11

Scott


2 Answers

For UNIX-like systems you want to play with the ECHO flag...

#include <termios.h>
...
struct termios t;
tcgetattr(fd, &t);
t.c_lflag &= ~ECHO;
tcsetattr(fd, TCSANOW, &t);
...
like image 85
dwc Avatar answered Dec 09 '22 10:12

dwc


The getpass command is present in Linux. But you can make a prettier version, the system echo alone doesn't kill the need for an enter command, while knocking down buffering doesn't kill the production of a carraige return after data entry. Combining the two gives a good approximation of a quiet entry. You can add an asterisk to give a secret entry appearance so here is a combination of two suggestions:

    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    int getche(void);
    int main(int argc, char **argv){
    int i=0;       
    char d,c='h',s[6];
    printf("Enter five secret letters\n");
    s[5]='\0'; //Set string terminator for string five letters long
    do{
      d=getche();//Fake getche command silently digests each character
    printf("*");
      s[i++]=d;} while (i<5);
    printf("\nThank you!!\n Now enter one more letter.\n");
    c=getchar();
    printf("You just typed %c,\nbut the last letter of your secret string was %c\n",c,d);   
    printf("Your secret string was: %s\n",s);   
        return 0;
    }
    /* reads from keypress, echoes */
        int getche(void)
        {
            struct termios oldattr, newattr;
            int ch;
            tcgetattr( STDIN_FILENO, &oldattr );
            newattr = oldattr;
            newattr.c_lflag &= ~( ICANON | ECHO);\\knock down keybuffer
            tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
            system("stty -echo");\\shell out to kill echo
            ch = getchar();
            system("stty echo");
            tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
            return ch;
        }
like image 35
Edward A Kimble Avatar answered Dec 09 '22 11:12

Edward A Kimble