diff options
Diffstat (limited to 'server.c')
-rw-r--r-- | server.c | 770 |
1 files changed, 3 insertions, 767 deletions
@@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.11 2007-09-22 11:50:33 nicm Exp $ */ +/* $Id: server.c,v 1.12 2007-09-26 10:35:24 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -50,34 +50,7 @@ void fill_clients(struct pollfd **); void handle_clients(struct pollfd **); struct client *accept_client(int); void lost_client(struct client *); -void user_start(struct client *, const char *, const char *, - size_t, void (*)(struct client *, const char *)); -void user_input(struct client *, size_t); -void write_message(struct client *, const char *, ...); -void write_client(struct client *, u_int, void *, size_t); -void write_client2( - struct client *, u_int, void *, size_t, void *, size_t); -void write_clients(struct window *, u_int, void *, size_t); -void new_window(struct window *); -void lost_window(struct window *); -void changed_window(struct client *); -void draw_client(struct client *, u_int, u_int); -void process_client(struct client *); -void process_new_msg(struct client *, struct hdr *); -void process_attach_msg(struct client *, struct hdr *); -void process_create_msg(struct client *, struct hdr *); -void process_next_msg(struct client *, struct hdr *); -void process_previous_msg(struct client *, struct hdr *); -void process_select_msg(struct client *, struct hdr *); -void process_size_msg(struct client *, struct hdr *); -void process_input_msg(struct client *, struct hdr *); -void process_refresh_msg(struct client *, struct hdr *); -void process_sessions_msg(struct client *, struct hdr *); -void process_windows_msg(struct client *, struct hdr *); -void process_rename_msg(struct client *, struct hdr *); -void process_last_msg(struct client *, struct hdr *); -void process_windowlist_msg(struct client *, struct hdr *); -void rename_callback(struct client *, const char *); +void lost_window(struct window *); /* Fork and start server process. */ int @@ -302,7 +275,7 @@ handle_clients(struct pollfd *(*pfd)) if (buffer_poll((*pfd), c->in, c->out) != 0) lost_client(c); else - process_client(c); + server_msg_dispatch(c); } (*pfd)++; } @@ -334,7 +307,6 @@ accept_client(int srv_fd) c->in = buffer_create(BUFSIZ); c->out = buffer_create(BUFSIZ); c->session = NULL; - c->prompt = NULL; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { if (ARRAY_ITEM(&clients, i) == NULL) { @@ -363,302 +335,6 @@ lost_client(struct client *c) xfree(c); } -/* Write message command to a client. */ -void -write_message(struct client *c, const char *fmt, ...) -{ - struct hdr hdr; - va_list ap; - char *msg; - size_t size; - u_int i; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - input_store_zero(c->out, CODE_CURSOROFF); - input_store_two(c->out, CODE_CURSORMOVE, c->sy, 1); - input_store_one(c->out, CODE_ATTRIBUTES, 2); - input_store16(c->out, 0); - input_store16(c->out, 7); - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); - buffer_write(c->out, msg, strlen(msg)); - for (i = strlen(msg); i < c->sx; i++) - input_store8(c->out, ' '); - xfree(msg); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_OUTPUT; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - - hdr.type = MSG_PAUSE; - hdr.size = 0; - buffer_write(c->out, &hdr, sizeof hdr); - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw(&c->session->window->screen, c->out, c->sy - 1, c->sy - 1); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_OUTPUT; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); -} - -/* Start user input. */ -void -user_start(struct client *c, const char *prompt, const char *now, - size_t len, void (*callback)(struct client *, const char *)) -{ - struct hdr hdr; - size_t size; - u_int i; - - c->callback = callback; - c->prompt = prompt; - - c->len = len; - if (c->len > c->sx - strlen(c->prompt)) - c->len = c->sx - strlen(c->prompt); - c->buf = xmalloc(c->len + 1); - strlcpy(c->buf, now, c->len + 1); - c->idx = strlen(c->buf); - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - input_store_zero(c->out, CODE_CURSOROFF); - input_store_two(c->out, CODE_CURSORMOVE, c->sy, 1); - input_store_one(c->out, CODE_ATTRIBUTES, 2); - input_store16(c->out, 0); - input_store16(c->out, 7); - - i = 0; - buffer_write(c->out, c->prompt, strlen(c->prompt)); - i += strlen(c->prompt); - if (*c->buf != '\0') { - buffer_write(c->out, c->buf, strlen(c->buf)); - i += strlen(c->buf); - } - for (; i < c->sx; i++) - input_store8(c->out, ' '); - - input_store_two(c->out, - CODE_CURSORMOVE, c->sy, 1 + strlen(c->prompt) + c->idx); - input_store_zero(c->out, CODE_CURSORON); - - size = BUFFER_USED(c->out) - size; - hdr.type = MSG_OUTPUT; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); -} - -/* Handle user input. */ -void -user_input(struct client *c, size_t in) -{ - struct hdr hdr; - size_t size; - int key; - u_int i; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - while (in != 0) { - if (in < 1) - break; - in--; - key = input_extract8(c->in); - if (key == '\e') { - if (in < 2) - fatalx("underflow"); - in -= 2; - key = (int16_t) input_extract16(c->in); - } - - again: - if (key == '\r') { - screen_draw(&c->session->window->screen, - c->out, c->sy - 1, c->sy - 1); - - c->callback(c, c->buf); - c->prompt = NULL; - xfree(c->buf); - break; - } - - switch (key) { - case KEYC_LEFT: - if (c->idx > 0) - c->idx--; - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - break; - case KEYC_RIGHT: - if (c->idx < strlen(c->buf)) - c->idx++; - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - break; - case KEYC_HOME: - c->idx = 0; - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - break; - case KEYC_LL: - c->idx = strlen(c->buf); - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - break; - case KEYC_BACKSPACE: - if (c->idx == 0) - break; - if (strlen(c->buf) == 0) - break; - if (c->idx == strlen(c->buf)) - c->buf[c->idx - 1] = '\0'; - else { - memmove(c->buf + c->idx - 1, - c->buf + c->idx, c->len - c->idx); - } - c->idx--; - input_store_one(c->out, CODE_CURSORLEFT, 1); - input_store_one(c->out, CODE_DELETECHARACTER, 1); - input_store_zero(c->out, CODE_CURSOROFF); - input_store_two(c->out, CODE_CURSORMOVE, c->sy, c->sx); - input_store8(c->out, ' '); - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - input_store_zero(c->out, CODE_CURSORON); - break; - case KEYC_DC: - if (strlen(c->buf) == 0) - break; - if (c->idx == strlen(c->buf)) - break; - memmove(c->buf + c->idx, - c->buf + c->idx + 1, c->len - c->idx - 1); - input_store_one(c->out, CODE_DELETECHARACTER, 1); - input_store_zero(c->out, CODE_CURSOROFF); - input_store_two(c->out,CODE_CURSORMOVE, c->sy, c->sx); - input_store8(c->out, ' '); - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - input_store_zero(c->out, CODE_CURSORON); - break; - default: - if (key >= ' ' && key != '\177') { - if (c->idx == c->len) - break; - if (strlen(c->buf) == c->len) - break; - memmove(c->buf + c->idx + 1, - c->buf + c->idx, c->len - c->idx); - c->buf[c->idx++] = key; - input_store_one( - c->out, CODE_INSERTCHARACTER, 1); - input_store8(c->out, key); - break; - } - switch (key) { - case '\001': - key = KEYC_HOME; - goto again; - case '\005': - key = KEYC_LL; - goto again; - case '\010': - key = KEYC_BACKSPACE; - goto again; - case '\177': - key = KEYC_DC; - goto again; - case '\013': - c->buf[c->idx + 1] = '\0'; - input_store_zero(c->out, CODE_CURSOROFF); - i = 1 + strlen(c->prompt) + c->idx; - for (; i < c->sx; i++) - input_store8(c->out, ' '); - input_store_two(c->out, CODE_CURSORMOVE, - c->sy, 1 + strlen(c->prompt) + c->idx); - input_store_zero(c->out, CODE_CURSORON); - break; - } - } - } - - size = BUFFER_USED(c->out) - size; - if (size != 0) { - hdr.type = MSG_OUTPUT; - hdr.size = size; - memcpy(BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } else - buffer_reverse_add(c->out, sizeof hdr); -} - -/* Write command to a client. */ -void -write_client(struct client *c, u_int cmd, void *buf, size_t len) -{ - struct hdr hdr; - - hdr.type = cmd; - hdr.size = len; - - buffer_write(c->out, &hdr, sizeof hdr); - if (buf != NULL) - buffer_write(c->out, buf, len); -} - -/* Write command to a client with two buffers. */ -void -write_client2(struct client *c, - u_int cmd, void *buf1, size_t len1, void *buf2, size_t len2) -{ - struct hdr hdr; - - hdr.type = cmd; - hdr.size = len1 + len2; - - buffer_write(c->out, &hdr, sizeof hdr); - if (buf1 != NULL) - buffer_write(c->out, buf1, len1); - if (buf2 != NULL) - buffer_write(c->out, buf2, len2); -} - -/* Write command to all clients attached to a specific window. */ -void -write_clients(struct window *w, u_int cmd, void *buf, size_t len) -{ - struct client *c; - struct hdr hdr; - u_int i; - - hdr.type = cmd; - hdr.size = len; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL) { - if (c->session->window == w) { - buffer_write(c->out, &hdr, sizeof hdr); - if (buf != NULL) - buffer_write(c->out, buf, len); - } - } - } -} - /* Lost window: move clients on to next window. */ void lost_window(struct window *w) @@ -690,443 +366,3 @@ lost_window(struct window *w) } } -/* Changed client window. */ -void -changed_window(struct client *c) -{ - struct window *w; - - w = c->session->window; - if (c->sx != w->screen.sx || c->sy != w->screen.sy) - window_resize(w, c->sx, c->sy); - draw_client(c, 0, c->sy - 1); -} - -/* Draw window on client. */ -void -draw_client(struct client *c, u_int py_upper, u_int py_lower) -{ - struct hdr hdr; - size_t size; - - buffer_ensure(c->out, sizeof hdr); - buffer_add(c->out, sizeof hdr); - size = BUFFER_USED(c->out); - - screen_draw(&c->session->window->screen, c->out, py_upper, py_lower); - - size = BUFFER_USED(c->out) - size; - log_debug("redrawing screen, %zu bytes", size); - if (size != 0) { - hdr.type = MSG_OUTPUT; - hdr.size = size; - memcpy( - BUFFER_IN(c->out) - size - sizeof hdr, &hdr, sizeof hdr); - } else - buffer_reverse_add(c->out, sizeof hdr); -} - -/* Process a command from the client. */ -void -process_client(struct client *c) -{ - struct hdr hdr; - - 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); - - switch (hdr.type) { - case MSG_NEW: - process_new_msg(c, &hdr); - break; - case MSG_ATTACH: - process_attach_msg(c, &hdr); - break; - case MSG_CREATE: - process_create_msg(c, &hdr); - break; - case MSG_NEXT: - process_next_msg(c, &hdr); - break; - case MSG_PREVIOUS: - process_previous_msg(c, &hdr); - break; - case MSG_SIZE: - process_size_msg(c, &hdr); - break; - case MSG_INPUT: - process_input_msg(c, &hdr); - break; - case MSG_REFRESH: - process_refresh_msg(c, &hdr); - break; - case MSG_SELECT: - process_select_msg(c, &hdr); - break; - case MSG_SESSIONS: - process_sessions_msg(c, &hdr); - break; - case MSG_WINDOWS: - process_windows_msg(c, &hdr); - break; - case MSG_RENAME: - process_rename_msg(c, &hdr); - break; - case MSG_LAST: - process_last_msg(c, &hdr); - break; - case MSG_WINDOWLIST: - process_windowlist_msg(c, &hdr); - break; - default: - fatalx("unexpected message"); - } -} - -/* New message from client. */ -void -process_new_msg(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 -process_attach_msg(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 -process_create_msg(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 -process_next_msg(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 -process_previous_msg(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 -process_size_msg(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 -process_input_msg(struct client *c, struct hdr *hdr) -{ - if (c->session == NULL) - return; - - if (c->prompt == NULL) - window_input(c->session->window, c->in, hdr->size); - else - user_input(c, hdr->size); -} - -/* Refresh message from client. */ -void -process_refresh_msg(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 -process_select_msg(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 -process_sessions_msg(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 -process_windows_msg(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 -process_rename_msg(struct client *c, struct hdr *hdr) -{ - if (c->session == NULL) - return; - if (hdr->size != 0) - fatalx("bad MSG_RENAME size"); - - user_start(c, "Window name: ", - c->session->window->name, MAXNAMELEN, rename_callback); -} - -/* Last window message from client */ -void -process_last_msg(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 -process_windowlist_msg(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); -} - -/* Callback for rename. */ -void -rename_callback(struct client *c, const char *string) -{ - strlcpy( - c->session->window->name, string, sizeof c->session->window->name); -} |