在Linux上的C程序中屏蔽密码字符

问题描述

我正在尝试创建一个程序,以使输入密码时输入的字符模糊不清。但是我仍然有一个问题,一旦启动程序,就会连续写入“ *”字符,直到出现分段错误。这是我编写的代码以及执行后程序的行为:

#include <stdio.h>
#include <curses.h>

#define ENTER 13
#define TAB 9

char pwd[100];

int main(){
    int i = 0;
    char ch;

    printf("Enter your password. Hit ENTER to confirm.\n");
    printf("Password:");

    while(getch() != ENTER){
        ch = getch();
        pwd[i++] = ch;
        printf("* \b");
    }
    if(ch == ENTER || ch == TAB){
        pwd[i] = '\0';
    }

    printf("\n\nPassword:%s\nLength:%d\n\n",pwd,i);
    return 0;
}

enter image description here

解决方法

在开始使用任何ncurses方法之前,应先致电initscr();。因此,尝试这样做:

int main(){
    int i = 0;
    char ch;

    initscr();
    // ...

更多information

,

您似乎从ERR返回了getch()

那不等于ENTER,因此循环被输入并重复。最终,您用光了pwd中的空间,但是继续在它外面写东西。分段错误意味着您试图写一些不可写的地址。

您还存在一个错误,即每个循环调用getch()两次,即使在解决了循环/段错误问题之后,也会给您带来麻烦。

,

关于:

while(getch() != ENTER){
    ch = getch();

每次循环都会得到2个字符。不是你想要的。建议:

while( ( ch = getch() ) != ENTER ){

为避免在用户输入字符时回显字符,请执行以下操作: 您需要打开回显off,然后对于用户输入的每个字符,输出一个屏蔽字符,例如*

由于数组pwd[]仅100个字符长,因此需要将用户可以输入的字符数限制为99(为末尾的NUL字节留出空间)建议:

 WINDOW *mainwin;
 mainwin = initscr();   /* start the curses mode with default window */
 clear()    /* clear the default window */
 ...
 raw();     /* stop terminal driver from interpreting key strokes */ 
 cbreak();  /* input chars without waiting for newline */
 
 nodelay( mainwin,true); /* causes getch() to wait for a key rather than returning ERR */
 keypad( mainwin,true ); /* program must handle all meta keys including newline */

 noecho();  /* stop terminal echo while entering password */

 size_t i = 0;
 while( i < (sizeof( pwd ) -1) && ( ch = getch() ) != ENTER )
 {
     pwd[i] = ch;
     i++;

     printw( "*" );
     refresh();
 }

 echo();               /* resume echoing characters on terminal */
 keypad( mainwin,false );      /* stop passing keypad chars to program */
 noraw();              /* terminal driver resumes interpreting key strokes */

 pwd[i] = '\0';        /* NUL terminate the string */   
 ...
 endwin();

以上可能有点矫kill过正。

由于几个问题,建议不要使用C库函数:getpass()

如果您使用raw()函数,则该程序还需要处理用户的退格(和类似字符)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...