diff --git a/tmate-daemon-decoder.c b/tmate-daemon-decoder.c index 4f3ae723..c835960f 100644 --- a/tmate-daemon-decoder.c +++ b/tmate-daemon-decoder.c @@ -374,10 +374,87 @@ static void tmate_reconnect(__unused struct tmate_session *session, /* Used by the proxy */ } -static void tmate_snapshot(__unused struct tmate_session *session, - __unused struct tmate_unpacker *uk) +static void restore_snapshot_grid(struct grid *grid, struct tmate_unpacker *uk) { - /* TODO copy info back */ + struct grid_cell gc; + char *line_str; + struct utf8_data *utf8_data; + unsigned int i, line_i; + unsigned int packed_flags; + + struct tmate_unpacker lines_uk, line_uk, line_flags_uk; + + unpack_array(uk, &lines_uk); + for (line_i = 0; lines_uk.argc > 0; line_i++) { + while (line_i >= grid->hsize + grid->sy) + grid_scroll_history(grid); + + unpack_array(&lines_uk, &line_uk); + line_str = unpack_string(&line_uk); + utf8_data = utf8_fromcstr(line_str); + free(line_str); + + unpack_array(&line_uk, &line_flags_uk); + for (i = 0; line_flags_uk.argc > 0; i++) { + utf8_copy(&gc.data, &utf8_data[i]); + packed_flags = unpack_int(&line_flags_uk); + gc.flags = (packed_flags >> 24) & 0xFF; + gc.attr = (packed_flags >> 16) & 0xFF; + gc.bg = (packed_flags >> 8) & 0xFF; + gc.fg = packed_flags & 0xFF; + grid_set_cell(grid, i, line_i, &gc); + } + } +} + +static void restore_snapshot_pane(struct tmate_unpacker *uk) +{ + int id; + struct window_pane *wp; + struct tmate_unpacker grid_uk; + struct screen *screen; + + id = unpack_int(uk); + wp = window_pane_find_by_id(id); + if (!wp) + tmate_fatal("can't find pane id=%d (snapshot restore)", id); + screen = &wp->base; + screen_reinit(screen); + wp->flags |= PANE_REDRAW; + + screen->mode = unpack_int(uk); + + unpack_array(uk, &grid_uk); + screen->cx = unpack_int(&grid_uk); + screen->cy = unpack_int(&grid_uk); + grid_clear_history(screen->grid); + restore_snapshot_grid(screen->grid, &grid_uk); + + if (wp->saved_grid != NULL) { + grid_destroy(wp->saved_grid); + wp->saved_grid = NULL; + } + + if (unpack_peek_type(uk) == MSGPACK_OBJECT_NIL) + return; + + unpack_array(uk, &grid_uk); + wp->saved_cx = unpack_int(&grid_uk); + wp->saved_cy = unpack_int(&grid_uk); + wp->saved_grid = grid_create(screen->grid->sx, screen->grid->sy, 0); + restore_snapshot_grid(wp->saved_grid, &grid_uk); +} + +static void tmate_snapshot(__unused struct tmate_session *session, + struct tmate_unpacker *uk) +{ + struct tmate_unpacker panes_uk, pane_uk; + + unpack_array(uk, &panes_uk); + while (panes_uk.argc > 0) { + unpack_array(&panes_uk, &pane_uk); + restore_snapshot_pane(&pane_uk); + } } void tmate_dispatch_daemon_message(struct tmate_session *session, diff --git a/tmate-msgpack.c b/tmate-msgpack.c index 01a9ee1e..301e6d63 100644 --- a/tmate-msgpack.c +++ b/tmate-msgpack.c @@ -264,10 +264,19 @@ void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested) uk->argc--; } +msgpack_object_type unpack_peek_type(struct tmate_unpacker *uk) +{ + if (uk->argc == 0) + tmate_decoder_error(); + return uk->argv[0].type; +} + +#define UNPACKER_RESERVE_SIZE 1024 + void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader, void *userdata) { - if (!msgpack_unpacker_init(&decoder->unpacker, TMATE_MAX_MESSAGE_SIZE)) + if (!msgpack_unpacker_init(&decoder->unpacker, UNPACKER_RESERVE_SIZE)) tmate_fatal("Cannot initialize the unpacker"); decoder->reader = reader; decoder->userdata = userdata; @@ -277,8 +286,7 @@ void tmate_decoder_get_buffer(struct tmate_decoder *decoder, char **buf, size_t *len) { ssize_t current_size = msgpack_unpacker_message_size(&decoder->unpacker); - if (!msgpack_unpacker_reserve_buffer(&decoder->unpacker, - TMATE_MAX_MESSAGE_SIZE - current_size)) + if (!msgpack_unpacker_reserve_buffer(&decoder->unpacker, UNPACKER_RESERVE_SIZE)) tmate_fatal("cannot expand decoder buffer"); *buf = msgpack_unpacker_buffer(&decoder->unpacker); diff --git a/tmate-protocol.h b/tmate-protocol.h index f7ad149a..b29f05b3 100644 --- a/tmate-protocol.h +++ b/tmate-protocol.h @@ -1,9 +1,6 @@ #ifndef TMATE_PROTOCOL_H #define TMATE_PROTOCOL_H - /* 17 and not 16 because the sender does not takes into account envelope size */ -#define TMATE_MAX_MESSAGE_SIZE (17*1024) - enum tmate_control_out_msg_types { TMATE_CTL_HEADER, TMATE_CTL_DEAMON_OUT_MSG, diff --git a/tmate-slave.c b/tmate-slave.c index 15c346a9..f02bc2eb 100644 --- a/tmate-slave.c +++ b/tmate-slave.c @@ -178,11 +178,17 @@ int main(int argc, char **argv, char **envp) if ((dev_urandom_fd = open("/dev/urandom", O_RDONLY)) < 0) tmate_fatal("Cannot open /dev/urandom"); - if ((mkdir(TMATE_WORKDIR, 0700) < 0 && errno != EEXIST) || - (mkdir(TMATE_WORKDIR "/sessions", 0700) < 0 && errno != EEXIST) || + if ((mkdir(TMATE_WORKDIR, 0701) < 0 && errno != EEXIST) || + (mkdir(TMATE_WORKDIR "/sessions", 0703) < 0 && errno != EEXIST) || (mkdir(TMATE_WORKDIR "/jail", 0700) < 0 && errno != EEXIST)) tmate_fatal("Cannot prepare session in " TMATE_WORKDIR); + /* The proxy needs to access the /session dir to rename sockets */ + if ((chmod(TMATE_WORKDIR, 0701) < 0) || + (chmod(TMATE_WORKDIR "/sessions", 0703) < 0) || + (chmod(TMATE_WORKDIR "/jail", 0700) < 0)) + tmate_fatal("Cannot prepare session in " TMATE_WORKDIR); + tmate_ssh_server_main(tmate_session, tmate_settings->keys_dir, tmate_settings->ssh_port); return 0; diff --git a/tmate.h b/tmate.h index 0c0394af..5630cac9 100644 --- a/tmate.h +++ b/tmate.h @@ -79,6 +79,7 @@ extern bool unpack_bool(struct tmate_unpacker *uk); extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len); extern char *unpack_string(struct tmate_unpacker *uk); extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested); +extern msgpack_object_type unpack_peek_type(struct tmate_unpacker *uk); #define unpack_each(nested_uk, tmp_uk, uk) \ for (unpack_array(uk, tmp_uk); \