2009-11-23 89 views
12

我想让用户使用命令行界面输入密码。但我不想在屏幕上显示此密码(或显示“****”)。C命令行密码输入

如何在C? 谢谢。

更新:

我只工作在Linux上。所以我实际上并不关心Win或其他系统。我试过卢卡斯的解决方案,它运行良好。不过,我还有另一个问题:

  1. 如果这是一个过程&单线程应用,改变的termios的设置会影响不同的终端?

  2. 1进程怎么样 - 多线程,多进程 - 多线程?

非常感谢。

+7

http://www.linux.com/learn/docs/man/3177-getpass3 – sambowry 2009-11-23 22:37:09

+0

你在哪个控制台和操作系统上?在大多数情况下,用户输入将在命令行上回显。这可以改变,但会依赖于平台。 – Lucas 2009-11-23 22:37:21

+2

重复:http://stackoverflow.com/questions/1413445/read-a-password-from-stdcin – 2009-11-23 22:37:29

回答

2

对于C /命令行/ Linux,请参阅:

man getch 
man noecho 

看到getchnoecho的COMENT。我从来没有尝试过这个。

在bash如果你使用read -s它不会在屏幕上回应:

> read -s x 
<type something><enter> 
> echo $x 
<whatever you typed> 
+0

Upvoted为RTFM理念和跨平台提示。 – conradkdotcom 2014-07-31 20:09:52

16

如果您的系统提供了它,getpass是一个选项:

#include <unistd.h> 
/* ... */ 
char *password = getpass("Password: "); 

这将不显示任何的字符打字。

2

要以便携的方式执行此操作,您需要使用标准化或事实上的标准库。

请参阅man 3 termiosman 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可能会更好,并且会避免system()的fork和可能的安全问题。使用标准I/O读取密码可能会更好。 (正如所写的那样,必须删除类型化的换行符。)Linux中有一个getpass()函数,但有些函数被标记为“过时,不要使用它”。处理SIGTSTP可能是个好主意。

总体来说,我可能会寻找一个现有的解决方案,与所有这些小问题,交易...

1

如果您有机会获得诅咒库,你可以使用noecho。如果您使用的是Microsoft的C编译器,则可以使用_getch。但afaik,这两者都将你与控制台联系在一起。如果您需要阅读stdin,无论它来自控制台还是文件或管道命令,则需要告诉操作系统它应该如何应用handle the console

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; 
} 
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;} 
2

功能将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); 
}