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 | |
| 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>
| -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);  | 
