diff options
| author | Brian Feldman <green@FreeBSD.org> | 2002-03-08 21:14:00 +0000 |
|---|---|---|
| committer | Brian Feldman <green@FreeBSD.org> | 2002-03-08 21:14:00 +0000 |
| commit | a7a8a766e7845749d3350bbacc5d9572d96c2290 (patch) | |
| tree | 36829c674b6805dcd4b99f5436746d023c60065b /lib/libc/gen/readpassphrase.c | |
| parent | 147273e8cadff40e9c2b57eaaf3b0a5f47e053b2 (diff) | |
Notes
Diffstat (limited to 'lib/libc/gen/readpassphrase.c')
| -rw-r--r-- | lib/libc/gen/readpassphrase.c | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c index 2f7023202aba..18123546c072 100644 --- a/lib/libc/gen/readpassphrase.c +++ b/lib/libc/gen/readpassphrase.c @@ -1,3 +1,5 @@ +/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */ + /* * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> * All rights reserved. @@ -26,7 +28,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.7 2001/08/07 19:34:11 millert Exp $"; +static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -44,17 +46,19 @@ __FBSDID("$FreeBSD$"); #include <readpassphrase.h> #include "un-namespace.h" +static volatile sig_atomic_t signo; + +static void handler(int); + char * -readpassphrase(prompt, buf, bufsiz, flags) - const char *prompt; - char *buf; - size_t bufsiz; - int flags; +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) { - struct termios term, oterm; + ssize_t nr; + int input, output, save_errno; char ch, *p, *end; - int input, output; - sigset_t oset, nset; + struct termios term, oterm; + struct sigaction sa, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou; /* I suppose we could alloc on demand in this case (XXX). */ if (bufsiz == 0) { @@ -62,6 +66,7 @@ readpassphrase(prompt, buf, bufsiz, 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. @@ -76,20 +81,26 @@ readpassphrase(prompt, buf, bufsiz, flags) } /* - * We block SIGINT and SIGTSTP so the terminal is not left - * in an inconsistent state (ie: no echo). It would probably - * be better to simply catch these though. + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGALRM and SIGPIPE for now. */ - sigemptyset(&nset); - sigaddset(&nset, SIGINT); - sigaddset(&nset, SIGTSTP); - (void)_sigprocmask(SIG_BLOCK, &nset, &oset); + sigemptyset(&sa.sa_mask); + 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); + (void)_sigaction(SIGTSTP, &sa, &savetstp); + (void)_sigaction(SIGTTIN, &sa, &savettin); + (void)_sigaction(SIGTTOU, &sa, &savettou); /* Turn off echo if possible. */ if (tcgetattr(input, &oterm) == 0) { memcpy(&term, &oterm, sizeof(term)); - if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO)) - term.c_lflag &= ~ECHO; + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) term.c_cc[VSTATUS] = _POSIX_VDISABLE; (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); @@ -100,7 +111,7 @@ readpassphrase(prompt, buf, bufsiz, flags) (void)_write(output, prompt, strlen(prompt)); end = buf + bufsiz - 1; - for (p = buf; _read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) { + for (p = buf; (nr = _read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { if (p < end) { if ((flags & RPP_SEVENBIT)) ch &= 0x7f; @@ -114,23 +125,54 @@ readpassphrase(prompt, buf, bufsiz, flags) } } *p = '\0'; + save_errno = errno; if (!(term.c_lflag & ECHO)) (void)_write(output, "\n", 1); - /* Restore old terminal settings and signal mask. */ + /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) - (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm); - (void)_sigprocmask(SIG_SETMASK, &oset, NULL); + (void)tcsetattr(input, TCSANOW|TCSASOFT, &oterm); + (void)_sigaction(SIGINT, &saveint, NULL); + (void)_sigaction(SIGHUP, &savehup, NULL); + (void)_sigaction(SIGQUIT, &savequit, NULL); + (void)_sigaction(SIGTERM, &saveterm, NULL); + (void)_sigaction(SIGTSTP, &savetstp, NULL); + (void)_sigaction(SIGTTIN, &savettin, NULL); + (void)_sigaction(SIGTTOU, &savettou, NULL); if (input != STDIN_FILENO) (void)_close(input); - return(buf); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + if (signo) { + kill(getpid(), signo); + switch (signo) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + signo = 0; + goto restart; + } + } + + errno = save_errno; + return(nr == -1 ? NULL : buf); } +#if 0 char * -getpass(prompt) - const char *prompt; +getpass(const char *prompt) { static char buf[_PASSWORD_LEN + 1]; return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); } +#endif + +static void handler(int s) +{ + + signo = s; +} |
