diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-04-04 09:57:17 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-04-04 09:57:17 +0000 |
commit | 7c1d11f7e82c0ff8563d4426262f1025ac03d6dc (patch) | |
tree | 69729fa9090655d973fb53cca7b0caf47a1084e2 /winsup/cygwin/passwd.cc | |
parent | ecdcf15712b184af397c6440baa4f4b3f9e263c3 (diff) | |
download | cygnal-7c1d11f7e82c0ff8563d4426262f1025ac03d6dc.tar.gz cygnal-7c1d11f7e82c0ff8563d4426262f1025ac03d6dc.tar.bz2 cygnal-7c1d11f7e82c0ff8563d4426262f1025ac03d6dc.zip |
* passwd.cc (_getpass_close_fd): New static pthread cleanup handler.
(getpass): Rework to use /dev/tty in the first place. Install
_getpass_close_fd as pthread cleanup handler. Flush prompt explicitely.
Lock input and switch off signal input handling when reading password.
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r-- | winsup/cygwin/passwd.cc | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 962bf776e..74b8020b8 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -269,29 +269,50 @@ setpassent () return 0; } +static void +_getpass_close_fd (void *arg) +{ + if (arg) + fclose ((FILE *) arg); +} + extern "C" char * getpass (const char * prompt) { char *pass = _my_tls.locals.pass; struct termios ti, newti; - cygheap_fdget fhstdin (0); + /* Try to use controlling tty in the first place. Use stdin and stderr + only as fallback. */ + FILE *in = stdin, *err = stderr; + FILE *tty = fopen ("/dev/tty", "w+b"); + pthread_cleanup_push (_getpass_close_fd, tty); + if (tty) + { + /* Set close-on-exec for obvious reasons. */ + fcntl (fileno (tty), F_SETFD, fcntl (fileno (tty), F_GETFD) | FD_CLOEXEC); + in = err = tty; + } - if (fhstdin < 0) + /* Make sure to notice if stdin is closed. */ + if (tcgetattr (fileno (in), &ti) == -1) pass[0] = '\0'; else { - fhstdin->tcgetattr (&ti); + flockfile (in); newti = ti; - newti.c_lflag &= ~ECHO; - fhstdin->tcsetattr (TCSANOW, &newti); - fputs (prompt, stderr); - fgets (pass, _PASSWORD_LEN, stdin); - fprintf (stderr, "\n"); - for (int i=0; pass[i]; i++) - if (pass[i] == '\r' || pass[i] == '\n') - pass[i] = '\0'; - fhstdin->tcsetattr (TCSANOW, &ti); + newti.c_lflag &= ~(ECHO | ISIG); /* No echo, no signal handling. */ + tcsetattr (fileno (in), TCSANOW, &newti); + fputs (prompt, err); + fflush (err); + fgets (pass, _PASSWORD_LEN, in); + fprintf (err, "\n"); + tcsetattr (fileno (in), TCSANOW, &ti); + funlockfile (in); + char *crlf = strpbrk (pass, "\r\n"); + if (crlf) + *crlf = '\0'; } + pthread_cleanup_pop (1); return pass; } |