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

Получение пароля на C без использования getpass (3)?

Я мог бы использовать getpass() для получения пароля. Однако на странице руководства говорится:

Эта функция устарела. Не используй он.

Каков текущий способ получить пароль из пользовательского терминала без его эхо-ответа, с POSIX-совместимым способом? [Первоначально я сказал "портативно", но я решил не использовать устаревшую функцию.]

4b9b3361

Ответ 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;
}