From 22990a6595fdff840010aa6df9a60ada61331b5e Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 27 Sep 2007 09:52:03 +0000 Subject: [PATCH] New session selection rules: - find by name if given - otherwise try current index from $TMUX - otherwise if only one session, use it - otherwise error --- client.c | 32 ++++++++++++++++++++++++++++++- op-list.c | 4 ++-- op.c | 4 ++-- server-fn.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++- server-msg.c | 34 +++++++++------------------------ session.c | 8 ++++---- tmux.h | 53 ++++++++++++++++++++++++++++++---------------------- 7 files changed, 131 insertions(+), 57 deletions(-) diff --git a/client.c b/client.c index 3593cc58..fec1b81c 100644 --- a/client.c +++ b/client.c @@ -1,4 +1,4 @@ -/* $Id: client.c,v 1.5 2007-09-26 19:09:30 nicm Exp $ */ +/* $Id: client.c,v 1.6 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -196,6 +196,36 @@ local_dead: fatalx("local socket dead"); } +void +client_fill_sessid(struct sessid *sid, char name[MAXNAMELEN]) +{ + char *env, *ptr, buf[256]; + const char *errstr; + long long ll; + + strlcpy(sid->name, name, sizeof sid->name); + + sid->pid = -1; + if ((env = getenv("TMUX")) == NULL) + return; + if ((ptr = strchr(env, ',')) == NULL) + return; + if ((size_t) (ptr - env) > sizeof buf) + return; + memcpy(buf, env, ptr - env); + buf[ptr - env] = '\0'; + + ll = strtonum(ptr + 1, 0, UINT_MAX, &errstr); + if (errstr != NULL) + return; + sid->idx = ll; + + ll = strtonum(buf, 0, LLONG_MAX, &errstr); + if (errstr != NULL) + return; + sid->pid = ll; +} + void client_write_server( struct client_ctx *cctx, enum hdrtype type, void *buf, size_t len) diff --git a/op-list.c b/op-list.c index ba7f3862..bfaaf63d 100644 --- a/op-list.c +++ b/op-list.c @@ -1,4 +1,4 @@ -/* $Id: op-list.c,v 1.3 2007-09-26 19:38:42 nicm Exp $ */ +/* $Id: op-list.c,v 1.4 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -63,7 +63,7 @@ op_list(char *path, int argc, char **argv) if (*name == '\0') client_write_server(&cctx, MSG_SESSIONS, &sdata, sizeof sdata); else { - strlcpy(wdata.name, name, sizeof wdata.name); + client_fill_sessid(&wdata.sid, name); client_write_server(&cctx, MSG_WINDOWS, &wdata, sizeof wdata); } diff --git a/op.c b/op.c index 3c24c8b5..22377d80 100644 --- a/op.c +++ b/op.c @@ -1,4 +1,4 @@ -/* $Id: op.c,v 1.5 2007-09-26 19:38:42 nicm Exp $ */ +/* $Id: op.c,v 1.6 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -93,7 +93,7 @@ op_attach(char *path, int argc, char **argv) if (client_init(path, &cctx, 1) != 0) return (1); - strlcpy(data.name, name, sizeof data.name); + client_fill_sessid(&data.sid, name); data.sx = cctx.ws.ws_col; data.sy = cctx.ws.ws_row; client_write_server(&cctx, MSG_ATTACH, &data, sizeof data); diff --git a/server-fn.c b/server-fn.c index 0429af94..9309b343 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.3 2007-09-27 09:15:58 nicm Exp $ */ +/* $Id: server-fn.c,v 1.4 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -19,9 +19,60 @@ #include #include +#include #include "tmux.h" +/* Find session from sessid. */ +struct session * +server_find_sessid(struct sessid *sid, char **cause) +{ + struct session *s; + u_int i, n; + + if (*sid->name != '\0') { + if ((s = session_find(sid->name)) == NULL) { + xasprintf(cause, "session not found: %s", sid->name); + return (NULL); + } + return (s); + } + + if (sid->pid != -1) { + if (sid->pid != getpid()) { + xasprintf(cause, "wrong server: %lld", sid->pid); + return (NULL); + } + if (sid->idx > ARRAY_LENGTH(&sessions)) { + xasprintf(cause, "index out of range: %u", sid->idx); + return (NULL); + } + if ((s = ARRAY_ITEM(&sessions, sid->idx) = NULL)) { + xasprintf(cause, "session doesn't exist: %u", sid->idx); + return (NULL); + } + return (s); + } + + s = NULL; + n = 0; + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + if (ARRAY_ITEM(&sessions, i) != NULL) { + s = ARRAY_ITEM(&sessions, i); + n++; + } + } + if (s == NULL) { + xasprintf(cause, "no sessions"); + return (NULL); + } + if (n != 1) { + xasprintf(cause, "multiple sessions and session not specified"); + return (NULL); + } + return (s); +} + /* Write command to a client. */ void server_write_client(struct client *c, enum hdrtype type, void *buf, size_t len) diff --git a/server-msg.c b/server-msg.c index 0f8d092d..4d84a3d3 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.4 2007-09-26 18:50:49 nicm Exp $ */ +/* $Id: server-msg.c,v 1.5 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -138,9 +138,7 @@ int server_msg_fn_attach(struct hdr *hdr, struct client *c) { struct attach_data data; - char *msg; - struct session *s; - u_int i; + char *cause; if (c->session != NULL) return (0); @@ -155,23 +153,9 @@ server_msg_fn_attach(struct hdr *hdr, struct client *c) if (c->sy == 0) c->sy = 25; - if (*data.name != '\0') { - if ((c->session = session_find(data.name)) == NULL) - xasprintf(&msg, "session not found: %s", data.name); - } else { - /* Find the oldest session. */ - for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { - if ((s = ARRAY_ITEM(&sessions, i)) == NULL) - continue; - if (c->session == NULL || s->tim < c->session->tim) - c->session = s; - } - if (c->session == NULL) - xasprintf(&msg, "no sessions found"); - } - if (c->session == NULL) { - server_write_client(c, MSG_ERROR, msg, strlen(msg)); - xfree(msg); + if ((c->session = server_find_sessid(&data.sid, &cause)) == NULL) { + server_write_client(c, MSG_ERROR, cause, strlen(cause)); + xfree(cause); return (0); } @@ -361,15 +345,15 @@ server_msg_fn_windows(struct hdr *hdr, struct client *c) struct session *s; struct window *w; u_int i; + char *cause; 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; - server_write_client(c, MSG_WINDOWS, &data, sizeof data); + if ((s = server_find_sessid(&data.sid, &cause)) == NULL) { + server_write_client(c, MSG_ERROR, cause, strlen(cause)); + xfree(cause); return (0); } diff --git a/session.c b/session.c index 9350694c..d15af07c 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $Id: session.c,v 1.16 2007-09-27 09:15:58 nicm Exp $ */ +/* $Id: session.c,v 1.17 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -112,13 +112,13 @@ session_new(struct session *s, const char *cmd, u_int sx, u_int sy) { struct window *w; const char *environ[] = { NULL, "TERM=screen", NULL }; - char blk[256]; + char buf[256]; u_int i; if (session_index(s, &i) != 0) fatalx("session not found"); - xsnprintf(blk, sizeof blk, "TMUX=%ld,%u", (long) getpid(), i); - environ[0] = blk; + xsnprintf(buf, sizeof buf, "TMUX=%ld,%u", (long) getpid(), i); + environ[0] = buf; if ((w = window_create(cmd, environ, sx, sy)) == NULL) return (-1); diff --git a/tmux.h b/tmux.h index 32af458c..a7bbdbb2 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.16 2007-09-27 09:15:58 nicm Exp $ */ +/* $Id: tmux.h,v 1.17 2007-09-27 09:52:03 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -285,53 +285,60 @@ struct hdr { size_t size; }; +/* Session identification. */ +struct sessid { + long long pid; /* pid from $TMUX or -1 */ + u_int idx; /* index from $TMUX */ + char name[MAXNAMELEN]; /* empty for current */ +}; + struct new_data { - char name[MAXNAMELEN]; - u_int sx; - u_int sy; + char name[MAXNAMELEN]; + u_int sx; + u_int sy; }; struct attach_data { - char name[MAXNAMELEN]; - u_int sx; - u_int sy; + struct sessid sid; + u_int sx; + u_int sy; }; struct sessions_data { - u_int sessions; + u_int sessions; }; struct sessions_entry { - char name[MAXNAMELEN]; - time_t tim; - u_int windows; + char name[MAXNAMELEN]; + time_t tim; + u_int windows; }; struct windows_data { - char name[MAXNAMELEN]; - u_int windows; + struct sessid sid; + u_int windows; }; struct windows_entry { - u_int idx; - char tty[TTY_NAME_MAX]; + u_int idx; + char tty[TTY_NAME_MAX]; - char name[MAXNAMELEN]; - char title[MAXTITLELEN]; + char name[MAXNAMELEN]; + char title[MAXTITLELEN]; }; struct size_data { - u_int sx; - u_int sy; + u_int sx; + u_int sy; }; struct select_data { - u_int idx; + u_int idx; }; struct refresh_data { - u_int py_upper; - u_int py_lower; + u_int py_upper; + u_int py_lower; }; /* Attributes. */ @@ -449,6 +456,7 @@ int op_list(char *, int, char **); int client_init(char *, struct client_ctx *, int); int client_main(struct client_ctx *); void client_write_server(struct client_ctx *, enum hdrtype, void *, size_t); +void client_fill_sessid(struct sessid *, char [MAXNAMELEN]); /* client-msg.c */ int client_msg_dispatch(struct client_ctx *, char **); @@ -465,6 +473,7 @@ int server_start(char *); int server_msg_dispatch(struct client *); /* server-fn.c */ +struct session *server_find_sessid(struct sessid *, char **); void server_write_message(struct client *, const char *, ...); void server_write_client(struct client *, enum hdrtype, void *, size_t); void server_write_client2(