From: Todd C. Miller Date: Fri, 4 Jun 2010 21:44:43 +0000 (-0400) Subject: Do signal setup after turning off echo, not before. If we are using X-Git-Tag: SUDO_1_7_3~112 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47e5321804ee1235b4dae50bbf5d1e6f3e6d680c;p=sudo Do signal setup after turning off echo, not before. If we are using a tty but are not the foreground pgrp this will generate SIGTTOU so we want the default action to be taken (suspend process). Use an array for signals received instead of a single variable so we don't lose any when there are multiple different signals. --HG-- branch : 1.7 --- diff --git a/tgetpass.c b/tgetpass.c index 3c51f2862..48b6b1e7a 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -56,7 +56,17 @@ #include "sudo.h" -static volatile sig_atomic_t signo; +#if !defined(NSIG) +# if defined(_NSIG) +# define NSIG _NSIG +# elif defined(__NSIG) +# define NSIG __NSIG +# else +# define NSIG 64 +# endif +#endif + +static volatile sig_atomic_t signo[NSIG]; static void handler __P((int)); static char *getln __P((int, char *, size_t, int)); @@ -75,7 +85,7 @@ tgetpass(prompt, timeout, flags) sigaction_t savetstp, savettin, savettou; char *pass; static char buf[SUDO_PASS_MAX + 1]; - int input, output, save_errno, neednl;; + int i, input, output, save_errno, neednl, need_restart; (void) fflush(stdout); @@ -84,9 +94,11 @@ tgetpass(prompt, timeout, flags) return(sudo_askpass(prompt)); restart: - signo = 0; + for (i = 0; i < NSIG; i++) + signo[i] = 0; pass = NULL; save_errno = 0; + need_restart = 0; /* Open /dev/tty for reading/writing if possible else use stdin/stderr. */ if (ISSET(flags, TGP_STDIN) || (input = output = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) { @@ -94,6 +106,15 @@ restart: output = STDERR_FILENO; } + /* + * If we are using a tty but are not the foreground pgrp this will + * generate SIGTTOU, so do it *before* installing the signal handlers. + */ + if (def_pwfeedback) + neednl = term_cbreak(input); + else + neednl = term_noecho(input); + /* * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. @@ -111,25 +132,17 @@ restart: (void) sigaction(SIGTTIN, &sa, &savettin); (void) sigaction(SIGTTOU, &sa, &savettou); - if (def_pwfeedback) - neednl = term_cbreak(input); - else - neednl = term_noecho(input); - - /* No output if we are already backgrounded. */ - if (signo != SIGTTOU && signo != SIGTTIN) { - if (prompt) - (void) write(output, prompt, strlen(prompt)); + if (prompt) + (void) write(output, prompt, strlen(prompt)); - if (timeout > 0) - alarm(timeout); - pass = getln(input, buf, sizeof(buf), def_pwfeedback); - alarm(0); - save_errno = errno; + if (timeout > 0) + alarm(timeout); + pass = getln(input, buf, sizeof(buf), def_pwfeedback); + alarm(0); + save_errno = errno; - if (neednl) - (void) write(output, "\n", 1); - } + if (neednl) + (void) write(output, "\n", 1); /* Restore old tty settings and signals. */ term_restore(input, 1); @@ -148,15 +161,20 @@ restart: * 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: - goto restart; + for (i = 0; i < NSIG; i++) { + if (signo[i]) { + kill(getpid(), i); + switch (i) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + need_restart = 1; + break; + } } } + if (need_restart) + goto restart; if (save_errno) errno = save_errno; @@ -267,7 +285,7 @@ handler(s) int s; { if (s != SIGALRM) - signo = s; + signo[s] = 1; } int