From f8176ceda26ee700aea8df21d41b590c2813654b Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Fri, 28 May 2004 22:06:50 +0000 Subject: [PATCH] Use SA_INTERRUPT so SunOS works correctly, avoid stdio and just use read/write as it is simpler. --- tgetpass.c | 69 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/tgetpass.c b/tgetpass.c index fb3d5ed0a..c3771c73a 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -115,6 +115,7 @@ static const char rcsid[] = "$Sudo$"; static volatile sig_atomic_t signo; static void handler __P((int)); +static char *getln __P((int, char *, size_t)); /* * Like getpass(3) but with timeout and echo flags. @@ -127,29 +128,26 @@ tgetpass(prompt, timeout, flags) { sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm; sigaction_t savetstp, savettin, savettou; - FILE *input, *output; struct TERM term, oterm; - char *pass, *ep; + char *pass; static char buf[SUDO_PASS_MAX + 1]; - int fd, save_errno; + int input, output, save_errno; + (void) fflush(stdout); restart: /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */ if (ISSET(flags, TGP_STDIN) || - (fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1 || - (input = output = fdopen(fd, "r+")) == NULL) { - input = stdin; - output = stderr; - (void) fflush(output); + (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) { + input = STDIN_FILENO; + output = STDERR_FILENO; } /* * 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. + * up with echo turned off in the shell. */ sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */ sa.sa_handler = handler; (void) sigaction(SIGALRM, &sa, &savealrm); (void) sigaction(SIGINT, &sa, &saveint); @@ -161,43 +159,34 @@ restart: (void) sigaction(SIGTTOU, &sa, &savettou); /* Turn echo off/on as specified by flags. */ - if (term_getattr(fileno(input), &oterm) == 0) { + if (term_getattr(input, &oterm) == 0) { (void) memcpy(&term, &oterm, sizeof(term)); if (!ISSET(flags, TGP_ECHO)) CLR(term.tflags, (ECHO | ECHONL)); #ifdef VSTATUS term.c_cc[VSTATUS] = _POSIX_VDISABLE; #endif - (void) term_setattr(fileno(input), &term); + (void) term_setattr(input, &term); } else { memset(&term, 0, sizeof(term)); memset(&oterm, 0, sizeof(oterm)); } - if (prompt) { - (void) fputs(prompt, output); - (void) fflush(output); - if (input == output) - (void) rewind(input); - } + if (prompt) + (void) write(output, prompt, strlen(prompt)); if (timeout > 0) alarm(timeout); - pass = fgets(buf, sizeof(buf), input); + pass = getln(input, buf, sizeof(buf)); alarm(0); - if (pass != NULL) { - ep = pass + strlen(pass); - while (ep > pass && (*--ep == '\n' || *ep == '\r')) - *ep = '\0'; - } save_errno = errno; if (!ISSET(term.tflags, ECHO)) - fputc('\n', output); + (void) write(output, "\n", 1); /* Restore old tty settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) - (void) term_setattr(fileno(input), &oterm); + (void) term_setattr(input, &oterm); (void) sigaction(SIGALRM, &savealrm, NULL); (void) sigaction(SIGINT, &saveint, NULL); (void) sigaction(SIGHUP, &savehup, NULL); @@ -206,8 +195,8 @@ restart: (void) sigaction(SIGTSTP, &savetstp, NULL); (void) sigaction(SIGTTIN, &savettin, NULL); (void) sigaction(SIGTTOU, &savettou, NULL); - if (input != stdin) - (void) fclose(input); + if (input != STDIN_FILENO) + (void) close(input); /* * If we were interrupted by a signal, resend it to ourselves @@ -228,6 +217,28 @@ restart: return(pass); } +static char * +getln(fd, buf, bufsiz) + int fd; + char *buf; + size_t bufsiz; +{ + char c, *cp; + ssize_t nr; + + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); /* sanity */ + } + + cp = buf; + nr = -1; + while (--bufsiz && (nr = read(fd, &c, 1)) == 1 && c != '\n' && c != '\r') + *cp++ = c; + *cp = '\0'; + return(nr == -1 ? NULL : buf); +} + static void handler(s) int s; -- 2.40.0