【问题标题】:How to use getpass() with poll() to set time limit?如何使用 getpass() 和 poll() 来设置时间限制?
【发布时间】:2015-09-29 07:22:29
【问题描述】:

我正在使用poll()getpass() 在有限的时间内从用户那里获得输入。它可以工作,但不是显示getpass() 中给出的message,而是在按下enter key 之前不显示message。如何同时使用这两个功能,让getpass()中给出的message无需输入enter key就能显示出来,而且输入密码的时间会受到限制?

我试图通过清除stdinstdout 来解决这个问题,但没有奏效。

#include <poll.h>
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
if( poll(&mypoll, 1, 20000) )
{
    char *pass = getpass("\nPlease enter password:");
}

【问题讨论】:

    标签: c linux input stdin


    【解决方案1】:

    getpass 函数已过时。不要使用它。

    这是一个工作示例。程序等待 20 秒。如果用户在 20 秒内输入密码,则程序会读取密码信息,否则会通知用户输入密码超时。以下示例不会关闭回显。

    #include <unistd.h>
    #include <poll.h>
    #include <stdio.h>
    
    int main()
    {
        struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
        char password[100];
    
        printf("Please enter password\n");
        if( poll(&mypoll, 1, 20000) )
        {
            scanf("%99s", password); 
            printf("password - %s\n", password);
        }
        else
        {
            puts("Time Up");
        }
    
        return 0;
    }
    

    以下示例将关闭回声。与 getpass 相同。这适用于 linux/macosx,windows 版本应该使用Get/Set ConsoleMode

    #include <unistd.h>
    #include <poll.h>
    #include <stdio.h>
    #include <termios.h>
    #include <stdlib.h>
    int main()
    {
        struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
        char password[100];
        struct termios oflags, nflags;
    
        /* disabling echo */
        tcgetattr(fileno(stdin), &oflags);
        nflags = oflags;
        nflags.c_lflag &= ~ECHO;
        nflags.c_lflag |= ECHONL;
    
        if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
            perror("tcsetattr");
            return EXIT_FAILURE;
        }
    
        printf("Please enter password\n");
        if( poll(&mypoll, 1, 20000) )
        {
            scanf("%s", password);
            printf("password - %s\n", password);
        }
        else
        {
            puts("Time Up");
        }
    
        /* restore terminal */
        if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
            perror("tcsetattr");
            return EXIT_FAILURE;
        }
        return 0;
    }
    

    【讨论】:

    • getpass 和 scanf 有区别,第一个关闭 echo 并首先尝试从 /dev/tty 读取,而后者则没有,所以 scanf 不是替换。接下来,如果您建议使用scanf,您至少可以不添加不受控制的缓冲区溢出可能性并使用scanf("%99s", password);
    • @SergeBallesta 感谢您指出缓冲区溢出。在答案中对其进行了修改。是的,scanf 不是 getpass 的替代品。如果 OP 只想在有限的时间内从用户那里获得输入,那么 OP 可以使用它。提供了另一个控制回声的例子。
    猜你喜欢
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 2016-02-18
    • 2019-08-17
    • 2017-12-10
    相关资源
    最近更新 更多