version 1.24, 2010/12/20 01:28:18 |
version 1.25, 2010/12/21 22:37:59 |
|
|
/* 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. |
|
|
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; |
|
|
|
s.name = (char *) name; |
|
return (RB_FIND(sessions, &sessions, &s)); |
|
} |
|
|
|
/* Find session by index. */ |
|
struct session * |
|
session_find_by_index(u_int idx) |
|
{ |
struct session *s; |
struct session *s; |
u_int i; |
|
|
|
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { |
RB_FOREACH(s, sessions, &sessions) { |
s = ARRAY_ITEM(&sessions, i); |
if (s->idx == idx) |
if (s != NULL && strcmp(s->name, name) == 0) |
|
return (s); |
return (s); |
} |
} |
|
|
return (NULL); |
return (NULL); |
} |
} |
|
|
|
|
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; |
|
|
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) { |
|
|
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); |
|
|
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. */ |
struct session * |
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); |
} |
} |
|
|
|
|
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); |
} |
} |
|
|