diff options
author | Nate Straz <nstraz@redhat.com> | 2005-08-24 23:12:22 +0000 |
---|---|---|
committer | Nate Straz <nstraz@redhat.com> | 2005-08-24 23:12:22 +0000 |
commit | 468d9d0d5dd436b6280639850449a38f48715894 (patch) | |
tree | 11097eec4886099a81ad9d478e5ea85e7d66209d /qarsh/qarshd.c | |
parent | e48b3f4d5002deced980f5ef8e1c4fe3eb884fbc (diff) | |
download | qarsh-468d9d0d5dd436b6280639850449a38f48715894.tar.gz qarsh-468d9d0d5dd436b6280639850449a38f48715894.tar.xz qarsh-468d9d0d5dd436b6280639850449a38f48715894.zip |
Initial pass at signal propogation. Only SIGINT is passed along at this point.
Diffstat (limited to 'qarsh/qarshd.c')
-rw-r--r-- | qarsh/qarshd.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/qarsh/qarshd.c b/qarsh/qarshd.c index d443704..bf8353b 100644 --- a/qarsh/qarshd.c +++ b/qarsh/qarshd.c @@ -1,4 +1,5 @@ +#define _GNU_SOURCE #include <stdio.h> #include <errno.h> #include <unistd.h> @@ -25,6 +26,7 @@ /* Globals */ struct sockaddr_in peername; +int child_exitted = 0; int setup_user(char *user, char *group) @@ -49,6 +51,12 @@ setup_user(char *user, char *group) return 1; } +void +sig_handler(int sig) +{ + if (sig == SIGCHLD) child_exitted++; +} + pid_t run_cmd(const char *cmd, int p_in, int p_out, int p_err) { @@ -113,20 +121,40 @@ handle_packets(int infd) { fd_set rfds; int nfd; - struct timeval timeout; + struct timespec timeout; struct qa_packet *qp = NULL, *rp = NULL; + sigset_t sigmask, orig_sigmask; + struct sigaction sa; pid_t child_pid = 0; int child_status; + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigmask, &orig_sigmask); + sa.sa_handler = sig_handler; + sa.sa_mask = sigmask; + sa.sa_flags = SA_RESTART; + sigaction(SIGCHLD, &sa, NULL); + for (;;) { FD_SET(infd, &rfds); timeout.tv_sec = 5; - timeout.tv_usec = 0; - nfd = select(infd+1, &rfds, NULL, NULL, &timeout); + nfd = pselect(infd+1, &rfds, NULL, NULL, &timeout, + &orig_sigmask); if (nfd < 0) { - syslog(LOG_ERR, "select errno %d, %s\n", errno, strerror(errno)); + if (errno == EINTR) { + /* Handle signals here */ + if (child_exitted) { + waitpid(child_pid, &child_status, 0); + rp = make_qp_cmdexit(child_pid, child_status); + send_packet(fileno(stdout), rp); + qpfree(rp); + } + } else { + syslog(LOG_ERR, "select errno %d, %s\n", errno, strerror(errno)); + } } else if (nfd > 0) { qp = recv_packet(infd); if (qp == NULL) { @@ -134,6 +162,14 @@ handle_packets(int infd) break; } switch (qp->qp_type) { + case QP_KILL: + if (child_pid) { + + syslog(LOG_INFO, "Sending child %d signal %d", + child_pid, qp->qp_kill.qp_sig); + kill(child_pid, qp->qp_kill.qp_sig); + } + break; case QP_SETUSER: if (setup_user(qp->qp_setuser.qp_user, qp->qp_setuser.qp_group) == 0) { @@ -149,10 +185,6 @@ handle_packets(int infd) qp->qp_runcmd.qp_stdin_port, qp->qp_runcmd.qp_stdout_port, qp->qp_runcmd.qp_stderr_port); - waitpid(child_pid, &child_status, 0); - rp = make_qp_cmdexit(child_pid, child_status); - send_packet(fileno(stdout), rp); - qpfree(rp); break; default: syslog(LOG_WARNING, |