Ответ 1
Если ваша система предоставляет его, getpass является опцией:
#include <unistd.h>
/* ... */
char *password = getpass("Password: ");
Это не отображает ничего, поскольку набираются символы.
Я хочу, чтобы пользователи вводили пароль с помощью интерфейса командной строки. но я не хочу отображать этот пароль на экране (или отображать "****" ).
Как это сделать в C? Спасибо.
Update:
Я работаю только с Linux. Поэтому я действительно не забочусь о Win или других системах. Я попробовал решение Lucas, и все получилось отлично. Однако у меня есть еще один вопрос:
Если это однопроцессное приложение и приложение с одним потоком, изменение настройки termios влияет на разные терминалы?
Как насчет 1 процесса - несколько потоков, много процессов - несколько потоков?
Большое спасибо.
Если ваша система предоставляет его, getpass является опцией:
#include <unistd.h>
/* ... */
char *password = getpass("Password: ");
Это не отображает ничего, поскольку набираются символы.
Если вы используете среду UNIX, что-то вроде этого может отключить ECHO командной строки.
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#define SIZE 100
void getPassword(char password[])
{
static struct termios oldt, newt;
int i = 0;
int c;
/*saving the old settings of STDIN_FILENO and copy settings for resetting*/
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
/*setting the approriate bit in the termios struct*/
newt.c_lflag &= ~(ECHO);
/*setting the new bits*/
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
/*reading the password from the console*/
while ((c = getchar())!= '\n' && c != EOF && i < SIZE){
password[i++] = c;
}
password[i] = '\0';
/*resetting our old STDIN_FILENO*/
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}
int main(void)
{
char password[SIZE];
printf("please enter password\n");
getPassword(password);
printf("Do something with the password <<%s>>\n", password);
return 0;
}
Для C/commandline/linux см.:
man getch
man noecho
см. в coment в getch
около noecho
. Я никогда не пробовал это сам.
В bash, если вы используете read -s
, он не будет эхом на экране:
> read -s x
<type something><enter>
> echo $x
<whatever you typed>
Чтобы сделать это переносимым способом, вам понадобится стандартная или де-факто стандартная библиотека.
См. man 3 termios
и man 3 ncurses
.
Вот программа, которая будет работать на Linux и других Unix-системах...
#include <stdio.h>
int main(void) {
int f = open("/dev/tty", 0);
char s[100];
system("stty -echo > /dev/tty");
f >= 0 && read(f, s, sizeof s) > 0 && printf("password was %s", s);
system("stty echo > /dev/tty");
return 0;
}
Возможно несколько улучшений. Использование termios, вероятно, было бы лучше, и это позволило бы избежать вилки и возможных проблем безопасности системы(). Использование стандартного ввода-вывода для чтения пароля, вероятно, будет лучше. (Как написано, введенная новая строка должна быть удалена.) В Linux есть функция getpass(), а некоторые другие, но она помечена как "устаревшая. Не используйте ее". Было бы неплохо иметь дело с SIGTSTP.
В целом, я могу найти существующее решение, которое касается всех этих небольших проблем...
Функция getpass теперь устарела. Используйте termios.
#include <termios.h>
#include <stdio.h>
void get_password(char *password)
{
static struct termios old_terminal;
static struct termios new_terminal;
//get settings of the actual terminal
tcgetattr(STDIN_FILENO, &old_terminal);
// do not echo the characters
new_terminal = old_terminal;
new_terminal.c_lflag &= ~(ECHO);
// set this as the new terminal options
tcsetattr(STDIN_FILENO, TCSANOW, &new_terminal);
// get the password
// the user can add chars and delete if he puts it wrong
// the input process is done when he hits the enter
// the \n is stored, we replace it with \0
if (fgets(password, BUFSIZ, stdin) == NULL)
password[0] = '\0';
else
password[strlen(password)-1] = '\0';
// go back to the old settings
tcsetattr(STDIN_FILENO, TCSANOW, &old_terminal);
}
int main(void)
{
char password[BUFSIZ];
puts("Insert password:");
get_password(password);
puts(password);
}
Если у вас есть доступ к библиотеке curses, вы можете использовать noecho. Если вы используете компилятор Microsoft C, вы можете использовать _ getch. Но афайк, оба они связывают вас с консолью. Если вам нужно читать stdin, независимо от того, поступает ли он от консоли или файла или команды с каналами, вам нужно сообщить операционной системе, как она должна обрабатывать консоль.
#include<conio.h>
#include<iostream>
using namespace std;
int main(){
char *pass = new char[20];
cout<<"Password :";
int i=0;
while( ( pass[i]=getch() ) != '\n' && pass[i] != '\r' && i<19 )
{putchar('*'); i++;}
pass[i]='\0';
cout<<endl;
if(strcmp("123456789",pass)==0 ) // do stuff
return 0;}