我想允许用户使用命令行界面输入密码。但我不想在屏幕上显示此密码(或显示“****”)。
如何在C中执行此操作? 感谢。
更新
我只在Linux上工作。所以我实际上并不关心Win或其他系统。我试过卢卡斯的解决方案,它工作得很好。但是,我还有另一个问题:
如果这是一个单一的过程&单线程应用程序,更改termios的设置会影响不同的终端吗?
1个进程怎么样 - 多线程,多进程 - 多线程?
非常感谢。
答案 0 :(得分:16)
如果您的系统提供,getpass是一个选项:
#include <unistd.h>
/* ... */
char *password = getpass("Password: ");
在键入字符时不会显示任何内容。
答案 1 :(得分:9)
如果您使用的是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;
}
答案 2 :(得分:4)
函数getpass现在是obsolete。使用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);
}
答案 3 :(得分:2)
对于C /命令行/ linux,请参阅:
man getch
man noecho
请参阅getch
中有关noecho
的评论。我自己从未尝试过这个。
如果使用read -s
,则在bash中,它不会在屏幕上回显:
> read -s x
<type something><enter>
> echo $x
<whatever you typed>
答案 4 :(得分:1)
要以便携方式执行此操作,您需要使用标准化或事实上的标准库。
请参阅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可能会更好,它可以避免fork()和system()可能出现的安全问题。使用标准I / O来读取密码可能会更好。 (正如所写的那样,必须删除键入的换行符。)Linux中有一个getpass()函数,但是它被标记为“过时了。不要使用它。”。处理SIGTSTP可能是个好主意。
总的来说,我可能会寻找一个处理所有这些小问题的现有解决方案......
答案 5 :(得分:1)
如果您有权访问curses库,则可以使用noecho。如果您使用的是Microsoft的C编译器,则可以使用_getch。但是afaik,这两个都把你绑在控制台上。如果你需要读取stdin而不管它是来自控制台还是文件或管道命令,你需要告诉操作系统它应该如何handle the console。
答案 6 :(得分:0)
#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;}