Finally complete my fix for the behaviour of getpass(3) upon receipt
of signals. Signals are now properly caught, tty state is being restored, and the previous sigaction triggered. Upon receipt of a sigcont, echo is turned off again. SIGTSTP causes a buffer flush, the man page mentions this. (Although i rather think of it as a feature than a bug.) This is likely to be my last FreeBSD action for 1995, xearth shows me that our .au guys must already write 1996. :-)
This commit is contained in:
parent
cfaaf1594e
commit
7560bb26ff
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user