summaryrefslogtreecommitdiffstats
path: root/qarsh/qarsh.c
diff options
context:
space:
mode:
Diffstat (limited to 'qarsh/qarsh.c')
-rw-r--r--qarsh/qarsh.c56
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--;
}
}