summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/getpass.34
-rw-r--r--lib/libc/gen/getpass.c70
2 files changed, 56 insertions, 18 deletions
diff --git a/lib/libc/gen/getpass.3 b/lib/libc/gen/getpass.3
index 34e91cb..f312d42 100644
--- a/lib/libc/gen/getpass.3
+++ b/lib/libc/gen/getpass.3
@@ -86,3 +86,7 @@ will modify the same object.
The calling process should zero the password as soon as possible to
avoid leaving the cleartext password visible in the process's address
space.
+.Pp
+Upon receipt of a SIGTSTP, the input buffer will be flushed, so any
+partially typed password must be retyped when the process
+continues.
diff --git a/lib/libc/gen/getpass.c b/lib/libc/gen/getpass.c
index cf6088a..658f5b6 100644
--- a/lib/libc/gen/getpass.c
+++ b/lib/libc/gen/getpass.c
@@ -43,16 +43,47 @@ static char sccsid[] = "@(#)getpass.c 8.1 (Berkeley) 6/4/93";
#include <stdio.h>
#include <unistd.h>
+static struct termios oterm, term;
+static sig_t ointhandler, oquithandler, otstphandler, oconthandler;
+static FILE *fp;
+
+static void
+sighandler(int signo)
+{
+ /* restore tty state */
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &oterm);
+
+ /* restore old sig handlers */
+ (void)signal(SIGINT, ointhandler);
+ (void)signal(SIGQUIT, oquithandler);
+ (void)signal(SIGTSTP, otstphandler);
+
+ /* resend us this signal */
+ (void)kill(getpid(), signo);
+}
+
+/* ARGSUSED */
+static void
+sigconthandler(int signo)
+{
+ /* re-install our signal handlers */
+ ointhandler = signal(SIGINT, sighandler);
+ oquithandler = signal(SIGQUIT, sighandler);
+ otstphandler = signal(SIGTSTP, sighandler);
+
+ /* turn off echo again */
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
+}
+
+
char *
getpass(prompt)
const char *prompt;
{
- struct termios term;
register int ch;
register char *p;
- FILE *fp, *outfp;
+ FILE *outfp;
long omask;
- int echo;
static char buf[_PASSWORD_LEN + 1];
/*
@@ -63,16 +94,16 @@ getpass(prompt)
outfp = stderr;
fp = stdin;
}
- /*
- * note - blocking signals isn't necessarily the
- * right thing, but we leave it for now.
- */
- omask = sigblock(sigmask(SIGTSTP));
- (void)tcgetattr(fileno(fp), &term);
- if (echo = (term.c_lflag & ECHO)) {
- term.c_lflag &= ~ECHO;
- (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
- }
+
+ ointhandler = signal(SIGINT, sighandler);
+ oquithandler = signal(SIGQUIT, sighandler);
+ otstphandler = signal(SIGTSTP, sighandler);
+ oconthandler = signal(SIGCONT, sigconthandler);
+
+ (void)tcgetattr(fileno(fp), &oterm);
+ term = oterm;
+ term.c_lflag &= ~ECHO;
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
(void)fputs(prompt, outfp);
rewind(outfp); /* implied flush */
for (p = buf; (ch = getc(fp)) != EOF && ch != '\n';)
@@ -80,11 +111,14 @@ getpass(prompt)
*p++ = ch;
*p = '\0';
(void)write(fileno(outfp), "\n", 1);
- if (echo) {
- term.c_lflag |= ECHO;
- (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &term);
- }
- (void)sigsetmask(omask);
+ (void)tcsetattr(fileno(fp), TCSAFLUSH|TCSASOFT, &oterm);
+
+ /* restore old sig handlers */
+ (void)signal(SIGINT, ointhandler);
+ (void)signal(SIGQUIT, oquithandler);
+ (void)signal(SIGTSTP, otstphandler);
+ (void)signal(SIGCONT, oconthandler);
+
if (fp != stdin)
(void)fclose(fp);
return(buf);
OpenPOWER on IntegriCloud