Получение пароля на C без использования getpass (3)?
Я мог бы использовать getpass()
для получения пароля. Однако на странице руководства говорится:
Эта функция устарела. Не используй он.
Каков текущий способ получить пароль из пользовательского терминала без его эхо-ответа, с POSIX-совместимым способом? [Первоначально я сказал "портативно", но я решил не использовать устаревшую функцию.]
Ответы
Ответ 1
это должно работать на linux/macosx, версия Windows должна использовать Get/Set ConsoleMode
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
int
main(int argc, char **argv)
{
struct termios oflags, nflags;
char password[64];
/* 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("password: ");
fgets(password, sizeof(password), stdin);
password[strlen(password) - 1] = 0;
printf("you typed '%s'\n", password);
/* restore terminal */
if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
perror("tcsetattr");
return EXIT_FAILURE;
}
return 0;
}
Ответ 2
Вы можете использовать библиотеку ncurses для чтения со стандартного ввода без отражения результатов на экране, (Вызовите noecho()
, прежде чем получать какие-либо данные). Библиотека существует уже много веков и работает на самых разных платформах (версия Windows может быть найдена здесь)
Ответ 3
Даже если это очень старый вопрос, на который уже был дан ответ, вот то, что я использовал (что очень похоже на принятый ответ):
#include <termios.h>
#include <cstdio>
//
// The following is a slightly modifed version taken from:
// http://www.gnu.org/software/libc/manual/html_node/getpass.html
//
ssize_t my_getpass (char *prompt, char **lineptr, size_t *n, FILE *stream)
{
struct termios _old, _new;
int nread;
/* Turn echoing off and fail if we can’t. */
if (tcgetattr (fileno (stream), &_old) != 0)
return -1;
_new = _old;
_new.c_lflag &= ~ECHO;
if (tcsetattr (fileno (stream), TCSAFLUSH, &_new) != 0)
return -1;
/* Display the prompt */
if (prompt)
printf("%s", prompt);
/* Read the password. */
nread = getline (lineptr, n, stream);
/* Remove the carriage return */
if (nread >= 1 && (*lineptr)[nread - 1] == '\n')
{
(*lineptr)[nread-1] = 0;
nread--;
}
printf("\n");
/* Restore terminal. */
(void) tcsetattr (fileno (stream), TCSAFLUSH, &_old);
return nread;
}
//
// Test harness - demonstrate calling my_getpass().
//
int main(int argc, char *argv[])
{
size_t maxlen = 255;
char pwd[maxlen];
char *pPwd = pwd; // <-- haven't figured out how to avoid this.
int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin);
printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd);
return 0;
}
Ответ 4
Согласно документации Университета Милуоки, он устарел, потому что:
Функция getpass()
не является потокобезопасной, поскольку она управляет глобальное состояние сигнала.
Функция getpass()
должна быть удалена из будущей версии спецификации X/Open CAE.
Ответ 5
В окнах вы, вероятно, можете использовать SetConsoleMode
api, описанный здесь.
Ответ 6
Еще одно простое решение для Windows.
Включить "conio.h"
for (;;) {
int c = _getch();
switch (c)
{
case '\r':
case '\n':
case EOF:
_putch('\n');
break;
default:
_putch('*'); //mask
thePassword += char(c);
continue;
}
break;
}