Подтвердить что ты не робот

C ввод пароля командной строки

Я хочу, чтобы пользователи вводили пароль с помощью интерфейса командной строки. но я не хочу отображать этот пароль на экране (или отображать "****" ).

Как это сделать в C? Спасибо.

Update:

Я работаю только с Linux. Поэтому я действительно не забочусь о Win или других системах. Я попробовал решение Lucas, и все получилось отлично. Однако у меня есть еще один вопрос:

  • Если это однопроцессное приложение и приложение с одним потоком, изменение настройки termios влияет на разные терминалы?

  • Как насчет 1 процесса - несколько потоков, много процессов - несколько потоков?

Большое спасибо.

4b9b3361

Ответ 1

Если ваша система предоставляет его, getpass является опцией:

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

Это не отображает ничего, поскольку набираются символы.

Ответ 2

Если вы используете среду 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;
}

Ответ 3

Для C/commandline/linux см.:

man getch
man noecho

см. в coment в getch около noecho. Я никогда не пробовал это сам.

В bash, если вы используете read -s, он не будет эхом на экране:

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

Ответ 4

Чтобы сделать это переносимым способом, вам понадобится стандартная или де-факто стандартная библиотека.

См. 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.

В целом, я могу найти существующее решение, которое касается всех этих небольших проблем...

Ответ 5

Функция 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);
}

Ответ 6

Если у вас есть доступ к библиотеке curses, вы можете использовать noecho. Если вы используете компилятор Microsoft C, вы можете использовать _ getch. Но афайк, оба они связывают вас с консолью. Если вам нужно читать stdin, независимо от того, поступает ли он от консоли или файла или команды с каналами, вам нужно сообщить операционной системе, как она должна обрабатывать консоль.

Ответ 7

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