From 38b3cd5f04f3a0c38941146b81e8292ec3abbcac Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 23 Dec 2011 14:24:12 +0100 Subject: getpass: several fixes fixes bogus fgets error check fixes bogus strlen() < 0 check switches off buffering regardless of tcgetattr() success prints newline even on error or if there was no '\n' on input uses sizeof(buf) instead of PWD_BUFFER_SIZE Signed-off-by: Denys Vlasenko --- libc/unistd/getpass.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) (limited to 'libc/unistd') diff --git a/libc/unistd/getpass.c b/libc/unistd/getpass.c index 8d8018231..dd927ab87 100644 --- a/libc/unistd/getpass.c +++ b/libc/unistd/getpass.c @@ -45,17 +45,22 @@ char * getpass (const char *prompt) /* Try to write to and read from the terminal if we can. If we can't open the terminal, use stderr and stdin. */ - in = fopen ("/dev/tty", "r+"); + out = in = fopen ("/dev/tty", "r+"); if (in == NULL) { in = stdin; out = stderr; } else - out = in; + { + /* Disable buffering for read/write FILE to prevent problems with + * fseek and buffering for read/write auto-transitioning. */ + setvbuf(in, NULL, _IONBF, 0); + } /* Turn echoing off if it is on now. */ + tty_changed = 0; if (tcgetattr (fileno (in), &t) == 0) { /* Save the old one. */ @@ -63,41 +68,28 @@ char * getpass (const char *prompt) /* Tricky, tricky. */ t.c_lflag &= ~(ECHO|ISIG); tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); - if (in != stdin) { - /* Disable buffering for read/write FILE to prevent problems with - * fseek and buffering for read/write auto-transitioning. */ - setvbuf(in, NULL, _IONBF, 0); - } } - else - tty_changed = 0; /* Write the prompt. */ fputs(prompt, out); fflush(out); /* Read the password. */ - fgets (buf, PWD_BUFFER_SIZE-1, in); - if (buf != NULL) + if (!fgets (buf, sizeof(buf)-1, in)) + buf[0] = '\0'; + nread = strlen(buf); + if (nread > 0 && buf[nread - 1] == '\n') + /* Remove the newline. */ + buf[nread - 1] = '\0'; + + if (tty_changed) { - nread = strlen(buf); - if (nread < 0) - buf[0] = '\0'; - else if (buf[nread - 1] == '\n') - { - /* Remove the newline. */ - buf[nread - 1] = '\0'; - if (tty_changed) - /* Write the newline that was not echoed. */ - putc('\n', out); - } + /* Write the newline that was not echoed. */ + putc('\n', out); + /* Restore the original setting. */ + (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); } - /* Restore the original setting. */ - if (tty_changed) { - (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); - } - if (in != stdin) /* We opened the terminal; now close it. */ fclose (in); -- cgit v1.2.3