diff options
author | Thomas <thomas@xteddy.org> | 2013-10-11 14:33:29 +0100 |
---|---|---|
committer | Thomas <thomas@xteddy.org> | 2013-10-11 14:33:29 +0100 |
commit | 7f479ffdce8f49f6c57d575b708c4cbe8cbe18df (patch) | |
tree | c0b1ddfb340c9bd59bbc02e83f30bf34aeb29a88 /server-client.c | |
parent | c190c73240576aa2a8274a305844f1fa7fcb0e71 (diff) | |
parent | 4901d9ddc8d8c33ecdca363dcb67e66482745fa5 (diff) | |
download | rtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.tar.gz rtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.tar.bz2 rtmux-7f479ffdce8f49f6c57d575b708c4cbe8cbe18df.zip |
Merge branch 'obsd-master' into mtemp
Diffstat (limited to 'server-client.c')
-rw-r--r-- | server-client.c | 189 |
1 files changed, 117 insertions, 72 deletions
diff --git a/server-client.c b/server-client.c index 5923eb0e..cc18a96f 100644 --- a/server-client.c +++ b/server-client.c @@ -40,9 +40,8 @@ void server_client_reset_state(struct client *); int server_client_assume_paste(struct session *); int server_client_msg_dispatch(struct client *); -void server_client_msg_command(struct client *, struct msg_command_data *); -void server_client_msg_identify( - struct client *, struct msg_identify_data *, int); +void server_client_msg_command(struct client *, struct imsg *); +void server_client_msg_identify(struct client *, struct imsg *); void server_client_msg_shell(struct client *); /* Create a new client. */ @@ -63,6 +62,8 @@ server_client_create(int fd) fatal("gettimeofday failed"); memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); + environ_init(&c->environ); + c->cmdq = cmdq_new(c); c->cmdq->client_exit = 1; @@ -151,6 +152,8 @@ server_client_lost(struct client *c) */ if (c->flags & CLIENT_TERMINAL) tty_free(&c->tty); + free(c->ttyname); + free(c->term); evbuffer_free (c->stdin_data); evbuffer_free (c->stdout_data); @@ -162,6 +165,7 @@ server_client_lost(struct client *c) screen_free(&c->status); free(c->title); + close(c->cwd); evtimer_del(&c->repeat_timer); @@ -179,7 +183,6 @@ server_client_lost(struct client *c) free(c->prompt_string); free(c->prompt_buffer); - free(c->cwd); c->cmdq->dead = 1; cmdq_free(c->cmdq); @@ -695,8 +698,6 @@ server_client_repeat_timer(unused int fd, unused short events, void *data) void server_client_check_exit(struct client *c) { - struct msg_exit_data exitdata; - if (!(c->flags & CLIENT_EXIT)) return; @@ -707,9 +708,7 @@ server_client_check_exit(struct client *c) if (EVBUFFER_LENGTH(c->stderr_data) != 0) return; - exitdata.retcode = c->retcode; - server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata); - + server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval); c->flags &= ~CLIENT_EXIT; } @@ -790,10 +789,8 @@ int server_client_msg_dispatch(struct client *c) { struct imsg imsg; - struct msg_command_data commanddata; - struct msg_identify_data identifydata; - struct msg_environ_data environdata; struct msg_stdin_data stdindata; + const char *data; ssize_t n, datalen; if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) @@ -804,40 +801,37 @@ server_client_msg_dispatch(struct client *c) return (-1); if (n == 0) return (0); + + data = imsg.data; datalen = imsg.hdr.len - IMSG_HEADER_SIZE; if (imsg.hdr.peerid != PROTOCOL_VERSION) { server_write_client(c, MSG_VERSION, NULL, 0); c->flags |= CLIENT_BAD; + if (imsg.fd != -1) + close(imsg.fd); imsg_free(&imsg); continue; } log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd); switch (imsg.hdr.type) { - case MSG_COMMAND: - if (datalen != sizeof commanddata) - fatalx("bad MSG_COMMAND size"); - memcpy(&commanddata, imsg.data, sizeof commanddata); - - server_client_msg_command(c, &commanddata); + case MSG_IDENTIFY_FLAGS: + case MSG_IDENTIFY_TERM: + case MSG_IDENTIFY_TTYNAME: + case MSG_IDENTIFY_CWD: + case MSG_IDENTIFY_STDIN: + case MSG_IDENTIFY_ENVIRON: + case MSG_IDENTIFY_DONE: + server_client_msg_identify(c, &imsg); break; - case MSG_IDENTIFY: - if (datalen != sizeof identifydata) - fatalx("bad MSG_IDENTIFY size"); - memcpy(&identifydata, imsg.data, sizeof identifydata); -#ifdef __CYGWIN__ - imsg.fd = open(identifydata.ttyname, O_RDWR|O_NOCTTY); -#endif - if (imsg.fd == -1) - fatalx("MSG_IDENTIFY missing fd"); - - server_client_msg_identify(c, &identifydata, imsg.fd); + case MSG_COMMAND: + server_client_msg_command(c, &imsg); break; case MSG_STDIN: if (datalen != sizeof stdindata) fatalx("bad MSG_STDIN size"); - memcpy(&stdindata, imsg.data, sizeof stdindata); + memcpy(&stdindata, data, sizeof stdindata); if (c->stdin_callback == NULL) break; @@ -887,23 +881,12 @@ server_client_msg_dispatch(struct client *c) server_redraw_client(c); recalculate_sizes(); break; - case MSG_ENVIRON: - if (datalen != sizeof environdata) - fatalx("bad MSG_ENVIRON size"); - memcpy(&environdata, imsg.data, sizeof environdata); - - environdata.var[(sizeof environdata.var) - 1] = '\0'; - if (strchr(environdata.var, '=') != NULL) - environ_put(&c->environ, environdata.var); - break; case MSG_SHELL: if (datalen != 0) fatalx("bad MSG_SHELL size"); server_client_msg_shell(c); break; - default: - fatalx("unexpected message"); } imsg_free(&imsg); @@ -912,15 +895,26 @@ server_client_msg_dispatch(struct client *c) /* Handle command message. */ void -server_client_msg_command(struct client *c, struct msg_command_data *data) +server_client_msg_command(struct client *c, struct imsg *imsg) { - struct cmd_list *cmdlist = NULL; - int argc; - char **argv, *cause; - - argc = data->argc; - data->argv[(sizeof data->argv) - 1] = '\0'; - if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) { + struct msg_command_data data; + char *buf; + size_t len; + struct cmd_list *cmdlist = NULL; + int argc; + char **argv, *cause; + + if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data) + fatalx("bad MSG_COMMAND size"); + memcpy(&data, imsg->data, sizeof data); + + buf = (char*)imsg->data + sizeof data; + len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data; + if (len > 0 && buf[len - 1] != '\0') + fatalx("bad MSG_COMMAND string"); + + argc = data.argc; + if (cmd_unpack_argv(buf, len, argc, &argv) != 0) { cmdq_error(c->cmdq, "command too long"); goto error; } @@ -951,44 +945,99 @@ error: /* Handle identify message. */ void -server_client_msg_identify( - struct client *c, struct msg_identify_data *data, int fd) +server_client_msg_identify(struct client *c, struct imsg *imsg) { - c->cwd = NULL; - data->cwd[(sizeof data->cwd) - 1] = '\0'; - if (*data->cwd != '\0') - c->cwd = xstrdup(data->cwd); + const char *data; + size_t datalen; + int flags; + + if (c->flags & CLIENT_IDENTIFIED) + fatalx("out-of-order identify message"); + + data = imsg->data; + datalen = imsg->hdr.len - IMSG_HEADER_SIZE; + + switch (imsg->hdr.type) { + case MSG_IDENTIFY_FLAGS: + if (datalen != sizeof flags) + fatalx("bad MSG_IDENTIFY_FLAGS size"); + memcpy(&flags, data, sizeof flags); + c->flags |= flags; + break; + case MSG_IDENTIFY_TERM: + if (datalen == 0 || data[datalen - 1] != '\0') + fatalx("bad MSG_IDENTIFY_TERM string"); + c->term = xstrdup(data); + break; + case MSG_IDENTIFY_TTYNAME: + if (datalen == 0 || data[datalen - 1] != '\0') + fatalx("bad MSG_IDENTIFY_TTYNAME string"); + c->ttyname = xstrdup(data); + break; + case MSG_IDENTIFY_CWD: + if (datalen != 0) + fatalx("bad MSG_IDENTIFY_CWD size"); + c->cwd = imsg->fd; + break; + case MSG_IDENTIFY_STDIN: + if (datalen != 0) + fatalx("bad MSG_IDENTIFY_STDIN size"); + c->fd = imsg->fd; + break; + case MSG_IDENTIFY_ENVIRON: + if (datalen == 0 || data[datalen - 1] != '\0') + fatalx("bad MSG_IDENTIFY_ENVIRON string"); + if (strchr(data, '=') != NULL) + environ_put(&c->environ, data); + break; + default: + break; + } + + if (imsg->hdr.type != MSG_IDENTIFY_DONE) + return; + c->flags |= CLIENT_IDENTIFIED; + +#ifdef __CYGWIN__ + c->fd = open(c->ttyname, O_RDWR|O_NOCTTY); + c->cwd = open(".", O_RDONLY); +#endif - if (data->flags & IDENTIFY_CONTROL) { + if (c->flags & CLIENT_CONTROL) { c->stdin_callback = control_callback; + evbuffer_free(c->stderr_data); c->stderr_data = c->stdout_data; - c->flags |= CLIENT_CONTROL; - if (data->flags & IDENTIFY_TERMIOS) + + if (c->flags & CLIENT_CONTROLCONTROL) evbuffer_add_printf(c->stdout_data, "\033P1000p"); server_write_client(c, MSG_STDIN, NULL, 0); c->tty.fd = -1; c->tty.log_fd = -1; - close(fd); + close(c->fd); + c->fd = -1; + return; } - if (!isatty(fd)) { - close(fd); + if (c->fd == -1) + return; + if (!isatty(c->fd)) { + close(c->fd); + c->fd = -1; return; } - data->term[(sizeof data->term) - 1] = '\0'; - tty_init(&c->tty, c, fd, data->term); - if (data->flags & IDENTIFY_UTF8) + tty_init(&c->tty, c, c->fd, c->term); + if (c->flags & CLIENT_UTF8) c->tty.flags |= TTY_UTF8; - if (data->flags & IDENTIFY_256COLOURS) + if (c->flags & CLIENT_256COLOURS) c->tty.term_flags |= TERM_256COLOURS; tty_resize(&c->tty); - if (!(data->flags & IDENTIFY_CONTROL)) + if (!(c->flags & CLIENT_CONTROL)) c->flags |= CLIENT_TERMINAL; } @@ -996,16 +1045,12 @@ server_client_msg_identify( void server_client_msg_shell(struct client *c) { - struct msg_shell_data data; - const char *shell; + const char *shell; shell = options_get_string(&global_s_options, "default-shell"); - if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; - if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell) - strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell); + server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1); - server_write_client(c, MSG_SHELL, &data, sizeof data); c->flags |= CLIENT_BAD; /* it will die after exec */ } |