Have you every wondered, In some terminal programs when they ask for password and you enter it, so either it does not display anything or displays '**********' while typing.
So how these programs take passwords?
The default input mode of terminal is echo, So as soon as we start typing any character in the terminal it show there simultaneously. But we can change this default behavior to do our job of taking the password from terminal without being it visible.
Here is a simple program that demonstrate how we can do this. termios.h
is the header file where all the struct and function related to terminal are defined.
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
int getch() {
int ch;
// struct to hold the terminal settings
struct termios old_settings, new_settings;
// take default setting in old_settings
tcgetattr(STDIN_FILENO, &old_settings);
// make of copy of it (Read my previous blog to know
// more about how to copy struct)
new_settings = old_settings;
// change the settings for by disabling ECHO mode
// read man page of termios.h for more settings info
new_settings.c_lflag &= ~(ICANON | ECHO);
// apply these new settings
tcsetattr(STDIN_FILENO, TCSANOW, &new_settings);
// now take the input in this mode
ch = getchar();
// reset back to default settings
tcsetattr(STDIN_FILENO, TCSANOW, &old_settings);
return ch;
}
int main(void) {
char password[100];
int i = 0;
int ch;
printf("Enter password: ");
while ((ch = getch()) != '\n') {
if (ch == 127 || ch == 8) { // handle backspace
if (i != 0) {
i--;
printf("\b \b");
}
} else {
password[i++] = ch;
// echo the '*' to get feel of taking password
printf("*");
}
}
password[i] = '\0';
printf("\nYou entered password: %s\n", password);
return 0;
}
Output:
Enter password: *****
You entered password: naman
Instead of writing this whole program we can either use inbuild function getoass
define in unistd.h
header to take password without echoing but we don't get much control here like echoing '*' while writing.
#include <stdio.h>
#include <unistd.h>
int main(void) {
char *password;
password = getpass("Enter password: ");
printf("You entered password: %s\n", password);
return 0;
}
Output:
Enter password:
You entered password: naman
NOTE: The man page of
getpass
says function opens /dev/tty (the controlling terminal of the process), outputs the string prompt, turns off echoing, reads one line (the "password"), restores the terminal state and closes /dev/tty again. which means that password will not be stored in the shell history.NOTE: Custom implementation of this program also does not store the password in the shell history even though it is taking input from
stdin
. The reason is that thegetch
function reads a character directly from the terminal without waiting for the user to press the enter key, so the password is not passed to the shell as a command.
Thank you ❤️ so much for reading this article. I'm also a student learning new things so If you find any mistakes or have any suggestions please let me know in the comments.
Also, consider sharing and giving a thumbs up If this post helps you in any way.
Top comments (3)
You shouldn't name the function
getch()
since there's already a curses library function with the same name.It's ok in linux. linux does not have 'getch()' function.
The point is to be cross-platform. Not everybody uses Linux.