* 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

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>
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MINOR): Bump to 13.

View File

@ -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;
}