mirror of
https://github.com/tmate-io/tmate.git
synced 2024-12-24 15:48:58 +01:00
Store sessions in an RB tree by name rather than a list, this is tidier
and allows them to easily be shown sorted in various lists (list-sessions/choose-sessions). Keep a session index which is used in a couple of places internally but make it an ever-increasing number rather than filling in gaps with new sessions.
This commit is contained in:
parent
1b8488ee75
commit
acf13ce978
@ -47,7 +47,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
char *overrides, *cause;
|
char *overrides, *cause;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&sessions) == 0) {
|
if (RB_EMPTY(&sessions)) {
|
||||||
ctx->error(ctx, "no sessions");
|
ctx->error(ctx, "no sessions");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
u_int i, idx, sgidx, cur;
|
u_int idx, sgidx, cur;
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
|
||||||
if (ctx->curclient == NULL) {
|
if (ctx->curclient == NULL) {
|
||||||
@ -70,10 +70,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
cur = idx = 0;
|
cur = idx = 0;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
if (s == ctx->curclient->session)
|
if (s == ctx->curclient->session)
|
||||||
cur = idx;
|
cur = idx;
|
||||||
idx++;
|
idx++;
|
||||||
@ -86,7 +83,7 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
|
xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_choose_add(wl->window->active, i,
|
window_choose_add(wl->window->active, s->idx,
|
||||||
"%s: %u windows [%ux%u]%s%s", s->name,
|
"%s: %u windows [%ux%u]%s%s", s->name,
|
||||||
winlink_count(&s->windows), s->sx, s->sy,
|
winlink_count(&s->windows), s->sx, s->sy,
|
||||||
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
|
||||||
@ -120,9 +117,7 @@ cmd_choose_session_callback(void *data, int idx)
|
|||||||
if (cdata->client->flags & CLIENT_DEAD)
|
if (cdata->client->flags & CLIENT_DEAD)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((u_int) idx > ARRAY_LENGTH(&sessions) - 1)
|
s = session_find_by_index(idx);
|
||||||
return;
|
|
||||||
s = ARRAY_ITEM(&sessions, idx);
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return;
|
return;
|
||||||
template = cmd_template_replace(cdata->template, s->name, 1);
|
template = cmd_template_replace(cdata->template, s->name, 1);
|
||||||
|
@ -46,14 +46,10 @@ cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct session *s;
|
struct session *s;
|
||||||
struct session_group *sg;
|
struct session_group *sg;
|
||||||
char *tim, tmp[64];
|
char *tim, tmp[64];
|
||||||
u_int i, idx;
|
u_int idx;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
sg = session_group_find(s);
|
sg = session_group_find(s);
|
||||||
if (sg == NULL)
|
if (sg == NULL)
|
||||||
*tmp = '\0';
|
*tmp = '\0';
|
||||||
|
@ -53,8 +53,10 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
|
RB_REMOVE(sessions, &sessions, s);
|
||||||
xfree(s->name);
|
xfree(s->name);
|
||||||
s->name = xstrdup(data->arg);
|
s->name = xstrdup(data->arg);
|
||||||
|
RB_INSERT(sessions, &sessions, s);
|
||||||
|
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
|
|
||||||
|
@ -81,8 +81,6 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
else
|
else
|
||||||
ctx->print(ctx, "configuration file not specified");
|
ctx->print(ctx, "configuration file not specified");
|
||||||
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
|
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
|
||||||
ctx->print(ctx, "%u clients, %u sessions",
|
|
||||||
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
|
|
||||||
ctx->print(ctx, "%s", "");
|
ctx->print(ctx, "%s", "");
|
||||||
|
|
||||||
ctx->print(ctx, "Clients:");
|
ctx->print(ctx, "Clients:");
|
||||||
@ -101,19 +99,14 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
ctx->print(ctx, "Sessions: [%zu/%zu]",
|
ctx->print(ctx, "Sessions: [%zu/%zu]",
|
||||||
sizeof (struct grid_cell), sizeof (struct grid_utf8));
|
sizeof (struct grid_cell), sizeof (struct grid_utf8));
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
t = s->creation_time.tv_sec;
|
t = s->creation_time.tv_sec;
|
||||||
tim = ctime(&t);
|
tim = ctime(&t);
|
||||||
*strchr(tim, '\n') = '\0';
|
*strchr(tim, '\n') = '\0';
|
||||||
|
|
||||||
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
|
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
|
||||||
"[flags=0x%x, references=%u]", i, s->name,
|
"[flags=0x%x]", s->idx, s->name,
|
||||||
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags,
|
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
|
||||||
s->references);
|
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
|
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
|
||||||
|
57
cmd.c
57
cmd.c
@ -112,7 +112,8 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct session *cmd_choose_session(struct sessions *);
|
struct session *cmd_choose_session_list(struct sessionslist *);
|
||||||
|
struct session *cmd_choose_session(void);
|
||||||
struct client *cmd_choose_client(struct clients *);
|
struct client *cmd_choose_client(struct clients *);
|
||||||
struct client *cmd_lookup_client(const char *);
|
struct client *cmd_lookup_client(const char *);
|
||||||
struct session *cmd_lookup_session(const char *, int *);
|
struct session *cmd_lookup_session(const char *, int *);
|
||||||
@ -316,10 +317,9 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
struct msg_command_data *data = ctx->msgdata;
|
struct msg_command_data *data = ctx->msgdata;
|
||||||
struct client *c = ctx->cmdclient;
|
struct client *c = ctx->cmdclient;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct sessions ss;
|
struct sessionslist ss;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
u_int i;
|
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (ctx->curclient != NULL && ctx->curclient->session != NULL)
|
if (ctx->curclient != NULL && ctx->curclient->session != NULL)
|
||||||
@ -332,9 +332,7 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
*/
|
*/
|
||||||
if (c != NULL && c->tty.path != NULL) {
|
if (c != NULL && c->tty.path != NULL) {
|
||||||
ARRAY_INIT(&ss);
|
ARRAY_INIT(&ss);
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
found = 0;
|
found = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
@ -350,25 +348,43 @@ cmd_current_session(struct cmd_ctx *ctx)
|
|||||||
ARRAY_ADD(&ss, s);
|
ARRAY_ADD(&ss, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = cmd_choose_session(&ss);
|
s = cmd_choose_session_list(&ss);
|
||||||
ARRAY_FREE(&ss);
|
ARRAY_FREE(&ss);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use the session from the TMUX environment variable. */
|
/* Use the session from the TMUX environment variable. */
|
||||||
if (data != NULL &&
|
if (data != NULL && data->pid == getpid()) {
|
||||||
data->pid == getpid() &&
|
s = session_find_by_index(data->idx);
|
||||||
data->idx <= ARRAY_LENGTH(&sessions) &&
|
if (s != NULL)
|
||||||
(s = ARRAY_ITEM(&sessions, data->idx)) != NULL)
|
return (s);
|
||||||
return (s);
|
}
|
||||||
|
|
||||||
return (cmd_choose_session(&sessions));
|
return (cmd_choose_session());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the most recently used session. */
|
||||||
|
struct session *
|
||||||
|
cmd_choose_session(void)
|
||||||
|
{
|
||||||
|
struct session *s, *sbest;
|
||||||
|
struct timeval *tv = NULL;
|
||||||
|
|
||||||
|
sbest = NULL;
|
||||||
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
|
if (tv == NULL || timercmp(&s->activity_time, tv, >)) {
|
||||||
|
sbest = s;
|
||||||
|
tv = &s->activity_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (sbest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the most recently used session from a list. */
|
/* Find the most recently used session from a list. */
|
||||||
struct session *
|
struct session *
|
||||||
cmd_choose_session(struct sessions *ss)
|
cmd_choose_session_list(struct sessionslist *ss)
|
||||||
{
|
{
|
||||||
struct session *s, *sbest;
|
struct session *s, *sbest;
|
||||||
struct timeval *tv = NULL;
|
struct timeval *tv = NULL;
|
||||||
@ -516,7 +532,6 @@ struct session *
|
|||||||
cmd_lookup_session(const char *name, int *ambiguous)
|
cmd_lookup_session(const char *name, int *ambiguous)
|
||||||
{
|
{
|
||||||
struct session *s, *sfound;
|
struct session *s, *sfound;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
|
|
||||||
@ -525,21 +540,15 @@ cmd_lookup_session(const char *name, int *ambiguous)
|
|||||||
* be unique so an exact match can't be ambigious and can just be
|
* be unique so an exact match can't be ambigious and can just be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
if ((s = session_find(name)) != NULL)
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
return (s);
|
||||||
continue;
|
|
||||||
if (strcmp(name, s->name) == 0)
|
|
||||||
return (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise look for partial matches, returning early if it is found to
|
* Otherwise look for partial matches, returning early if it is found to
|
||||||
* be ambiguous.
|
* be ambiguous.
|
||||||
*/
|
*/
|
||||||
sfound = NULL;
|
sfound = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
if (strncmp(name, s->name, strlen(name)) == 0 ||
|
||||||
fnmatch(name, s->name, 0) == 0) {
|
fnmatch(name, s->name, 0) == 0) {
|
||||||
if (sfound != NULL) {
|
if (sfound != NULL) {
|
||||||
|
11
resize.c
11
resize.c
@ -52,11 +52,7 @@ recalculate_sizes(void)
|
|||||||
u_int i, j, ssx, ssy, has, limit;
|
u_int i, j, ssx, ssy, has, limit;
|
||||||
int flag;
|
int flag;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ssx = ssy = UINT_MAX;
|
ssx = ssy = UINT_MAX;
|
||||||
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
|
||||||
c = ARRAY_ITEM(&clients, j);
|
c = ARRAY_ITEM(&clients, j);
|
||||||
@ -98,9 +94,8 @@ recalculate_sizes(void)
|
|||||||
flag = options_get_number(&w->options, "aggressive-resize");
|
flag = options_get_number(&w->options, "aggressive-resize");
|
||||||
|
|
||||||
ssx = ssy = UINT_MAX;
|
ssx = ssy = UINT_MAX;
|
||||||
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, j);
|
if (s->flags & SESSION_UNATTACHED)
|
||||||
if (s == NULL || s->flags & SESSION_UNATTACHED)
|
|
||||||
continue;
|
continue;
|
||||||
if (flag)
|
if (flag)
|
||||||
has = s->curw->window == w;
|
has = s->curw->window == w;
|
||||||
|
31
server-fn.c
31
server-fn.c
@ -30,13 +30,10 @@ void server_callback_identify(int, short, void *);
|
|||||||
void
|
void
|
||||||
server_fill_environ(struct session *s, struct environ *env)
|
server_fill_environ(struct session *s, struct environ *env)
|
||||||
{
|
{
|
||||||
char tmuxvar[MAXPATHLEN], *term;
|
char tmuxvar[MAXPATHLEN], *term;
|
||||||
u_int idx;
|
|
||||||
|
|
||||||
if (session_index(s, &idx) != 0)
|
|
||||||
fatalx("session not found");
|
|
||||||
xsnprintf(tmuxvar, sizeof tmuxvar,
|
xsnprintf(tmuxvar, sizeof tmuxvar,
|
||||||
"%s,%ld,%u", socket_path, (long) getpid(), idx);
|
"%s,%ld,%u", socket_path, (long) getpid(), s->idx);
|
||||||
environ_set(env, "TMUX", tmuxvar);
|
environ_set(env, "TMUX", tmuxvar);
|
||||||
|
|
||||||
term = options_get_string(&s->options, "default-terminal");
|
term = options_get_string(&s->options, "default-terminal");
|
||||||
@ -175,7 +172,6 @@ void
|
|||||||
server_status_window(struct window *w)
|
server_status_window(struct window *w)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is slightly different. We want to redraw the status line of any
|
* This is slightly different. We want to redraw the status line of any
|
||||||
@ -183,9 +179,8 @@ server_status_window(struct window *w)
|
|||||||
* current window.
|
* current window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
if (session_has(s, w) != NULL)
|
||||||
if (s != NULL && session_has(s, w) != NULL)
|
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,11 +241,9 @@ server_kill_window(struct window *w)
|
|||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
if (session_has(s, w) == NULL)
|
||||||
if (s == NULL || session_has(s, w) == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
|
while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
|
||||||
if (session_detach(s, wl)) {
|
if (session_detach(s, wl)) {
|
||||||
@ -365,12 +358,10 @@ struct session *
|
|||||||
server_next_session(struct session *s)
|
server_next_session(struct session *s)
|
||||||
{
|
{
|
||||||
struct session *s_loop, *s_out;
|
struct session *s_loop, *s_out;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
s_out = NULL;
|
s_out = NULL;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s_loop, sessions, &sessions) {
|
||||||
s_loop = ARRAY_ITEM(&sessions, i);
|
if (s_loop == s)
|
||||||
if (s_loop == NULL || s_loop == s)
|
|
||||||
continue;
|
continue;
|
||||||
if (s_out == NULL ||
|
if (s_out == NULL ||
|
||||||
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
timercmp(&s_loop->activity_time, &s_out->activity_time, <))
|
||||||
@ -411,15 +402,13 @@ void
|
|||||||
server_check_unattached (void)
|
server_check_unattached (void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If any sessions are no longer attached and have destroy-unattached
|
* If any sessions are no longer attached and have destroy-unattached
|
||||||
* set, collect them.
|
* set, collect them.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
if (!(s->flags & SESSION_UNATTACHED))
|
||||||
if (s == NULL || !(s->flags & SESSION_UNATTACHED))
|
|
||||||
continue;
|
continue;
|
||||||
if (options_get_number (&s->options, "destroy-unattached"))
|
if (options_get_number (&s->options, "destroy-unattached"))
|
||||||
session_destroy(s);
|
session_destroy(s);
|
||||||
|
@ -38,17 +38,14 @@ server_window_loop(void)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i, j;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||||
w = ARRAY_ITEM(&windows, i);
|
w = ARRAY_ITEM(&windows, i);
|
||||||
if (w == NULL)
|
if (w == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < ARRAY_LENGTH(&sessions); j++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, j);
|
|
||||||
if (s == NULL)
|
|
||||||
continue;
|
|
||||||
wl = session_has(s, w);
|
wl = session_has(s, w);
|
||||||
if (wl == NULL)
|
if (wl == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
59
server.c
59
server.c
@ -147,8 +147,8 @@ server_start(void)
|
|||||||
ARRAY_INIT(&windows);
|
ARRAY_INIT(&windows);
|
||||||
ARRAY_INIT(&clients);
|
ARRAY_INIT(&clients);
|
||||||
ARRAY_INIT(&dead_clients);
|
ARRAY_INIT(&dead_clients);
|
||||||
ARRAY_INIT(&sessions);
|
RB_INIT(&sessions);
|
||||||
ARRAY_INIT(&dead_sessions);
|
RB_INIT(&dead_sessions);
|
||||||
TAILQ_INIT(&session_groups);
|
TAILQ_INIT(&session_groups);
|
||||||
mode_key_init_trees();
|
mode_key_init_trees();
|
||||||
key_bindings_init();
|
key_bindings_init();
|
||||||
@ -174,8 +174,8 @@ server_start(void)
|
|||||||
* If there is a session already, put the current window and pane into
|
* If there is a session already, put the current window and pane into
|
||||||
* more mode.
|
* more mode.
|
||||||
*/
|
*/
|
||||||
if (!ARRAY_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
|
if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) {
|
||||||
wp = ARRAY_FIRST(&sessions)->curw->window->active;
|
wp = RB_MIN(sessions, &sessions)->curw->window->active;
|
||||||
window_pane_set_mode(wp, &window_copy_mode);
|
window_pane_set_mode(wp, &window_copy_mode);
|
||||||
window_copy_init_for_output(wp);
|
window_copy_init_for_output(wp);
|
||||||
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
|
||||||
@ -223,10 +223,8 @@ server_should_shutdown(void)
|
|||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
if (!options_get_number(&global_options, "exit-unattached")) {
|
if (!options_get_number(&global_options, "exit-unattached")) {
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
if (!RB_EMPTY(&sessions))
|
||||||
if (ARRAY_ITEM(&sessions, i) != NULL)
|
return (0);
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
if (ARRAY_ITEM(&clients, i) != NULL)
|
if (ARRAY_ITEM(&clients, i) != NULL)
|
||||||
@ -240,7 +238,7 @@ void
|
|||||||
server_send_shutdown(void)
|
server_send_shutdown(void)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s;
|
struct session *s, *next_s;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||||
@ -254,9 +252,11 @@ server_send_shutdown(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
s = RB_MIN(sessions, &sessions);
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) != NULL)
|
while (s != NULL) {
|
||||||
session_destroy(s);
|
next_s = RB_NEXT(sessions, &sessions, s);
|
||||||
|
session_destroy(s);
|
||||||
|
s = next_s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,16 +264,19 @@ server_send_shutdown(void)
|
|||||||
void
|
void
|
||||||
server_clean_dead(void)
|
server_clean_dead(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s, *next_s;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
|
s = RB_MIN(sessions, &dead_sessions);
|
||||||
s = ARRAY_ITEM(&dead_sessions, i);
|
while (s != NULL) {
|
||||||
if (s == NULL || s->references != 0)
|
next_s = RB_NEXT(sessions, &dead_sessions, s);
|
||||||
continue;
|
if (s->references == 0) {
|
||||||
ARRAY_SET(&dead_sessions, i, NULL);
|
RB_REMOVE(sessions, &dead_sessions, s);
|
||||||
xfree(s);
|
xfree(s->name);
|
||||||
|
xfree(s);
|
||||||
|
}
|
||||||
|
s = next_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
|
for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
|
||||||
@ -290,15 +293,13 @@ void
|
|||||||
server_update_socket(void)
|
server_update_socket(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
static int last = -1;
|
static int last = -1;
|
||||||
int n, mode;
|
int n, mode;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
if (!(s->flags & SESSION_UNATTACHED)) {
|
||||||
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
|
|
||||||
n++;
|
n++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -485,15 +486,11 @@ void
|
|||||||
server_lock_server(void)
|
server_lock_server(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
int timeout;
|
int timeout;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (s->flags & SESSION_UNATTACHED) {
|
if (s->flags & SESSION_UNATTACHED) {
|
||||||
if (gettimeofday(&s->activity_time, NULL) != 0)
|
if (gettimeofday(&s->activity_time, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
@ -514,15 +511,11 @@ void
|
|||||||
server_lock_sessions(void)
|
server_lock_sessions(void)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
int timeout;
|
int timeout;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (s->flags & SESSION_UNATTACHED) {
|
if (s->flags & SESSION_UNATTACHED) {
|
||||||
if (gettimeofday(&s->activity_time, NULL) != 0)
|
if (gettimeofday(&s->activity_time, NULL) != 0)
|
||||||
fatal("gettimeofday failed");
|
fatal("gettimeofday failed");
|
||||||
|
113
session.c
113
session.c
@ -30,11 +30,20 @@
|
|||||||
/* Global session list. */
|
/* Global session list. */
|
||||||
struct sessions sessions;
|
struct sessions sessions;
|
||||||
struct sessions dead_sessions;
|
struct sessions dead_sessions;
|
||||||
|
u_int next_session;
|
||||||
struct session_groups session_groups;
|
struct session_groups session_groups;
|
||||||
|
|
||||||
struct winlink *session_next_alert(struct winlink *);
|
struct winlink *session_next_alert(struct winlink *);
|
||||||
struct winlink *session_previous_alert(struct winlink *);
|
struct winlink *session_previous_alert(struct winlink *);
|
||||||
|
|
||||||
|
RB_GENERATE(sessions, session, entry, session_cmp);
|
||||||
|
|
||||||
|
int
|
||||||
|
session_cmp(struct session *s1, struct session *s2)
|
||||||
|
{
|
||||||
|
return (strcmp(s1->name, s2->name));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find if session is still alive. This is true if it is still on the global
|
* Find if session is still alive. This is true if it is still on the global
|
||||||
* sessions list.
|
* sessions list.
|
||||||
@ -42,24 +51,35 @@ struct winlink *session_previous_alert(struct winlink *);
|
|||||||
int
|
int
|
||||||
session_alive(struct session *s)
|
session_alive(struct session *s)
|
||||||
{
|
{
|
||||||
u_int idx;
|
struct session *s_loop;
|
||||||
|
|
||||||
return (session_index(s, &idx) == 0);
|
RB_FOREACH(s_loop, sessions, &sessions) {
|
||||||
|
if (s_loop == s)
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find session by name. */
|
/* Find session by name. */
|
||||||
struct session *
|
struct session *
|
||||||
session_find(const char *name)
|
session_find(const char *name)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session s;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
s.name = (char *) name;
|
||||||
s = ARRAY_ITEM(&sessions, i);
|
return (RB_FIND(sessions, &sessions, &s));
|
||||||
if (s != NULL && strcmp(s->name, name) == 0)
|
}
|
||||||
|
|
||||||
|
/* Find session by index. */
|
||||||
|
struct session *
|
||||||
|
session_find_by_index(u_int idx)
|
||||||
|
{
|
||||||
|
struct session *s;
|
||||||
|
|
||||||
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
|
if (s->idx == idx)
|
||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +90,6 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
char **cause)
|
char **cause)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
s = xmalloc(sizeof *s);
|
s = xmalloc(sizeof *s);
|
||||||
s->references = 0;
|
s->references = 0;
|
||||||
@ -102,19 +121,12 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
s->sx = sx;
|
s->sx = sx;
|
||||||
s->sy = sy;
|
s->sy = sy;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
|
s->idx = next_session++;
|
||||||
if (ARRAY_ITEM(&sessions, i) == NULL) {
|
|
||||||
ARRAY_SET(&sessions, i, s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == ARRAY_LENGTH(&sessions))
|
|
||||||
ARRAY_ADD(&sessions, s);
|
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
s->name = xstrdup(name);
|
s->name = xstrdup(name);
|
||||||
else
|
else
|
||||||
xasprintf(&s->name, "%u", i);
|
xasprintf(&s->name, "%u", s->idx);
|
||||||
|
RB_INSERT(sessions, &sessions, s);
|
||||||
|
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
if (session_new(s, NULL, cmd, cwd, idx, cause) == NULL) {
|
||||||
@ -133,15 +145,9 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
void
|
void
|
||||||
session_destroy(struct session *s)
|
session_destroy(struct session *s)
|
||||||
{
|
{
|
||||||
u_int i;
|
|
||||||
|
|
||||||
log_debug("session %s destroyed", s->name);
|
log_debug("session %s destroyed", s->name);
|
||||||
|
|
||||||
if (session_index(s, &i) != 0)
|
RB_REMOVE(sessions, &sessions, s);
|
||||||
fatalx("session not found");
|
|
||||||
ARRAY_SET(&sessions, i, NULL);
|
|
||||||
while (!ARRAY_EMPTY(&sessions) && ARRAY_LAST(&sessions) == NULL)
|
|
||||||
ARRAY_TRUNC(&sessions, 1);
|
|
||||||
|
|
||||||
if (s->tio != NULL)
|
if (s->tio != NULL)
|
||||||
xfree(s->tio);
|
xfree(s->tio);
|
||||||
@ -157,27 +163,8 @@ session_destroy(struct session *s)
|
|||||||
winlink_remove(&s->windows, RB_ROOT(&s->windows));
|
winlink_remove(&s->windows, RB_ROOT(&s->windows));
|
||||||
|
|
||||||
xfree(s->cwd);
|
xfree(s->cwd);
|
||||||
xfree(s->name);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
|
RB_INSERT(sessions, &dead_sessions, s);
|
||||||
if (ARRAY_ITEM(&dead_sessions, i) == NULL) {
|
|
||||||
ARRAY_SET(&dead_sessions, i, s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == ARRAY_LENGTH(&dead_sessions))
|
|
||||||
ARRAY_ADD(&dead_sessions, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find session index. */
|
|
||||||
int
|
|
||||||
session_index(struct session *s, u_int *i)
|
|
||||||
{
|
|
||||||
for (*i = 0; *i < ARRAY_LENGTH(&sessions); (*i)++) {
|
|
||||||
if (s == ARRAY_ITEM(&sessions, *i))
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the next usable session. */
|
/* Find the next usable session. */
|
||||||
@ -185,19 +172,18 @@ struct session *
|
|||||||
session_next_session(struct session *s)
|
session_next_session(struct session *s)
|
||||||
{
|
{
|
||||||
struct session *s2;
|
struct session *s2;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&sessions) == 0 || session_index(s, &i) != 0)
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
s2 = s;
|
||||||
do {
|
do {
|
||||||
if (i == ARRAY_LENGTH(&sessions) - 1)
|
s2 = RB_NEXT(sessions, &sessions, s2);
|
||||||
i = 0;
|
if (s2 == NULL)
|
||||||
else
|
s2 = RB_MIN(sessions, &sessions);
|
||||||
i++;
|
} while (s2 != s);
|
||||||
s2 = ARRAY_ITEM(&sessions, i);
|
if (s2 == s)
|
||||||
} while (s2 == NULL);
|
return (NULL);
|
||||||
|
|
||||||
return (s2);
|
return (s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,19 +192,18 @@ struct session *
|
|||||||
session_previous_session(struct session *s)
|
session_previous_session(struct session *s)
|
||||||
{
|
{
|
||||||
struct session *s2;
|
struct session *s2;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
if (ARRAY_LENGTH(&sessions) == 0 || session_index(s, &i) != 0)
|
if (RB_EMPTY(&sessions) || !session_alive(s))
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
s2 = s;
|
||||||
do {
|
do {
|
||||||
if (i == 0)
|
s2 = RB_PREV(sessions, &sessions, s2);
|
||||||
i = ARRAY_LENGTH(&sessions) - 1;
|
if (s2 == NULL)
|
||||||
else
|
s2 = RB_MAX(sessions, &sessions);
|
||||||
i--;
|
} while (s2 != s);
|
||||||
s2 = ARRAY_ITEM(&sessions, i);
|
if (s2 == s)
|
||||||
} while (s2 == NULL);
|
return (NULL);
|
||||||
|
|
||||||
return (s2);
|
return (s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
tmux.h
10
tmux.h
@ -930,6 +930,8 @@ struct session_group {
|
|||||||
TAILQ_HEAD(session_groups, session_group);
|
TAILQ_HEAD(session_groups, session_group);
|
||||||
|
|
||||||
struct session {
|
struct session {
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
|
|
||||||
@ -957,8 +959,10 @@ struct session {
|
|||||||
int references;
|
int references;
|
||||||
|
|
||||||
TAILQ_ENTRY(session) gentry;
|
TAILQ_ENTRY(session) gentry;
|
||||||
|
RB_ENTRY(session) entry;
|
||||||
};
|
};
|
||||||
ARRAY_DECL(sessions, struct session *);
|
RB_HEAD(sessions, session);
|
||||||
|
ARRAY_DECL(sessionslist, struct session *);
|
||||||
|
|
||||||
/* TTY information. */
|
/* TTY information. */
|
||||||
struct tty_key {
|
struct tty_key {
|
||||||
@ -1967,13 +1971,15 @@ void clear_signals(int);
|
|||||||
extern struct sessions sessions;
|
extern struct sessions sessions;
|
||||||
extern struct sessions dead_sessions;
|
extern struct sessions dead_sessions;
|
||||||
extern struct session_groups session_groups;
|
extern struct session_groups session_groups;
|
||||||
|
int session_cmp(struct session *, struct session *);
|
||||||
|
RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
||||||
int session_alive(struct session *);
|
int session_alive(struct session *);
|
||||||
struct session *session_find(const char *);
|
struct session *session_find(const char *);
|
||||||
|
struct session *session_find_by_index(u_int);
|
||||||
struct session *session_create(const char *, const char *, const char *,
|
struct session *session_create(const char *, const char *, const char *,
|
||||||
struct environ *, struct termios *, int, u_int, u_int,
|
struct environ *, struct termios *, int, u_int, u_int,
|
||||||
char **);
|
char **);
|
||||||
void session_destroy(struct session *);
|
void session_destroy(struct session *);
|
||||||
int session_index(struct session *, u_int *);
|
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *);
|
||||||
struct session *session_previous_session(struct session *);
|
struct session *session_previous_session(struct session *);
|
||||||
struct winlink *session_new(struct session *,
|
struct winlink *session_new(struct session *,
|
||||||
|
Loading…
Reference in New Issue
Block a user