summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2001-12-07 22:16:49 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2001-12-07 22:16:49 +0000
commit301e3e49ce66f692104152d27c10a47f15daaf89 (patch)
tree3868829a3fb7a1616234ee2f22e60574354d99a7
parenta994716ebc6aaf583819900e980c0220350e54da (diff)
Instead of restoring the tty mode, restoring the signal handler,
unblocking the signal and redelivering it just make all our signal handler interupt system calls and set a flag. We can just deliver the signal at the end right before we would normally return. This solves the SIG_IGN problem nicely and causes readpassphrase() to return when someone hits ^C even if the handler is SIG_IGN.
-rw-r--r--lib/libc/gen/readpassphrase.321
-rw-r--r--lib/libc/gen/readpassphrase.c87
2 files changed, 27 insertions, 81 deletions
diff --git a/lib/libc/gen/readpassphrase.3 b/lib/libc/gen/readpassphrase.3
index 0abfbf3de7e..7ec89898352 100644
--- a/lib/libc/gen/readpassphrase.3
+++ b/lib/libc/gen/readpassphrase.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: readpassphrase.3,v 1.4 2001/12/07 20:21:17 millert Exp $
+.\" $OpenBSD: readpassphrase.3,v 1.5 2001/12/07 22:16:48 millert Exp $
.\"
.\" Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
.\" All rights reserved.
@@ -131,30 +131,13 @@ signal (stop signal generated from keyboard) is treated specially.
When the process is resumed after it has been stopped,
.Fn readpassphrase
will reprint the prompt and the user may then enter a passphrase.
-.Pp
-Note: if the handler for a signal was
-.Dv SIG_IGN
-(ignore signal) when
-.Fn readpassphrase
-was called, terminal echo will not be restored to its previous value
-(since there is no other handler to call).
-This is only a problem when the program that calls
-.Fn readpassphrase
-is running as a child process of another program that also
-receives the signal (and exits or suspends due to it).
-Because of this it is suggested that these signals be blocked
-instead of ignored.
-See
-.Xr sigprocmask 3
-for details on blocking signal receipt.
.Sh FILES
.Bl -tag -width /dev/tty -compact
.It Pa /dev/tty
.El
.Sh SEE ALSO
.Xr sigaction 2 ,
-.Xr getpass 3 ,
-.Xr sigprocmask 3
+.Xr getpass 3
.Sh HISTORY
The
.Fn readpassphrase
diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c
index 515a37ad965..197e0003617 100644
--- a/lib/libc/gen/readpassphrase.c
+++ b/lib/libc/gen/readpassphrase.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readpassphrase.c,v 1.9 2001/12/06 07:04:17 millert Exp $ */
+/* $OpenBSD: readpassphrase.c,v 1.10 2001/12/07 22:16:48 millert Exp $ */
/*
* Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -28,7 +28,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.9 2001/12/06 07:04:17 millert Exp $";
+static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.10 2001/12/07 22:16:48 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <ctype.h>
@@ -42,19 +42,17 @@ static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.9 2001/12/06 07:04:1
#include <unistd.h>
#include <readpassphrase.h>
-/* Shared with signal handler below to restore state. */
-static struct termios term, oterm;
-static struct sigaction sa, saveint, savehup, savequit, saveterm, savetstp;
-static int input;
-static volatile sig_atomic_t susp;
+static volatile sig_atomic_t signo;
static void handler(int);
char *
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
{
+ int input, output;
char ch, *p, *end;
- int output;
+ struct termios term, oterm;
+ struct sigaction sa, saveint, savehup, savequit, saveterm, savetstp;
/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
@@ -62,6 +60,7 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
return(NULL);
}
+restart:
/*
* Read and write to /dev/tty if available. If not, read from
* stdin and write to stderr unless a tty is required.
@@ -81,13 +80,12 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
* things like SIGALRM and SIGPIPE for now.
*/
sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
+ sa.sa_flags = 0; /* don't restart system calls */
sa.sa_handler = handler;
(void)sigaction(SIGINT, &sa, &saveint);
(void)sigaction(SIGHUP, &sa, &savehup);
(void)sigaction(SIGQUIT, &sa, &savequit);
(void)sigaction(SIGTERM, &sa, &saveterm);
- sa.sa_flags = 0; /* don't restart for SIGTSTP */
(void)sigaction(SIGTSTP, &sa, &savetstp);
/* Turn off echo if possible. */
@@ -103,7 +101,6 @@ readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
memset(&oterm, 0, sizeof(oterm));
}
-redo:
(void)write(output, prompt, strlen(prompt));
end = buf + bufsiz - 1;
for (p = buf; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) {
@@ -119,18 +116,13 @@ redo:
*p++ = ch;
}
}
- if (susp) {
- /* Back from suspend. */
- susp = 0;
- goto redo;
- }
*p = '\0';
if (!(term.c_lflag & ECHO))
(void)write(output, "\n", 1);
/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0)
- (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm);
+ (void)tcsetattr(input, TCSANOW|TCSASOFT, &oterm);
(void)sigaction(SIGINT, &saveint, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
(void)sigaction(SIGQUIT, &savequit, NULL);
@@ -138,6 +130,20 @@ redo:
(void)sigaction(SIGTSTP, &savetstp, NULL);
if (input != STDIN_FILENO)
(void)close(input);
+
+ /*
+ * If we were interrupted by a signal, resend it to ourselves
+ * now that we have restored the signal handlers.
+ */
+ if (signo) {
+ kill(getpid(), signo);
+ if (signo == SIGTSTP) {
+ signo = 0;
+ goto restart;
+ }
+
+ }
+
return(buf);
}
@@ -149,51 +155,8 @@ getpass(const char *prompt)
return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
}
-static void handler(int signo)
+static void handler(int s)
{
- struct sigaction osa;
- sigset_t nset;
- int save_errno;
-
- save_errno = errno;
-
- /* Restore tty modes */
- if (memcmp(&term, &oterm, sizeof(term)) != 0)
- (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm);
-
- /*
- * Save old handler and set to original value.
- * Unblock receipt of 'signo' and resend the signal so that
- * it is caught by the pre-readpassphrase handler.
- */
- switch (signo) {
- case SIGINT:
- (void)sigaction(signo, &saveint, &osa);
- break;
- case SIGHUP:
- (void)sigaction(signo, &savehup, &osa);
- break;
- case SIGQUIT:
- (void)sigaction(signo, &savequit, &osa);
- break;
- case SIGTERM:
- (void)sigaction(signo, &saveterm, &osa);
- break;
- case SIGTSTP:
- (void)sigaction(signo, &savetstp, &osa);
- susp = 1;
- break;
- }
- (void)sigemptyset(&nset);
- (void)sigaddset(&nset, signo);
- (void)sigprocmask(SIG_UNBLOCK, &nset, NULL);
- (void)kill(getpid(), signo);
- (void)sigprocmask(SIG_BLOCK, &nset, NULL);
- (void)sigaction(signo, &osa, NULL);
-
- /* Put tty modes back */
- if (memcmp(&term, &oterm, sizeof(term)) != 0)
- (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
- errno = save_errno;
+ signo = s;
}