2009-07-28 7 views
20

Potrei usare getpass() per ottenere una password. Tuttavia, la pagina man dice:Ottenere una password in C senza usare getpass (3)?

Questa funzione è obsoleta. Non usare it.

Qual è il modo attuale di ottenere una password dal terminale dell'utente senza riecheggiarla, in un modo conforme a POSIX? [Originariamente ho detto "portabilmente", ma la mia intenzione era evitare l'uso di una funzione obsoleta.]

+4

Non esiste un metodo portatile, dipende in gran parte dalla piattaforma. –

+0

@Jerry, non ne vale la pena ... anche se è LEGACY, è il modo più portatile per farlo. –

risposta

13

questo dovrebbe funzionare su Linux/MacOSX, una versione per Windows dovrebbe utilizzare 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

Questo sembra il modo più diretto per me. –

+3

Si dovrebbe usare/dev/tty prima di provare lo stdin, come se si stesse usando una pipe, lo stdin sarebbe il contenuto in pipe, non l'input del terminale. – xryl669

+3

Non mi dispiacerebbe vedere la password char [64] = {0}; o un memset prima che venga usato se è rientranti –

4

È possibile utilizzare la libreria ncurses per leggere dallo standard input senza riportare i risultati sullo schermo. (Chiama noecho() prima di ricevere qualsiasi input). La biblioteca è stata intorno per le età e funziona su una vasta gamma di piattaforme (la versione di Windows può essere trovato here)

+0

Ho fatto una semplice app di curses (è stata decodificata da un paio di volte da quando ho usato curses), e ho scoperto che cancellava lo schermo quando facevo initscr(). Probabilmente c'è un modo per aggirare questo, ma non era ovvio da una rapida lettura delle pagine man. –

1

su Windows, probabilmente si può utilizzare il SetConsoleMode api, descritto here.

2

Secondo la University of Milwaukee's documentation esso è obsoleto perché:

La funzione getpass() non è threadsafe perché manipola stato di segnale globale.

La funzione getpass() è programmata per essere ritirata da una versione futura di X/Open CAE Specification.

+3

È stato ritirato da POSIX/Single UNIX (il successore di X/Open) dal 2001. –

+2

Come è questa una risposta? Questo dovrebbe essere davvero un commento. –

3

Anche se questa è una domanda molto antica che è già stato risposto, ecco cosa ho usato (che è molto simile alla risposta accettata):

#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. Questo ti permetterà anche di inserire la tua password dalla riga di comando; tuttavia, se lo farai, potresti non voler stampare una richiesta di password. – JesseTG

Problemi correlati