diff options
Diffstat (limited to 'client.c')
-rw-r--r-- | client.c | 64 |
1 files changed, 49 insertions, 15 deletions
@@ -35,6 +35,7 @@ struct imsgbuf client_ibuf; struct event client_event; +struct event client_stdin; enum { CLIENT_EXIT_NONE, CLIENT_EXIT_DETACHED, @@ -56,6 +57,7 @@ void client_send_environ(void); void client_write_server(enum msgtype, void *, size_t); void client_update_event(void); void client_signal(int, short, void *); +void client_stdin_callback(int, short, void *); void client_callback(int, short, void *); int client_dispatch_attached(void); int client_dispatch_wait(void *); @@ -229,6 +231,11 @@ client_main(int argc, char **argv, int flags) imsg_init(&client_ibuf, fd); event_set(&client_event, fd, EV_READ, client_callback, shell_cmd); + /* Create stdin handler. */ + setblocking(STDIN_FILENO, 0); + event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST, + client_stdin_callback, NULL); + /* Establish signal handlers. */ set_signals(client_signal); @@ -257,6 +264,7 @@ client_main(int argc, char **argv, int flags) /* Set the event and dispatch. */ client_update_event(); + event_add (&client_stdin, NULL); event_dispatch(); /* Print the exit message, if any, and exit. */ @@ -268,6 +276,7 @@ client_main(int argc, char **argv, int flags) if (client_exittype == MSG_DETACHKILL && ppid > 1) kill(ppid, SIGHUP); } + setblocking(STDIN_FILENO, 1); return (client_exitval); } @@ -289,20 +298,11 @@ client_send_identify(int flags) strlcpy(data.term, term, sizeof data.term) >= sizeof data.term) *data.term = '\0'; - if ((fd = dup(STDOUT_FILENO)) == -1) - fatal("dup failed"); - imsg_compose(&client_ibuf, - MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0); - - if ((fd = dup(STDERR_FILENO)) == -1) - fatal("dup failed"); - imsg_compose(&client_ibuf, - MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0); - if ((fd = dup(STDIN_FILENO)) == -1) fatal("dup failed"); imsg_compose(&client_ibuf, MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data); + client_update_event(); } /* Forward entire environment to server. */ @@ -324,6 +324,7 @@ void client_write_server(enum msgtype type, void *buf, size_t len) { imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len); + client_update_event(); } /* Update client event based on whether it needs to read or read and write. */ @@ -423,6 +424,23 @@ lost_server: event_loopexit(NULL); } +/* Callback for client stdin read events. */ +/* ARGSUSED */ +void +client_stdin_callback(unused int fd, unused short events, unused void *data1) +{ + struct msg_stdin_data data; + + data.size = read(STDIN_FILENO, data.data, sizeof data.data); + if (data.size < 0 && (errno == EINTR || errno == EAGAIN)) + return; + + client_write_server(MSG_STDIN, &data, sizeof data); + if (data.size <= 0) + event_del(&client_stdin); + client_update_event(); +} + /* Dispatch imsgs when in wait state (before MSG_READY). */ int client_dispatch_wait(void *data) @@ -431,11 +449,10 @@ client_dispatch_wait(void *data) ssize_t n, datalen; struct msg_shell_data shelldata; struct msg_exit_data exitdata; + struct msg_stdout_data stdoutdata; + struct msg_stderr_data stderrdata; const char *shellcmd = data; - if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) - fatalx("imsg_read failed"); - for (;;) { if ((n = imsg_get(&client_ibuf, &imsg)) == -1) fatalx("imsg_get failed"); @@ -443,6 +460,7 @@ client_dispatch_wait(void *data) return (0); datalen = imsg.hdr.len - IMSG_HEADER_SIZE; + log_debug("got %d from server", imsg.hdr.type); switch (imsg.hdr.type) { case MSG_EXIT: case MSG_SHUTDOWN: @@ -459,14 +477,30 @@ client_dispatch_wait(void *data) if (datalen != 0) fatalx("bad MSG_READY size"); + event_del(&client_stdin); client_attached = 1; break; + case MSG_STDOUT: + if (datalen != sizeof stdoutdata) + fatalx("bad MSG_STDOUT"); + memcpy(&stdoutdata, imsg.data, sizeof stdoutdata); + + fwrite(stdoutdata.data, stdoutdata.size, 1, stdout); + break; + case MSG_STDERR: + if (datalen != sizeof stderrdata) + fatalx("bad MSG_STDERR"); + memcpy(&stderrdata, imsg.data, sizeof stderrdata); + + fwrite(stderrdata.data, stderrdata.size, 1, stderr); + break; case MSG_VERSION: if (datalen != 0) fatalx("bad MSG_VERSION size"); - log_warnx("protocol version mismatch (client %u, " - "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid); + fprintf(stderr, "protocol version mismatch " + "(client %u, server %u)\n", PROTOCOL_VERSION, + imsg.hdr.peerid); client_exitval = 1; imsg_free(&imsg); |