* 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.
This commit is contained in:
Corinna Vinschen 2012-04-04 09:57:17 +00:00
parent ecdcf15712
commit 7c1d11f7e8
2 changed files with 40 additions and 12 deletions
winsup/cygwin

View File

@ -1,3 +1,10 @@
2012-04-04 Corinna Vinschen <corinna@vinschen.de>
* 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.
2012-04-03 Corinna Vinschen <corinna@vinschen.de> 2012-04-03 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 13. * include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 13.

View File

@ -269,29 +269,50 @@ setpassent ()
return 0; return 0;
} }
static void
_getpass_close_fd (void *arg)
{
if (arg)
fclose ((FILE *) arg);
}
extern "C" char * extern "C" char *
getpass (const char * prompt) getpass (const char * prompt)
{ {
char *pass = _my_tls.locals.pass; char *pass = _my_tls.locals.pass;
struct termios ti, newti; 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'; pass[0] = '\0';
else else
{ {
fhstdin->tcgetattr (&ti); flockfile (in);
newti = ti; newti = ti;
newti.c_lflag &= ~ECHO; newti.c_lflag &= ~(ECHO | ISIG); /* No echo, no signal handling. */
fhstdin->tcsetattr (TCSANOW, &newti); tcsetattr (fileno (in), TCSANOW, &newti);
fputs (prompt, stderr); fputs (prompt, err);
fgets (pass, _PASSWORD_LEN, stdin); fflush (err);
fprintf (stderr, "\n"); fgets (pass, _PASSWORD_LEN, in);
for (int i=0; pass[i]; i++) fprintf (err, "\n");
if (pass[i] == '\r' || pass[i] == '\n') tcsetattr (fileno (in), TCSANOW, &ti);
pass[i] = '\0'; funlockfile (in);
fhstdin->tcsetattr (TCSANOW, &ti); char *crlf = strpbrk (pass, "\r\n");
if (crlf)
*crlf = '\0';
} }
pthread_cleanup_pop (1);
return pass; return pass;
} }