diff options
Diffstat (limited to 'src/utils/lib/pty-session.c')
-rw-r--r-- | src/utils/lib/pty-session.c | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/src/utils/lib/pty-session.c b/src/utils/lib/pty-session.c index 06b2a49..f4bb004 100644 --- a/src/utils/lib/pty-session.c +++ b/src/utils/lib/pty-session.c @@ -340,12 +340,17 @@ static int handle_io(struct ul_pty *pty, int fd, int *eof) char buf[BUFSIZ]; ssize_t bytes; int rc = 0; + sigset_t set; DBG(IO, ul_debugobj(pty, " handle I/O on fd=%d", fd)); *eof = 0; + sigemptyset(&set); + sigaddset(&set, SIGTTIN); + sigprocmask(SIG_UNBLOCK, &set, NULL); /* read from active FD */ bytes = read(fd, buf, sizeof(buf)); + sigprocmask(SIG_BLOCK, &set, NULL); if (bytes < 0) { if (errno == EAGAIN || errno == EINTR) return 0; @@ -409,8 +414,8 @@ void ul_pty_wait_for_child(struct ul_pty *pty) } } else { /* final wait */ - while ((pid = wait3(&status, options, NULL)) > 0) { - DBG(SIG, ul_debug(" wait3 done [rc=%d]", (int) pid)); + while ((pid = waitpid(-1, &status, options)) > 0) { + DBG(SIG, ul_debug(" waitpid done [rc=%d]", (int) pid)); if (pid == pty->child) { if (pty->callbacks.child_die) pty->callbacks.child_die( @@ -451,9 +456,10 @@ static int handle_signal(struct ul_pty *pty, int fd) else ul_pty_wait_for_child(pty); - } else if (info.ssi_status == SIGSTOP && pty->child > 0) + } else if (info.ssi_status == SIGSTOP && pty->child > 0) { pty->callbacks.child_sigstop(pty->callback_data, pty->child); + } if (pty->child <= 0) { DBG(SIG, ul_debugobj(pty, " no child, setting leaving timeout")); @@ -571,16 +577,15 @@ int ul_pty_proxy_master(struct ul_pty *pty) rc = mainloop_callback(pty); if (rc == 0) continue; - } else + } else { rc = 0; + } DBG(IO, ul_debugobj(pty, "leaving poll() loop [timeout=%d, rc=%d]", timeout, rc)); break; } /* event */ for (i = 0; i < ARRAY_SIZE(pfd); i++) { - rc = 0; - if (pfd[i].revents == 0) continue; @@ -594,34 +599,42 @@ int ul_pty_proxy_master(struct ul_pty *pty) pfd[i].revents & POLLERR ? "POLLERR" : "", pfd[i].revents & POLLNVAL ? "POLLNVAL" : "")); - switch (i) { - case POLLFD_STDIN: - case POLLFD_MASTER: - /* data */ - if (pfd[i].revents & POLLIN) - rc = handle_io(pty, pfd[i].fd, &eof); - /* EOF maybe detected in two ways; they are as follows: - * A) poll() return POLLHUP event after close() - * B) read() returns 0 (no data) - * - * POLLNVAL means that fd is closed. - */ - if ((pfd[i].revents & POLLHUP) || (pfd[i].revents & POLLNVAL) || eof) { - DBG(IO, ul_debugobj(pty, " ignore FD")); - pfd[i].fd = -1; - if (i == POLLFD_STDIN) { - ul_pty_write_eof_to_child(pty); - DBG(IO, ul_debugobj(pty, " ignore STDIN")); - } - } - continue; - case POLLFD_SIGNAL: + if (i == POLLFD_SIGNAL) rc = handle_signal(pty, pfd[i].fd); + else if (pfd[i].revents & POLLIN) + rc = handle_io(pty, pfd[i].fd, &eof); /* data */ + + if (rc) { + ul_pty_write_eof_to_child(pty); break; } - if (rc) - break; + + if (i == POLLFD_SIGNAL) + continue; + + /* EOF maybe detected in two ways; they are as follows: + * A) poll() return POLLHUP event after close() + * B) read() returns 0 (no data) + * + * POLLNVAL means that fd is closed. + */ + if ((pfd[i].revents & POLLHUP) || (pfd[i].revents & POLLNVAL) || eof) { + DBG(IO, ul_debugobj(pty, " ignore FD")); + pfd[i].fd = -1; + if (i == POLLFD_STDIN) { + ul_pty_write_eof_to_child(pty); + DBG(IO, ul_debugobj(pty, " ignore STDIN")); + } + } } + if (rc) + break; + } + + if (rc && pty->child && pty->child != (pid_t) -1 && !pty->delivered_signal) { + kill(pty->child, SIGTERM); + sleep(2); + kill(pty->child, SIGKILL); } pty_signals_cleanup(pty); @@ -686,9 +699,9 @@ int main(int argc, char *argv[]) shname = shname ? shname + 1 : shell; if (command) - execl(shell, shname, "-c", command, NULL); + execl(shell, shname, "-c", command, (char *)NULL); else - execl(shell, shname, "-i", NULL); + execl(shell, shname, "-i", (char *)NULL); err(EXIT_FAILURE, "failed to execute %s", shell); break; |