Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-04-04 13:57:17 +0400
committerCorinna Vinschen <corinna@vinschen.de>2012-04-04 13:57:17 +0400
commit7c1d11f7e82c0ff8563d4426262f1025ac03d6dc (patch)
tree69729fa9090655d973fb53cca7b0caf47a1084e2 /winsup/cygwin/passwd.cc
parentecdcf15712b184af397c6440baa4f4b3f9e263c3 (diff)
* 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.cc45
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;
}