From 03e3ca08dbcfcfaff664d3d0d5a41c9cf8a82215 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" <Todd.Miller@courtesan.com> Date: Sun, 11 Oct 2009 13:25:23 +0000 Subject: [PATCH] Handle SIGTTOU and remove some debugging. --- script.c | 112 +++++++++++++++++++++++-------------------------------- 1 file changed, 47 insertions(+), 65 deletions(-) diff --git a/script.c b/script.c index b6dffe5e5..d8b79024b 100644 --- a/script.c +++ b/script.c @@ -100,8 +100,6 @@ static int get_pty __P((int *master, int *slave)); /* * TODO: run monitor as root? - * make bg work (does not generate SIGTTOU) - * handle SIGTTIN/SIGTTOU better (race?) */ struct script_buf { @@ -239,9 +237,8 @@ script_setup() log_error(USE_ERRNO, "Can't get pty"); /* Copy terminal attrs from stdin -> pty slave. */ - if (!term_copy(STDIN_FILENO, script_fds[SFD_SLAVE], 0)) { + if (!term_copy(STDIN_FILENO, script_fds[SFD_SLAVE], 0)) log_error(USE_ERRNO, "Can't copy terminal attributes"); - } sync_winsize(STDIN_FILENO, script_fds[SFD_SLAVE]); if (!term_raw(STDIN_FILENO, 1)) @@ -342,7 +339,7 @@ script_execv(path, argv) { sigaction_t sa, saveint, savehup, saveterm; sigaction_t savequit, savetstp, savettin, savettou; - int status; + int status, exitcode = 1; pid_t child, pid; parent = getpid(); /* so child can pass signals back to us */ @@ -393,49 +390,57 @@ script_execv(path, argv) /* Wait for signal from child or for child to exit. */ for (;;) { pid = waitpid(child, &status, 0); - if (pid == -1 && errno == EINTR) { - /* Restore old tty settings and signal handler. */ - term_restore(STDIN_FILENO); - switch (signo) { - case SIGINT: - (void) sigaction(SIGINT, &saveint, NULL); - break; - case SIGHUP: - (void) sigaction(SIGHUP, &savehup, NULL); - break; - case SIGQUIT: - (void) sigaction(SIGQUIT, &savequit, NULL); - break; - case SIGTERM: - (void) sigaction(SIGTERM, &saveterm, NULL); - break; - case SIGTSTP: - (void) sigaction(SIGTSTP, &savetstp, NULL); - break; - case SIGTTIN: - (void) sigaction(SIGTTIN, &savettin, NULL); - break; - case SIGTTOU: - (void) sigaction(SIGTTOU, &savettou, NULL); - break; - } - kill(parent, signo); - /* Reinstall signal handler, reset raw mode and continue child */ - (void) sigaction(signo, &sa, NULL); - term_raw(STDIN_FILENO, 1); - killpg(child, SIGCONT); - } else { + if (pid != -1 || errno != EINTR) { + /* headed for exit */ if (pid == child) { if (WIFEXITED(status)) - exit(WEXITSTATUS(status)); + exitcode = WEXITSTATUS(status); if (WIFSIGNALED(status)) - exit(128 | WTERMSIG(status)); + exitcode = WTERMSIG(status) | 128; } break; } + + /* Restore old tty settings and signal handler. */ + term_restore(STDIN_FILENO); + check_sig: + switch (signo) { + case SIGINT: + (void) sigaction(SIGINT, &saveint, NULL); + break; + case SIGHUP: + (void) sigaction(SIGHUP, &savehup, NULL); + break; + case SIGQUIT: + (void) sigaction(SIGQUIT, &savequit, NULL); + break; + case SIGTERM: + (void) sigaction(SIGTERM, &saveterm, NULL); + break; + case SIGTSTP: + (void) sigaction(SIGTSTP, &savetstp, NULL); + break; + case SIGTTIN: + (void) sigaction(SIGTTIN, &savettin, NULL); + break; + case SIGTTOU: + (void) sigaction(SIGTTOU, &savettou, NULL); + break; + default: + /* should not happen */ + continue; + } + kill(parent, signo); /* re-send signal with handler disabled */ + /* Reinstall signal handler, reset raw mode and continue child */ + (void) sigaction(signo, &sa, NULL); + if (!term_raw(STDIN_FILENO, 1) && errno == EINTR) + goto check_sig; + killpg(child, SIGCONT); } - exit(0); + term_restore(STDIN_FILENO); + + exit(exitcode); } void @@ -468,7 +473,6 @@ script_child(path, argv) * Create new session, with the slave as controlling terminal and * point std{in,out,err} to it. */ - warningx("before: pid %d, pgrp %d, sid %d", getpid(), getpgrp(), getsid(0)); /* XXX */ #ifdef HAVE_SETSID if (setsid() == -1) log_error(USE_ERRNO, "setsid"); @@ -479,7 +483,6 @@ script_child(path, argv) if (ioctl(script_fds[SFD_SLAVE], TIOCSCTTY, NULL) != 0) log_error(USE_ERRNO, "unable to set controlling tty"); #endif - warningx("after: pid %d, pgrp %d, sid %d", getpid(), getpgrp(), getsid(0)); /* XXX */ if ((idfile = fdopen(script_fds[SFD_LOG], "w")) == NULL) log_error(USE_ERRNO, "fdopen"); @@ -674,12 +677,10 @@ script_child(path, argv) } while (output.len > output.off); } - term_restore(STDIN_FILENO); - if (WIFEXITED(grandchild_status)) exit(WEXITSTATUS(grandchild_status)); if (WIFSIGNALED(grandchild_status)) - exit(128 | WTERMSIG(grandchild_status)); + exit(WTERMSIG(grandchild_status) | 128); exit(1); } @@ -689,8 +690,6 @@ script_grandchild(path, argv, rbac_enabled) char *argv[]; int rbac_enabled; { - warningx("grandchild: pid %d, pgrp %d, sid %d, tcpgrp %d", getpid(), getpgrp(), getsid(0), tcgetpgrp(script_fds[SFD_SLAVE])); /* XXX */ - dup2(script_fds[SFD_SLAVE], STDIN_FILENO); dup2(script_fds[SFD_SLAVE], STDOUT_FILENO); dup2(script_fds[SFD_SLAVE], STDERR_FILENO); @@ -774,26 +773,9 @@ sigrelay(signo) { int serrno = errno; - /* XXX */ - switch (signo) { - case SIGTSTP: - write(STDERR_FILENO, "SIGTSTP caught\n", 15); - break; - case SIGTTIN: - write(STDERR_FILENO, "SIGTTIN caught\n", 15); - break; - case SIGTTOU: - write(STDERR_FILENO, "SIGTTOU caught\n", 15); - break; - case SIGQUIT: - write(STDERR_FILENO, "SIGQUIT caught\n", 15); - break; - default: - write(STDERR_FILENO, "SIG???? caught\n", 15); - break; - } /* Relay signal back to parent for its tty. */ kill(parent, signo); + /* Suspend self and command, parent will continue us when it is time. */ killpg(getpid(), SIGSTOP); -- 2.40.0