version 1.1.1.4, 2013/07/22 10:46:13
|
version 1.1.1.5, 2013/10/14 07:56:35
|
Line 515 dispatch_signals(int sv[2], pid_t child, int log_io, s
|
Line 515 dispatch_signals(int sv[2], pid_t child, int log_io, s
|
* select() notification. |
* select() notification. |
*/ |
*/ |
(void) shutdown(sv[0], SHUT_WR); |
(void) shutdown(sv[0], SHUT_WR); |
} else { | } else if (WIFSTOPPED(status)) { |
if (WIFSTOPPED(status)) { | /* |
| * Save the controlling terminal's process group |
| * so we can restore it after we resume, if needed. |
| * Most well-behaved shells change the pgrp back to |
| * its original value before suspending so we must |
| * not try to restore in that case, lest we race with |
| * the child upon resume, potentially stopping sudo |
| * with SIGTTOU while the command continues to run. |
| */ |
| sigaction_t sa, osa; |
| pid_t saved_pgrp = (pid_t)-1; |
| int signo = WSTOPSIG(status); |
| int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0); |
| if (fd != -1) { |
| saved_pgrp = tcgetpgrp(fd); |
/* |
/* |
* Save the controlling terminal's process group | * Child was stopped trying to access controlling |
* so we can restore it after we resume, if needed. | * terminal. If the child has a different pgrp |
* Most well-behaved shells change the pgrp back to | * and we own the controlling terminal, give it |
* its original value before suspending so we must | * to the child's pgrp and let it continue. |
* not try to restore in that case, lest we race with | |
* the child upon resume, potentially stopping sudo | |
* with SIGTTOU while the command continues to run. | |
*/ |
*/ |
sigaction_t sa, osa; | if (signo == SIGTTOU || signo == SIGTTIN) { |
pid_t saved_pgrp = (pid_t)-1; | if (saved_pgrp == ppgrp) { |
int signo = WSTOPSIG(status); | pid_t child_pgrp = getpgid(child); |
int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0); | if (child_pgrp != ppgrp) { |
if (fd != -1) { | if (tcsetpgrp(fd, child_pgrp) == 0) { |
if ((saved_pgrp = tcgetpgrp(fd)) == ppgrp) | if (killpg(child_pgrp, SIGCONT) != 0) { |
saved_pgrp = -1; | warning("kill(%d, SIGCONT)", |
| (int)child_pgrp); |
| } |
| close(fd); |
| debug_return_int(1); |
| } |
| } |
| } |
} |
} |
if (signo == SIGTSTP) { |
|
memset(&sa, 0, sizeof(sa)); |
|
sigemptyset(&sa.sa_mask); |
|
sa.sa_flags = SA_RESTART; |
|
sa.sa_handler = SIG_DFL; |
|
sudo_sigaction(SIGTSTP, &sa, &osa); |
|
} |
|
if (kill(getpid(), signo) != 0) |
|
warning("kill(%d, SIG%s)", (int)getpid(), signame); |
|
if (signo == SIGTSTP) |
|
sudo_sigaction(SIGTSTP, &osa, NULL); |
|
if (fd != -1) { |
|
/* |
|
* Restore command's process group if different. |
|
* Otherwise, we cannot resume some shells. |
|
*/ |
|
if (saved_pgrp != (pid_t)-1) |
|
(void)tcsetpgrp(fd, saved_pgrp); |
|
close(fd); |
|
} |
|
} else { |
|
/* Child has exited, we are done. */ |
|
cstat->type = CMD_WSTATUS; |
|
cstat->val = status; |
|
debug_return_int(0); |
|
} |
} |
|
if (signo == SIGTSTP) { |
|
memset(&sa, 0, sizeof(sa)); |
|
sigemptyset(&sa.sa_mask); |
|
sa.sa_flags = SA_RESTART; |
|
sa.sa_handler = SIG_DFL; |
|
sudo_sigaction(SIGTSTP, &sa, &osa); |
|
} |
|
if (kill(getpid(), signo) != 0) |
|
warning("kill(%d, SIG%s)", (int)getpid(), signame); |
|
if (signo == SIGTSTP) |
|
sudo_sigaction(SIGTSTP, &osa, NULL); |
|
if (fd != -1) { |
|
/* |
|
* Restore command's process group if different. |
|
* Otherwise, we cannot resume some shells. |
|
*/ |
|
if (saved_pgrp != ppgrp) |
|
(void)tcsetpgrp(fd, saved_pgrp); |
|
close(fd); |
|
} |
|
} else { |
|
/* Child has exited or been killed, we are done. */ |
|
cstat->type = CMD_WSTATUS; |
|
cstat->val = status; |
|
debug_return_int(0); |
} |
} |
} |
} |
} else { |
} else { |