diff options
Diffstat (limited to 'qarsh/qarsh.c')
-rw-r--r-- | qarsh/qarsh.c | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/qarsh/qarsh.c b/qarsh/qarsh.c index 0b91f5d..2c709c7 100644 --- a/qarsh/qarsh.c +++ b/qarsh/qarsh.c @@ -5,6 +5,7 @@ * */ +#define _GNU_SOURCE #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -28,6 +29,7 @@ /* Globals */ int qarsh_fd = -1; /* The control connection to qarshd */ +int signal_to_send = 0; void usage() @@ -60,6 +62,12 @@ copyargs(char **argv) } void +sig_handler(int sig) +{ + signal_to_send = sig; +} + +void set_remote_user(char *user, char *group) { struct qa_packet *qp; @@ -90,6 +98,8 @@ run_remote_cmd(char *cmdline) int l_in, l_out, l_err; /* listening sockets */ int c_in, c_out, c_err; /* client sockets */ fd_set readfds, testfds; + sigset_t sigmask, orig_sigmask; + struct sigaction sa; int nset; struct sockaddr_in caddr; socklen_t clen; @@ -160,9 +170,19 @@ run_remote_cmd(char *cmdline) FD_SET(c_out, &readfds); FD_SET(c_err, &readfds); FD_SET(fileno(stdin), &readfds); + /* Setup signal handling stuff so we can propogate signals */ + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); + sigprocmask(SIG_BLOCK, &sigmask, &orig_sigmask); + sa.sa_handler = sig_handler; + sa.sa_mask = sigmask; + sa.sa_flags = SA_RESTART; + sigaction(SIGINT, &sa, NULL); if (fcntl(fileno(stdin), F_SETFL, O_NONBLOCK) != 0) { - fprintf(stderr, "fcntl stdin O_NONBLOCK failed, %d: %s\n", errno, strerror(errno)); + fprintf(stderr, + "fcntl stdin O_NONBLOCK failed, %d: %s\n", + errno, strerror(errno)); } buf = malloc(1024); memset(buf, 0, 1024); @@ -171,47 +191,65 @@ run_remote_cmd(char *cmdline) testfds = readfds; memset(buf, 0, 1024); - nset = select(FD_SETSIZE, &testfds, NULL, NULL, NULL); - if (FD_ISSET(fileno(stdin), &testfds)) { + nset = pselect(FD_SETSIZE, &testfds, NULL, NULL, NULL, + &orig_sigmask); + if (nset == -1 && errno == EINTR) { + nset = 0; + } + + if (signal_to_send) { + qp = make_qp_kill(signal_to_send); + send_packet(qarsh_fd, qp); + qpfree(qp); + signal_to_send = 0; + } + if (nset && FD_ISSET(fileno(stdin), &testfds)) { do { bufsize = read(fileno(stdin), buf, 1024); - write(c_in, buf, bufsize); + if (bufsize > 0) + write(c_in, buf, bufsize); } while (bufsize == 1024); if (bufsize == 0) { FD_CLR(fileno(stdin), &readfds); close(c_in); c_in = 0; } + nset--; } - if (c_out && FD_ISSET(c_out, &testfds)) { + if (nset && c_out && FD_ISSET(c_out, &testfds)) { do { bufsize = read(c_out, buf, 1024); - write(fileno(stdout), buf, bufsize); + if (bufsize > 0) + write(fileno(stdout), buf, bufsize); } while (bufsize == 1024); if (bufsize == 0) { FD_CLR(c_out, &readfds); close(c_out); c_out = 0; } + nset--; } - if (c_err && FD_ISSET(c_err, &testfds)) { + if (nset && c_err && FD_ISSET(c_err, &testfds)) { do { bufsize = read(c_err, buf, 1024); - write(fileno(stderr), buf, bufsize); + if (bufsize > 0) + write(fileno(stderr), buf, bufsize); } while (bufsize == 1024); if (bufsize == 0) { FD_CLR(c_err, &readfds); close(c_err); c_err = 0; } + nset--; } - if (FD_ISSET(qarsh_fd, &testfds)) { + if (nset && FD_ISSET(qarsh_fd, &testfds)) { qp = recv_packet(qarsh_fd); /* dump_qp(qp); */ if (qp && qp->qp_type == QP_CMDEXIT) { break; } + nset--; } } |