diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-12-23 14:24:12 +0100 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-12-23 14:24:12 +0100 |
commit | 38b3cd5f04f3a0c38941146b81e8292ec3abbcac (patch) | |
tree | 8486c0e717f126d5f889e69e8d682a8cefd60d8e /libc/unistd/getpass.c | |
parent | 8a8434b367e0b94b9fda72c99f1c646737725403 (diff) |
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 <dvlasenk@redhat.com>
Diffstat (limited to 'libc/unistd/getpass.c')
-rw-r--r-- | libc/unistd/getpass.c | 46 |
1 files changed, 19 insertions, 27 deletions
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); |