diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-09-26 10:35:24 +0000 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2007-09-26 10:35:24 +0000 |
commit | 671694ac3037055c35521f438615e4ce9daafda3 (patch) | |
tree | 7ee663fadd0071e444d00f8b6374a320d869fc02 /server-msg.c | |
parent | 3fef2d998fb0fd1f4fd9f4b96c33816acf523567 (diff) |
Cleanup part 1: split up server.c.
Diffstat (limited to 'server-msg.c')
-rw-r--r-- | server-msg.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/server-msg.c b/server-msg.c new file mode 100644 index 00000000..8bf5af2a --- /dev/null +++ b/server-msg.c @@ -0,0 +1,420 @@ +/* $Id: server-msg.c,v 1.1 2007-09-26 10:35:24 nicm Exp $ */ + +/* + * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "tmux.h" + +void server_msg_fn_attach(struct client *, struct hdr *); +void server_msg_fn_create(struct client *, struct hdr *); +void server_msg_fn_input(struct client *, struct hdr *); +void server_msg_fn_last(struct client *, struct hdr *); +void server_msg_fn_new(struct client *, struct hdr *); +void server_msg_fn_next(struct client *, struct hdr *); +void server_msg_fn_previous(struct client *, struct hdr *); +void server_msg_fn_refresh(struct client *, struct hdr *); +void server_msg_fn_rename(struct client *, struct hdr *); +void server_msg_fn_select(struct client *, struct hdr *); +void server_msg_fn_sessions(struct client *, struct hdr *); +void server_msg_fn_size(struct client *, struct hdr *); +void server_msg_fn_windowlist(struct client *, struct hdr *); +void server_msg_fn_windows(struct client *, struct hdr *); + +struct server_msg { + enum hdrtype type; + + void (*fn)(struct client *, struct hdr *); +}; +struct server_msg server_msg_table[] = { + { MSG_ATTACH, server_msg_fn_attach }, + { MSG_CREATE, server_msg_fn_create }, + { MSG_INPUT, server_msg_fn_input }, + { MSG_LAST, server_msg_fn_last }, + { MSG_NEW, server_msg_fn_new }, + { MSG_NEXT, server_msg_fn_next }, + { MSG_PREVIOUS, server_msg_fn_previous }, + { MSG_REFRESH, server_msg_fn_refresh }, + { MSG_RENAME, server_msg_fn_rename }, + { MSG_SELECT, server_msg_fn_select }, + { MSG_SESSIONS, server_msg_fn_sessions }, + { MSG_SIZE, server_msg_fn_size }, + { MSG_WINDOWLIST, server_msg_fn_windowlist }, + { MSG_WINDOWS, server_msg_fn_windows }, +}; +#define NSERVERMSG (sizeof server_msg_table / sizeof server_msg_table[0]) + +void +server_msg_dispatch(struct client *c) +{ + struct hdr hdr; + struct server_msg *msg; + u_int i; + + if (BUFFER_USED(c->in) < sizeof hdr) + return; + memcpy(&hdr, BUFFER_OUT(c->in), sizeof hdr); + if (BUFFER_USED(c->in) < (sizeof hdr) + hdr.size) + return; + buffer_remove(c->in, sizeof hdr); + + for (i = 0; i < NSERVERMSG; i++) { + msg = server_msg_table + i; + if (msg->type == hdr.type) { + msg->fn(c, &hdr); + return; + } + } + + fatalx("unexpected message"); +} + +/* New message from client. */ +void +server_msg_fn_new(struct client *c, struct hdr *hdr) +{ + struct new_data data; + const char *shell; + char *cmd, *msg; + + if (c->session != NULL) + return; + if (hdr->size != sizeof data) + fatalx("bad MSG_NEW size"); + buffer_read(c->in, &data, hdr->size); + + c->sx = data.sx; + if (c->sx == 0) + c->sx = 80; + c->sy = data.sy; + if (c->sy == 0) + c->sy = 25; + + if (*data.name != '\0' && session_find(data.name) != NULL) { + xasprintf(&msg, "duplicate session: %s", data.name); + write_client(c, MSG_READY, msg, strlen(msg)); + xfree(msg); + return; + } + + shell = getenv("SHELL"); + if (shell == NULL) + shell = "/bin/ksh"; + xasprintf(&cmd, "%s -l", shell); + c->session = session_create(data.name, cmd, c->sx, c->sy); + if (c->session == NULL) + fatalx("session_create failed"); + xfree(cmd); + + write_client(c, MSG_READY, NULL, 0); + draw_client(c, 0, c->sy - 1); +} + +/* Attach message from client. */ +void +server_msg_fn_attach(struct client *c, struct hdr *hdr) +{ + struct attach_data data; + char *msg; + + if (c->session != NULL) + return; + if (hdr->size != sizeof data) + fatalx("bad MSG_ATTACH size"); + buffer_read(c->in, &data, hdr->size); + + c->sx = data.sx; + if (c->sx == 0) + c->sx = 80; + c->sy = data.sy; + if (c->sy == 0) + c->sy = 25; + + if (*data.name != '\0') + c->session = session_find(data.name); + if (c->session == NULL) { + xasprintf(&msg, "session not found: %s", data.name); + write_client(c, MSG_READY, msg, strlen(msg)); + xfree(msg); + return; + } + + write_client(c, MSG_READY, NULL, 0); + draw_client(c, 0, c->sy - 1); +} + +/* Create message from client. */ +void +server_msg_fn_create(struct client *c, struct hdr *hdr) +{ + const char *shell; + char *cmd; + + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_CREATE size"); + + shell = getenv("SHELL"); + if (shell == NULL) + shell = "/bin/ksh"; + xasprintf(&cmd, "%s -l", shell); + if (session_new(c->session, cmd, c->sx, c->sy) != 0) + fatalx("session_new failed"); + xfree(cmd); + + draw_client(c, 0, c->sy - 1); +} + +/* Next message from client. */ +void +server_msg_fn_next(struct client *c, struct hdr *hdr) +{ + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_NEXT size"); + + if (session_next(c->session) == 0) + changed_window(c); + else + write_message(c, "No next window"); +} + +/* Previous message from client. */ +void +server_msg_fn_previous(struct client *c, struct hdr *hdr) +{ + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_PREVIOUS size"); + + if (session_previous(c->session) == 0) + changed_window(c); + else + write_message(c, "No previous window"); +} + +/* Size message from client. */ +void +server_msg_fn_size(struct client *c, struct hdr *hdr) +{ + struct size_data data; + + if (c->session == NULL) + return; + if (hdr->size != sizeof data) + fatalx("bad MSG_SIZE size"); + buffer_read(c->in, &data, hdr->size); + + c->sx = data.sx; + if (c->sx == 0) + c->sx = 80; + c->sy = data.sy; + if (c->sy == 0) + c->sy = 25; + + if (window_resize(c->session->window, c->sx, c->sy) != 0) + draw_client(c, 0, c->sy - 1); +} + +/* Input message from client. */ +void +server_msg_fn_input(struct client *c, struct hdr *hdr) +{ + if (c->session == NULL) + return; + + window_input(c->session->window, c->in, hdr->size); +} + +/* Refresh message from client. */ +void +server_msg_fn_refresh(struct client *c, struct hdr *hdr) +{ + struct refresh_data data; + + if (c->session == NULL) + return; + if (hdr->size != 0 && hdr->size != sizeof data) + fatalx("bad MSG_REFRESH size"); + + draw_client(c, 0, c->sy - 1); +} + +/* Select message from client. */ +void +server_msg_fn_select(struct client *c, struct hdr *hdr) +{ + struct select_data data; + + if (c->session == NULL) + return; + if (hdr->size != sizeof data) + fatalx("bad MSG_SELECT size"); + buffer_read(c->in, &data, hdr->size); + + if (c->session == NULL) + return; + if (session_select(c->session, data.idx) == 0) + changed_window(c); + else + write_message(c, "Window %u not present", data.idx); +} + +/* Sessions message from client. */ +void +server_msg_fn_sessions(struct client *c, struct hdr *hdr) +{ + struct sessions_data data; + struct sessions_entry entry; + struct session *s; + u_int i, j; + + if (hdr->size != sizeof data) + fatalx("bad MSG_SESSIONS size"); + buffer_read(c->in, &data, hdr->size); + + data.sessions = 0; + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + if (ARRAY_ITEM(&sessions, i) != NULL) + data.sessions++; + } + write_client2(c, MSG_SESSIONS, + &data, sizeof data, NULL, data.sessions * sizeof entry); + + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + s = ARRAY_ITEM(&sessions, i); + if (s == NULL) + continue; + strlcpy(entry.name, s->name, sizeof entry.name); + entry.tim = s->tim; + entry.windows = 0; + for (j = 0; j < ARRAY_LENGTH(&s->windows); j++) { + if (ARRAY_ITEM(&s->windows, j) != NULL) + entry.windows++; + } + buffer_write(c->out, &entry, sizeof entry); + } +} + +/* Windows message from client. */ +void +server_msg_fn_windows(struct client *c, struct hdr *hdr) +{ + struct windows_data data; + struct windows_entry entry; + struct session *s; + struct window *w; + u_int i; + + if (hdr->size != sizeof data) + fatalx("bad MSG_WINDOWS size"); + buffer_read(c->in, &data, hdr->size); + + s = session_find(data.name); + if (s == NULL) { + data.windows = 0; + write_client(c, MSG_WINDOWS, &data, sizeof data); + return; + } + + data.windows = 0; + for (i = 0; i < ARRAY_LENGTH(&s->windows); i++) { + if (ARRAY_ITEM(&windows, i) != NULL) + data.windows++; + } + write_client2(c, MSG_WINDOWS, + &data, sizeof data, NULL, data.windows * sizeof entry); + + for (i = 0; i < ARRAY_LENGTH(&windows); i++) { + w = ARRAY_ITEM(&windows, i); + if (w == NULL) + continue; + entry.idx = i; + strlcpy(entry.name, w->name, sizeof entry.name); + strlcpy(entry.title, w->screen.title, sizeof entry.title); + if (ttyname_r(w->fd, entry.tty, sizeof entry.tty) != 0) + *entry.tty = '\0'; + buffer_write(c->out, &entry, sizeof entry); + } +} + +/* Rename message from client. */ +void +server_msg_fn_rename(struct client *c, struct hdr *hdr) +{ + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_RENAME size"); + + fatalx("not implemented"); +} + +/* Last window message from client */ +void +server_msg_fn_last(struct client *c, struct hdr *hdr) +{ + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_LAST size"); + + if (session_last(c->session) == 0) + changed_window(c); + else + write_message(c, "No last window"); +} + +/* Window list message from client */ +void +server_msg_fn_windowlist(struct client *c, struct hdr *hdr) +{ + struct window *w; + char *buf; + size_t len, off; + u_int i; + + if (c->session == NULL) + return; + if (hdr->size != 0) + fatalx("bad MSG_WINDOWLIST size"); + + len = c->sx + 1; + buf = xmalloc(len); + off = 0; + + *buf = '\0'; + for (i = 0; i < ARRAY_LENGTH(&c->session->windows); i++) { + w = ARRAY_ITEM(&c->session->windows, i); + if (w == NULL) + continue; + off += xsnprintf(buf + off, len - off, "%u:%s%s ", i, w->name, + w == c->session->window ? "*" : ""); + if (off >= len) + break; + } + + write_message(c, "%s", buf); + xfree(buf); +} |