Search code examples
clinuxdrivertermios

How to change the echo character in a linux terminal


I am interested in gathering a password from a user.

When the user is prompted for their password, I want to echo back to them * (asterisks) for each character they input.

void changeEcho() {
    termios term;
    tcgetattr(STDIN_FILENO, &term);
    term.c_lflag &= ~ECHO;
    tcsetattr(STDIN_FILENO, TCSANOW, &term);
}

I know that this will turn the echo off, but I am interested in echoing something that I choose, in my case '*'.


Solution

  • The feature you describe is unrelated to echo. Instead, you implement it yourself by simply reading a character and writing a * in a loop:

    #include <termios.h>
    #include <unistd.h>
    #include <stdio.h>
    
    
    int main() {
        char c;
        char p = '*';
        struct termios term, original;
        tcgetattr(STDIN_FILENO, &term);
        original = term;
        term.c_lflag &= ~ECHO & ~ICANON;
        tcsetattr(STDIN_FILENO, TCSANOW, &term);
    
        while (read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
            write(STDOUT_FILENO, &p, 1);
        printf("\n");
    
        tcsetattr(STDIN_FILENO, TCSANOW, &original);
        return 0;
    }
    

    When you run it and type things, all you see are *s:

    $ gcc foo.c && ./foo
    ***********
    

    It's up to the program to store the string, handle backspace, and only show a single * per multibyte character.