2009-07-28 7 views
20

Mogę użyć getpass(), aby uzyskać hasło. Jednak strona podręcznika mówi:Uzyskiwanie hasła w C bez użycia getpass (3)?

Ta funkcja jest przestarzała. Nie używaj go w postaci .

Jaki jest obecny sposób uzyskania hasła z terminala użytkownika bez jego echo, w sposób zgodny z POSIX? [Pierwotnie powiedziałem "przenośnie", ale moim zamiarem było uniknięcie użycia przestarzałej funkcji.]

+4

Nie ma przenośnej drogi - to zależy w dużej mierze od platformy. –

+0

@Jerry, to nie jest tego warte ... nawet jeśli jest to LEGACY, jest to najbardziej przenośny sposób na zrobienie tego. –

Odpowiedz

13

to powinno działać na platformie Linux/MacOSX, wersja okna powinny używać 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; 
} 
+0

To wydaje mi się najbardziej prostą drogą. –

+3

Powinieneś najpierw użyć/dev/tty, zanim spróbujesz stdin, tak jakbyś korzystał z potoku, stdin byłby potokiem, a nie wejściem terminalowym. – xryl669

+3

Nie miałbym nic przeciwko wyświetleniu hasła char [64] = {0}; lub memset, zanim zostanie użyty, jeśli jest ponownie wpisany –

4

Można użyć biblioteki ncurses do odczytu ze standardowego wejścia bez wyświetlania wyników na ekranie. (Zadzwoń pod numer noecho(), zanim otrzymasz jakiekolwiek dane wejściowe). Biblioteka istnieje już od wieków i działa na wielu platformach (wersja Windows można znaleźć here)

+0

Zrobiłem prostą aplikację curses (kilka dekad od czasu użycia przekleństw) i odkryłem, że wyczyściła ekran, gdy robiłem initscr(). Prawdopodobnie jest to możliwe, ale nie było to oczywiste po szybkim przejrzeniu stron man. –

1

W systemie Windows prawdopodobnie można korzystać z api SetConsoleMode, opisanego jako here.

2

Według University of Milwaukee's documentation jest przestarzały, ponieważ:

Funkcja getpass() nie jest threadsafe ponieważ manipuluje globalny stan sygnału.

Funkcja zostanie usunięta z przyszłej wersji specyfikacji X/Open CAE.

+3

Został wycofany z POSIX/Single UNIX (następca X/Open) od 2001 roku. –

+2

Jak to jest odpowiedź? To naprawdę powinien być komentarz. –

3

Choć jest to bardzo stare pytanie, które zostało już odpowiedział, oto co używam (co jest bardzo podobny do zaakceptowanej odpowiedzi):

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

Me gusta. Pozwoli to nawet na wpisanie hasła z wiersza poleceń; jednak, jeśli chcesz to zrobić, możesz nie chcieć wydrukować monitu o hasło. – JesseTG

Powiązane problemy