diff options
Diffstat (limited to 'server-client.c')
-rw-r--r-- | server-client.c | 261 |
1 files changed, 107 insertions, 154 deletions
diff --git a/server-client.c b/server-client.c index f818c2fe..924bcc04 100644 --- a/server-client.c +++ b/server-client.c @@ -18,6 +18,7 @@ #include <sys/types.h> #include <sys/ioctl.h> +#include <sys/uio.h> #include <errno.h> #include <event.h> @@ -41,10 +42,10 @@ void server_client_set_title(struct client *); 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 imsg *); -void server_client_msg_identify(struct client *, struct imsg *); -void server_client_msg_shell(struct client *); +void server_client_dispatch(struct imsg *, void *); +void server_client_dispatch_command(struct client *, struct imsg *); +void server_client_dispatch_identify(struct client *, struct imsg *); +void server_client_dispatch_shell(struct client *); /* Check if this client is inside this server. */ int @@ -86,8 +87,7 @@ server_client_create(int fd) c = xcalloc(1, sizeof *c); c->references = 1; - imsg_init(&c->ibuf, fd); - server_update_event(c); + c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c); if (gettimeofday(&c->creation_time, NULL) != 0) fatal("gettimeofday failed"); @@ -219,10 +219,8 @@ server_client_lost(struct client *c) environ_free(&c->environ); - close(c->ibuf.fd); - imsg_clear(&c->ibuf); - if (event_initialized(&c->event)) - event_del(&c->event); + proc_remove_peer(c->peer); + c->peer = NULL; server_client_unref(c); @@ -256,40 +254,6 @@ server_client_free(unused int fd, unused short events, void *arg) free(c); } -/* Process a single client event. */ -void -server_client_callback(int fd, short events, void *data) -{ - struct client *c = data; - - if (c->flags & CLIENT_DEAD) - return; - - if (fd == c->ibuf.fd) { - if (events & EV_WRITE && msgbuf_write(&c->ibuf.w) <= 0 && - errno != EAGAIN) - goto client_lost; - - if (c->flags & CLIENT_BAD) { - if (c->ibuf.w.queued == 0) - goto client_lost; - return; - } - - if (events & EV_READ && server_client_msg_dispatch(c) != 0) - goto client_lost; - } - - server_push_stdout(c); - server_push_stderr(c); - - server_update_event(c); - return; - -client_lost: - server_client_lost(c); -} - /* Check for mouse keys. */ int server_client_check_mouse(struct client *c) @@ -524,7 +488,7 @@ server_client_assume_paste(struct session *s) struct timeval tv; int t; - if ((t = options_get_number(&s->options, "assume-paste-time")) == 0) + if ((t = options_get_number(s->options, "assume-paste-time")) == 0) return (0); timersub(&s->activity_time, &s->last_activity_time, &tv); @@ -590,7 +554,7 @@ server_client_handle_key(struct client *c, int key) m->valid = 1; m->key = key; - if (!options_get_number(&s->options, "mouse")) + if (!options_get_number(s->options, "mouse")) goto forward; } else m->valid = 0; @@ -627,7 +591,7 @@ retry: * If this is a repeating key, start the timer. Otherwise reset * the client back to the root table. */ - xtimeout = options_get_number(&s->options, "repeat-time"); + xtimeout = options_get_number(s->options, "repeat-time"); if (xtimeout != 0 && bd->can_repeat) { c->flags |= CLIENT_REPEAT; @@ -669,8 +633,8 @@ retry: * No match, but in the root table. Prefix switches to the prefix table * and everything else is passed through. */ - if (key == options_get_number(&s->options, "prefix") || - key == options_get_number(&s->options, "prefix2")) { + if (key == options_get_number(s->options, "prefix") || + key == options_get_number(s->options, "prefix2")) { server_client_key_table(c, "prefix"); server_status_client(c); return; @@ -757,7 +721,7 @@ server_client_check_focus(struct window_pane *wp) int push; /* Are focus events off? */ - if (!options_get_number(&global_options, "focus-events")) + if (!options_get_number(global_options, "focus-events")) return; /* Do we need to push the focus state? */ @@ -817,7 +781,7 @@ server_client_reset_state(struct client *c) struct window *w = c->session->curw->window; struct window_pane *wp = w->active; struct screen *s = wp->screen; - struct options *oo = &c->session->options; + struct options *oo = c->session->options; int status, mode, o; if (c->flags & CLIENT_SUSPENDED) @@ -889,7 +853,7 @@ server_client_check_exit(struct client *c) if (EVBUFFER_LENGTH(c->stderr_data) != 0) return; - server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval); + proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval); c->flags &= ~CLIENT_EXIT; } @@ -906,7 +870,7 @@ server_client_check_redraw(struct client *c) return; if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) { - if (options_get_number(&s->options, "set-titles")) + if (options_get_number(s->options, "set-titles")) server_client_set_title(c); if (c->message_string != NULL) @@ -966,7 +930,7 @@ server_client_set_title(struct client *c) char *title; struct format_tree *ft; - template = options_get_string(&s->options, "set-titles-string"); + template = options_get_string(s->options, "set-titles-string"); ft = format_create(); format_defaults(ft, c, NULL, NULL, NULL); @@ -983,123 +947,112 @@ server_client_set_title(struct client *c) } /* Dispatch message from client. */ -int -server_client_msg_dispatch(struct client *c) +void +server_client_dispatch(struct imsg *imsg, void *arg) { - struct imsg imsg; + struct client *c = arg; struct msg_stdin_data stdindata; const char *data; - ssize_t n, datalen; + ssize_t datalen; struct session *s; - if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) - return (-1); + if (c->flags & CLIENT_DEAD) + return; - for (;;) { - if ((n = imsg_get(&c->ibuf, &imsg)) == -1) - 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; - } + if (imsg == NULL) { + server_client_lost(c); + return; + } - log_debug("got %u from client %p", imsg.hdr.type, c); - switch (imsg.hdr.type) { - 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_CLIENTPID: - case MSG_IDENTIFY_DONE: - server_client_msg_identify(c, &imsg); - break; - case MSG_COMMAND: - server_client_msg_command(c, &imsg); - break; - case MSG_STDIN: - if (datalen != sizeof stdindata) - fatalx("bad MSG_STDIN size"); - memcpy(&stdindata, data, sizeof stdindata); + data = imsg->data; + datalen = imsg->hdr.len - IMSG_HEADER_SIZE; - if (c->stdin_callback == NULL) - break; - if (stdindata.size <= 0) - c->stdin_closed = 1; - else { - evbuffer_add(c->stdin_data, stdindata.data, - stdindata.size); - } - c->stdin_callback(c, c->stdin_closed, - c->stdin_callback_data); - break; - case MSG_RESIZE: - if (datalen != 0) - fatalx("bad MSG_RESIZE size"); + switch (imsg->hdr.type) { + 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_CLIENTPID: + case MSG_IDENTIFY_DONE: + server_client_dispatch_identify(c, imsg); + break; + case MSG_COMMAND: + server_client_dispatch_command(c, imsg); + break; + case MSG_STDIN: + if (datalen != sizeof stdindata) + fatalx("bad MSG_STDIN size"); + memcpy(&stdindata, data, sizeof stdindata); - if (c->flags & CLIENT_CONTROL) - break; - if (tty_resize(&c->tty)) { - recalculate_sizes(); - server_redraw_client(c); - } + if (c->stdin_callback == NULL) break; - case MSG_EXITING: - if (datalen != 0) - fatalx("bad MSG_EXITING size"); + if (stdindata.size <= 0) + c->stdin_closed = 1; + else { + evbuffer_add(c->stdin_data, stdindata.data, + stdindata.size); + } + c->stdin_callback(c, c->stdin_closed, + c->stdin_callback_data); + break; + case MSG_RESIZE: + if (datalen != 0) + fatalx("bad MSG_RESIZE size"); - c->session = NULL; - tty_close(&c->tty); - server_write_client(c, MSG_EXITED, NULL, 0); + if (c->flags & CLIENT_CONTROL) break; - case MSG_WAKEUP: - case MSG_UNLOCK: - if (datalen != 0) - fatalx("bad MSG_WAKEUP size"); - - if (!(c->flags & CLIENT_SUSPENDED)) - break; - c->flags &= ~CLIENT_SUSPENDED; - - if (c->tty.fd == -1) /* exited in the meantime */ - break; - s = c->session; + if (tty_resize(&c->tty)) { + recalculate_sizes(); + server_redraw_client(c); + } + break; + case MSG_EXITING: + if (datalen != 0) + fatalx("bad MSG_EXITING size"); - if (gettimeofday(&c->activity_time, NULL) != 0) - fatal("gettimeofday failed"); - if (s != NULL) - session_update_activity(s, &c->activity_time); + c->session = NULL; + tty_close(&c->tty); + proc_send(c->peer, MSG_EXITED, -1, NULL, 0); + break; + case MSG_WAKEUP: + case MSG_UNLOCK: + if (datalen != 0) + fatalx("bad MSG_WAKEUP size"); - tty_start_tty(&c->tty); - server_redraw_client(c); - recalculate_sizes(); + if (!(c->flags & CLIENT_SUSPENDED)) break; - case MSG_SHELL: - if (datalen != 0) - fatalx("bad MSG_SHELL size"); + c->flags &= ~CLIENT_SUSPENDED; - server_client_msg_shell(c); + if (c->tty.fd == -1) /* exited in the meantime */ break; - } + s = c->session; + + if (gettimeofday(&c->activity_time, NULL) != 0) + fatal("gettimeofday failed"); + if (s != NULL) + session_update_activity(s, &c->activity_time); + + tty_start_tty(&c->tty); + server_redraw_client(c); + recalculate_sizes(); + break; + case MSG_SHELL: + if (datalen != 0) + fatalx("bad MSG_SHELL size"); - imsg_free(&imsg); + server_client_dispatch_shell(c); + break; } + + server_push_stdout(c); + server_push_stderr(c); } /* Handle command message. */ void -server_client_msg_command(struct client *c, struct imsg *imsg) +server_client_dispatch_command(struct client *c, struct imsg *imsg) { struct msg_command_data data; char *buf; @@ -1152,7 +1105,7 @@ error: /* Handle identify message. */ void -server_client_msg_identify(struct client *c, struct imsg *imsg) +server_client_dispatch_identify(struct client *c, struct imsg *imsg) { const char *data; size_t datalen; @@ -1231,7 +1184,7 @@ server_client_msg_identify(struct client *c, struct imsg *imsg) if (c->flags & CLIENT_CONTROLCONTROL) evbuffer_add_printf(c->stdout_data, "\033P1000p"); - server_write_client(c, MSG_STDIN, NULL, 0); + proc_send(c->peer, MSG_STDIN, -1, NULL, 0); c->tty.fd = -1; c->tty.log_fd = -1; @@ -1262,14 +1215,14 @@ server_client_msg_identify(struct client *c, struct imsg *imsg) /* Handle shell message. */ void -server_client_msg_shell(struct client *c) +server_client_dispatch_shell(struct client *c) { const char *shell; - shell = options_get_string(&global_s_options, "default-shell"); + shell = options_get_string(global_s_options, "default-shell"); if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; - server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1); + proc_send_s(c->peer, MSG_SHELL, shell); - c->flags |= CLIENT_BAD; /* it will die after exec */ + proc_kill_peer(c->peer); } |