diff --git a/CHANGES b/CHANGES index f284576e..93b3dafc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,17 @@ +02 June 2008 + +* BIG CHANGE: -s and -c to specify session name and client name are now passed + after the command rather than before it. So, for example: + + tmux -s0 neww + + Becomes: + + tmux neww -s0 + + This is to allow them to be used in the (forthcoming) configuration file + THIS WILL BREAK ANY CURRENT SCRIPTS OR ALIASES USING -s OR -c. + 01 June 2008 * Bug fix: don't die if -k passed to link-window and the destination doesn't @@ -316,4 +330,4 @@ (including mutt, emacs). No status bar yet and no key remapping or other customisation. -$Id: CHANGES,v 1.96 2008-06-01 20:32:41 nicm Exp $ +$Id: CHANGES,v 1.97 2008-06-02 18:08:16 nicm Exp $ diff --git a/Makefile b/Makefile index 3301b558..c32e7201 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.53 2008-06-01 20:20:25 nicm Exp $ +# $Id: Makefile,v 1.54 2008-06-02 18:08:16 nicm Exp $ .SUFFIXES: .c .o .y .h .PHONY: clean update-index.html upload-index.html @@ -17,8 +17,8 @@ META?= \002 # C-b SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ xmalloc.c xmalloc-debug.c input.c input-keys.c screen.c screen-display.c \ - window.c session.c log.c client.c client-msg.c client-fn.c \ - key-string.c key-bindings.c resize.c cmd.c cmd-new-session.c \ + window.c session.c log.c client.c client-msg.c client-fn.c cfg.c \ + key-string.c key-bindings.c resize.c cmd.c cmd-generic.c \ cmd-detach-client.c cmd-list-sessions.c cmd-new-window.c cmd-bind-key.c \ cmd-unbind-key.c cmd-previous-window.c cmd-last-window.c cmd-list-keys.c \ cmd-set-option.c cmd-rename-window.c cmd-select-window.c \ @@ -27,8 +27,8 @@ SRCS= tmux.c server.c server-msg.c server-fn.c buffer.c buffer-poll.c status.c \ cmd-link-window.c cmd-unlink-window.c cmd-next-window.c cmd-send-keys.c \ cmd-swap-window.c cmd-rename-session.c cmd-kill-session.c \ cmd-switch-client.c cmd-has-session.c cmd-scroll-mode.c cmd-copy-mode.c \ - cmd-paste-buffer.c window-scroll.c window-more.c window-copy.c \ - tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c + cmd-paste-buffer.c cmd-new-session.c window-scroll.c window-more.c \ + window-copy.c tty.c tty-keys.c tty-write.c screen-write.c screen-redraw.c CC?= cc INCDIRS+= -I. -I- -I/usr/local/include diff --git a/TODO b/TODO index 6234eb0b..4fcdc6fc 100644 --- a/TODO +++ b/TODO @@ -70,6 +70,13 @@ - poll(2) is broken on OS X/Darwin, a workaround for this would be nice - different screen model? layers perhaps? hmm +--- +[18:20] *priteau* i found something in tmux that could be tweaked to be better +[18:21] *priteau* in screen, when you type ^A-D, you can actually keep ctrl down + when typing the D +[18:21] *priteau* in tmux, you have to release ctrl for the command to work +--- + -- For 0.3 -------------------------------------------------------------------- - chmod +x socket when any client is attached (upd in lost/accept) - clear EOL etc CANNOT rely on term using the current colour/attr and probably diff --git a/cfg.c b/cfg.c new file mode 100644 index 00000000..4b4b2476 --- /dev/null +++ b/cfg.c @@ -0,0 +1,212 @@ +/* $Id: cfg.c,v 1.1 2008-06-02 18:08:16 nicm Exp $ */ + +/* + * Copyright (c) 2008 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include "tmux.h" + +/* + * Config file parser. Pretty quick and simple, each line is parsed into a + * argv array and executed as a command. + */ + +char *cfg_string(FILE *, char, int); +void printflike2 cfg_print(struct cmd_ctx *, const char *, ...); +void printflike2 cfg_error(struct cmd_ctx *, const char *, ...); + +void printflike2 +cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...) +{ +} + +void printflike2 +cfg_error(struct cmd_ctx *ctx, const char *fmt, ...) +{ + va_list ap; + char *msg; + + va_start(ap, fmt); + xvasprintf(&msg, fmt, ap); + va_end(ap); + + *msg = toupper((u_char) *msg); + // XXX + log_warnx("%s", msg); + xfree(msg); +} + +int +load_cfg(const char *path, char **cause) +{ + FILE *f; + int ch, argc; + u_int line; + char **argv, *buf, *s; + size_t len; + struct cmd *cmd; + struct cmd_ctx ctx; + + if ((f = fopen(path, "rb")) == NULL) { + xasprintf(cause, "%s: %s", path, strerror(errno)); + return (1); + } + + argv = NULL; + argc = 0; + + buf = NULL; + len = 0; + + line = 1; + while ((ch = getc(f)) != EOF) { + switch (ch) { + case '#': + /* Comment: discard until EOL. */ + while ((ch = getc(f)) != '\n' && ch != EOF) + ; + line++; + break; + case '\'': + if ((s = cfg_string(f, '\'', 0)) == NULL) + goto error; + argv = xrealloc(argv, argc + 1, sizeof (char *)); + argv[argc++] = s; + break; + case '"': + if ((s = cfg_string(f, '"', 1)) == NULL) + goto error; + argv = xrealloc(argv, argc + 1, sizeof (char *)); + argv[argc++] = s; + break; + case '\n': + case EOF: + case ' ': + case '\t': + if (len == 0) + break; + buf[len] = '\0'; + + argv = xrealloc(argv, argc + 1, sizeof (char *)); + argv[argc++] = buf; + + buf = NULL; + len = 0; + + if (ch != '\n' && ch != EOF) + break; + line++; + + if ((cmd = cmd_parse(argc, argv, cause)) == NULL) { + if (*cause != NULL) + xfree(*cause); /* XXX */ + goto error; + } + + ctx.cursession = NULL; + ctx.curclient = NULL; + + ctx.error = cfg_error; + ctx.print = cfg_print; + + ctx.cmdclient = NULL; + ctx.flags = CMD_KEY; + + cmd_exec(cmd, &ctx); + + cmd_free(cmd); + + while (--argc >= 0) + xfree(argv[argc]); + argc = 0; + break; + default: + if (len >= SIZE_MAX - 2) + goto error; + + buf = xrealloc(buf, 1, len + 1); + buf[len++] = ch; + break; + } + } + + fclose(f); + + return (0); + +error: + while (--argc > 0) + xfree(argv[argc]); + xfree(argv); + + if (buf != NULL) + xfree(buf); + + xasprintf(cause, "%s: error at line %u", path, line); + return (1); +} + +char * +cfg_string(FILE *f, char endch, int esc) +{ + int ch; + char *buf; + size_t len; + + buf = NULL; + len = 0; + + while ((ch = getc(f)) != endch) { + switch (ch) { + case EOF: + xfree(buf); + return (NULL); + case '\\': + if (!esc) + break; + switch (ch = getc(f)) { + case EOF: + xfree(buf); + return (NULL); + case 'r': + ch = '\r'; + break; + case 'n': + ch = '\n'; + break; + case 't': + ch = '\t'; + break; + } + break; + } + + if (len >= SIZE_MAX - 2) { + xfree(buf); + return (NULL); + } + buf = xrealloc(buf, 1, len + 1); + buf[len++] = ch; + } + + buf[len] = '\0'; + return (buf); +} diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 1741b36e..e9c336df 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-attach-session.c,v 1.11 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-attach-session.c,v 1.12 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -26,19 +26,21 @@ * Attach existing session to the current terminal. */ -int cmd_attach_session_parse(void **, int, char **, char **); +int cmd_attach_session_parse(struct cmd *, void **, int, char **, char **); void cmd_attach_session_exec(void *, struct cmd_ctx *); void cmd_attach_session_send(void *, struct buffer *); void cmd_attach_session_recv(void **, struct buffer *); void cmd_attach_session_free(void *); struct cmd_attach_session_data { + char *sname; int flag_detach; }; const struct cmd_entry cmd_attach_session_entry = { - "attach-session", "attach", "[-d]", - CMD_CANTNEST|CMD_NOCLIENT, + "attach-session", "attach", + "[-d] [-s session-name]", + CMD_CANTNEST, cmd_attach_session_parse, cmd_attach_session_exec, cmd_attach_session_send, @@ -47,19 +49,24 @@ const struct cmd_entry cmd_attach_session_entry = { }; int -cmd_attach_session_parse(void **ptr, int argc, char **argv, char **cause) +cmd_attach_session_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_attach_session_data *data; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->flag_detach = 0; - while ((opt = getopt(argc, argv, "dn:")) != EOF) { + while ((opt = getopt(argc, argv, "ds:")) != EOF) { switch (opt) { case 'd': data->flag_detach = 1; break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -72,8 +79,7 @@ cmd_attach_session_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_attach_session_entry.name, cmd_attach_session_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_attach_session_free(data); return (-1); @@ -83,11 +89,15 @@ void cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_attach_session_data *data = ptr; + struct session *s; char *cause; if (ctx->flags & CMD_KEY) return; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { ctx->error(ctx, "not a terminal"); return; @@ -100,8 +110,8 @@ cmd_attach_session_exec(void *ptr, struct cmd_ctx *ctx) } if (data->flag_detach) - server_write_session(ctx->session, MSG_DETACH, NULL, 0); - ctx->cmdclient->session = ctx->session; + server_write_session(s, MSG_DETACH, NULL, 0); + ctx->cmdclient->session = s; server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); recalculate_sizes(); @@ -114,6 +124,7 @@ cmd_attach_session_send(void *ptr, struct buffer *b) struct cmd_attach_session_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); } void @@ -123,6 +134,7 @@ cmd_attach_session_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); } void @@ -130,5 +142,7 @@ cmd_attach_session_free(void *ptr) { struct cmd_attach_session_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); xfree(data); } diff --git a/cmd-bind-key.c b/cmd-bind-key.c index 537a12f5..cff6c445 100644 --- a/cmd-bind-key.c +++ b/cmd-bind-key.c @@ -1,4 +1,4 @@ -/* $Id: cmd-bind-key.c,v 1.8 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-bind-key.c,v 1.9 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -26,7 +26,7 @@ * Bind a key to a command, this recurses through cmd_*. */ -int cmd_bind_key_parse(void **, int, char **, char **); +int cmd_bind_key_parse(struct cmd *, void **, int, char **, char **); void cmd_bind_key_exec(void *, struct cmd_ctx *); void cmd_bind_key_send(void *, struct buffer *); void cmd_bind_key_recv(void **, struct buffer *); @@ -38,8 +38,9 @@ struct cmd_bind_key_data { }; const struct cmd_entry cmd_bind_key_entry = { - "bind-key", "bind", "key command [arguments]", - CMD_NOCLIENT|CMD_NOSESSION, + "bind-key", "bind", + "key command [arguments]", + 0, cmd_bind_key_parse, cmd_bind_key_exec, cmd_bind_key_send, @@ -48,7 +49,8 @@ const struct cmd_entry cmd_bind_key_entry = { }; int -cmd_bind_key_parse(void **ptr, int argc, char **argv, char **cause) +cmd_bind_key_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_bind_key_data *data; int opt; @@ -80,8 +82,7 @@ cmd_bind_key_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_bind_key_entry.name, cmd_bind_key_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_bind_key_free(data); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index e9b30022..84d5c748 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-copy-mode.c,v 1.4 2007-12-06 10:04:42 nicm Exp $ */ +/* $Id: cmd-copy-mode.c,v 1.5 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,22 +30,26 @@ void cmd_copy_mode_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_copy_mode_entry = { - "copy-mode", NULL, "", - CMD_NOCLIENT, - NULL, + "copy-mode", NULL, + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_copy_mode_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void cmd_copy_mode_exec(unused void *ptr, struct cmd_ctx *ctx) { - struct window *w = ctx->session->curw->window; + struct session *s; + + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; if (ctx->flags & CMD_KEY) - window_set_mode(w, &window_copy_mode); + window_set_mode(s->curw->window, &window_copy_mode); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-detach-client.c b/cmd-detach-client.c index 64a31b85..fd0e5f55 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -1,4 +1,4 @@ -/* $Id: cmd-detach-client.c,v 1.1 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-detach-client.c,v 1.2 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -29,19 +29,25 @@ void cmd_detach_client_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_detach_client_entry = { - "detach-client", "detach", "", - CMD_NOSESSION, - NULL, + "detach-client", "detach", + CMD_CLIENTONLY_USAGE, + 0, + cmd_clientonly_parse, cmd_detach_client_exec, - NULL, - NULL, - NULL + cmd_clientonly_send, + cmd_clientonly_recv, + cmd_clientonly_free }; void -cmd_detach_client_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_detach_client_exec(void *ptr, struct cmd_ctx *ctx) { - server_write_client(ctx->client, MSG_DETACH, NULL, 0); + struct client *c; + + if ((c = cmd_clientonly_get(ptr, ctx)) == NULL) + return; + + server_write_client(c, MSG_DETACH, NULL, 0); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-generic.c b/cmd-generic.c new file mode 100644 index 00000000..49d0f9a4 --- /dev/null +++ b/cmd-generic.c @@ -0,0 +1,175 @@ +/* $Id: cmd-generic.c,v 1.1 2008-06-02 18:08:16 nicm Exp $ */ + +/* + * Copyright (c) 2008 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "tmux.h" + +struct cmd_clientonly_data { + char *cname; +}; + +struct cmd_sessiononly_data { + char *sname; +}; + +int +cmd_clientonly_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) +{ + struct cmd_clientonly_data *data; + int opt; + + *ptr = data = xmalloc(sizeof *data); + data->cname = NULL; + + while ((opt = getopt(argc, argv, "c:")) != EOF) { + switch (opt) { + case 'c': + data->cname = xstrdup(optarg); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + if (argc != 0) + goto usage; + + return (0); + +usage: + usage(cause, "%s %s", self->entry->name, self->entry->usage); + + self->entry->free(data); + return (-1); +} + +void +cmd_clientonly_send(void *ptr, struct buffer *b) +{ + struct cmd_clientonly_data *data = ptr; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->cname); +} + +void +cmd_clientonly_recv(void **ptr, struct buffer *b) +{ + struct cmd_clientonly_data *data; + + *ptr = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->cname = cmd_recv_string(b); +} + +void +cmd_clientonly_free(void *ptr) +{ + struct cmd_clientonly_data *data = ptr; + + if (data->cname != NULL) + xfree(data->cname); + xfree(data); +} + +struct client * +cmd_clientonly_get(void *ptr, struct cmd_ctx *ctx) +{ + struct cmd_clientonly_data *data = ptr; + + if (data != NULL) + return (cmd_find_client(ctx, data->cname)); + return (cmd_find_client(ctx, NULL)); +} + +int +cmd_sessiononly_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) +{ + struct cmd_sessiononly_data *data; + int opt; + + *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; + + while ((opt = getopt(argc, argv, "s:")) != EOF) { + switch (opt) { + case 's': + data->sname = xstrdup(optarg); + break; + default: + goto usage; + } + } + argc -= optind; + argv += optind; + if (argc != 0) + goto usage; + + return (0); + +usage: + usage(cause, "%s %s", self->entry->name, self->entry->usage); + + self->entry->free(data); + return (-1); +} + +void +cmd_sessiononly_send(void *ptr, struct buffer *b) +{ + struct cmd_sessiononly_data *data = ptr; + + buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); +} + +void +cmd_sessiononly_recv(void **ptr, struct buffer *b) +{ + struct cmd_sessiononly_data *data; + + *ptr = data = xmalloc(sizeof *data); + buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); +} + +void +cmd_sessiononly_free(void *ptr) +{ + struct cmd_sessiononly_data *data = ptr; + + if (data->sname != NULL) + xfree(data->sname); + xfree(data); +} + +struct session * +cmd_sessiononly_get(void *ptr, struct cmd_ctx *ctx) +{ + struct cmd_sessiononly_data *data = ptr; + + if (data != NULL) + return (cmd_find_session(ctx, data->sname)); + return (cmd_find_session(ctx, NULL)); +} diff --git a/cmd-has-session.c b/cmd-has-session.c index b6d3fdf5..b7d14a48 100644 --- a/cmd-has-session.c +++ b/cmd-has-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-has-session.c,v 1.3 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-has-session.c,v 1.4 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -32,8 +32,9 @@ void cmd_has_session_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_has_session_entry = { - "has-session", "has", "", - CMD_NOCLIENT, + "has-session", "has", + "", + 0, NULL, cmd_has_session_exec, NULL, diff --git a/cmd-kill-session.c b/cmd-kill-session.c index 21cb6025..cb9bf33f 100644 --- a/cmd-kill-session.c +++ b/cmd-kill-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-kill-session.c,v 1.5 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-kill-session.c,v 1.6 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -33,30 +33,35 @@ void cmd_kill_session_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_kill_session_entry = { - "kill-session", NULL, "", - CMD_NOCLIENT, - NULL, + "kill-session", NULL, + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_kill_session_exec, - NULL, - NULL, - NULL, + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void -cmd_kill_session_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_kill_session_exec(void *ptr, struct cmd_ctx *ctx) { + struct session *s; struct client *c; u_int i; + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c->session == ctx->session) { + if (c->session == s) { c->session = NULL; server_write_client(c, MSG_EXIT, NULL, 0); } } - session_destroy(ctx->session); + session_destroy(s); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-kill-window.c b/cmd-kill-window.c index 13742e19..5370fdc3 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-kill-window.c,v 1.7 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-kill-window.c,v 1.8 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,19 +27,21 @@ * Destroy window. */ -int cmd_kill_window_parse(void **, int, char **, char **); +int cmd_kill_window_parse(struct cmd *, void **, int, char **, char **); void cmd_kill_window_exec(void *, struct cmd_ctx *); void cmd_kill_window_send(void *, struct buffer *); void cmd_kill_window_recv(void **, struct buffer *); void cmd_kill_window_free(void *); struct cmd_kill_window_data { + char *sname; int idx; }; const struct cmd_entry cmd_kill_window_entry = { - "kill-window", "killw", "[-i index]", - CMD_NOCLIENT, + "kill-window", "killw", + "[-i index] [-s session-name]", + 0, cmd_kill_window_parse, cmd_kill_window_exec, cmd_kill_window_send, @@ -48,16 +50,18 @@ const struct cmd_entry cmd_kill_window_entry = { }; int -cmd_kill_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_kill_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_kill_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->idx = -1; - while ((opt = getopt(argc, argv, "i:")) != EOF) { + while ((opt = getopt(argc, argv, "i:s:")) != EOF) { switch (opt) { case 'i': data->idx = strtonum(optarg, 0, INT_MAX, &errstr); @@ -66,6 +70,9 @@ cmd_kill_window_parse(void **ptr, int argc, char **argv, char **cause) goto error; } break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -78,8 +85,7 @@ cmd_kill_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_kill_window_entry.name, cmd_kill_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_kill_window_free(data); @@ -89,9 +95,9 @@ error: void cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx) { - struct cmd_kill_window_data *data = ptr, std = { -1 }; + struct cmd_kill_window_data *data = ptr, std = { NULL, -1 }; + struct session *s; struct client *c; - struct winlinks *wwl = &ctx->session->windows; struct winlink *wl; u_int i; int destroyed; @@ -99,17 +105,20 @@ cmd_kill_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) data = &std; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if (data->idx == -1) - wl = ctx->session->curw; - else if ((wl = winlink_find_by_index(wwl, data->idx)) == NULL) { + wl = s->curw; + else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) { ctx->error(ctx, "no window %d", data->idx); return; } - destroyed = session_detach(ctx->session, wl); + destroyed = session_detach(s, wl); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != ctx->session) + if (c == NULL || c->session != s) continue; if (destroyed) { c->session = NULL; @@ -128,6 +137,7 @@ cmd_kill_window_send(void *ptr, struct buffer *b) struct cmd_kill_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); } void @@ -144,5 +154,7 @@ cmd_kill_window_free(void *ptr) { struct cmd_kill_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); xfree(data); } diff --git a/cmd-last-window.c b/cmd-last-window.c index e68289cd..88e0a538 100644 --- a/cmd-last-window.c +++ b/cmd-last-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-last-window.c,v 1.6 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-last-window.c,v 1.7 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,20 +30,26 @@ void cmd_last_window_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_last_window_entry = { - "last-window", "last", "", - CMD_NOCLIENT, - NULL, + "last-window", "last", + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_last_window_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void -cmd_last_window_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_last_window_exec(void *ptr, struct cmd_ctx *ctx) { - if (session_last(ctx->session) == 0) - server_redraw_session(ctx->session); + struct session *s; + + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + + if (session_last(s) == 0) + server_redraw_session(s); else ctx->error(ctx, "no last window"); diff --git a/cmd-link-window.c b/cmd-link-window.c index 45cb4876..72b2e03b 100644 --- a/cmd-link-window.c +++ b/cmd-link-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-link-window.c,v 1.10 2008-06-01 20:32:41 nicm Exp $ */ +/* $Id: cmd-link-window.c,v 1.11 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,13 +27,14 @@ * Link a window into another session. */ -int cmd_link_window_parse(void **, int, char **, char **); +int cmd_link_window_parse(struct cmd *, void **, int, char **, char **); void cmd_link_window_exec(void *, struct cmd_ctx *); void cmd_link_window_send(void *, struct buffer *); void cmd_link_window_recv(void **, struct buffer *); void cmd_link_window_free(void *); struct cmd_link_window_data { + char *sname; int flag_detached; int flag_kill; int dstidx; @@ -42,8 +43,9 @@ struct cmd_link_window_data { }; const struct cmd_entry cmd_link_window_entry = { - "link-window", "linkw", "[-dk] [-i index] name index", - CMD_NOCLIENT, + "link-window", "linkw", + "[-dk] [-s session-name] [-i index] session-name index", + 0, cmd_link_window_parse, cmd_link_window_exec, cmd_link_window_send, @@ -52,21 +54,26 @@ const struct cmd_entry cmd_link_window_entry = { }; int -cmd_link_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_link_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_link_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->flag_detached = 0; data->flag_kill = 0; data->dstidx = -1; data->srcidx = -1; data->srcname = NULL; - while ((opt = getopt(argc, argv, "dki:")) != EOF) { + while ((opt = getopt(argc, argv, "di:ks:")) != EOF) { switch (opt) { + case 'd': + data->flag_detached = 1; + break; case 'i': data->dstidx = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) { @@ -74,12 +81,12 @@ cmd_link_window_parse(void **ptr, int argc, char **argv, char **cause) goto error; } break; - case 'd': - data->flag_detached = 1; - break; case 'k': data->flag_kill = 1; break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -99,8 +106,7 @@ cmd_link_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_link_window_entry.name, cmd_link_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_link_window_free(data); @@ -111,12 +117,15 @@ void cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_link_window_data *data = ptr; - struct session *dst = ctx->session, *src; + struct session *s, *src; struct winlink *wl, *wl2; if (data == NULL) return; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if ((src = session_find(data->srcname)) == NULL) { ctx->error(ctx, "session not found: %s", data->srcname); return; @@ -137,7 +146,7 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) if (data->dstidx < 0) data->dstidx = -1; if (data->flag_kill && data->dstidx != -1) { - wl2 = winlink_find_by_index(&dst->windows, data->dstidx); + wl2 = winlink_find_by_index(&s->windows, data->dstidx); if (wl2 == NULL) { ctx->error(ctx, "no window %d", data->dstidx); return; @@ -147,16 +156,16 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) * Can't use session_detach as it will destroy session if this * makes it empty. */ - session_cancelbell(dst, wl2); - winlink_remove(&dst->windows, wl2); + session_cancelbell(s, wl2); + winlink_remove(&s->windows, wl2); /* Force select/redraw if current. */ - if (wl2 == dst->curw) { + if (wl2 == s->curw) { data->flag_detached = 0; - dst->curw = NULL; + s->curw = NULL; } - if (wl2 == dst->lastw) - dst->lastw = NULL; + if (wl2 == s->lastw) + s->lastw = NULL; /* * Can't error out after this or there could be an empty @@ -164,17 +173,17 @@ cmd_link_window_exec(void *ptr, struct cmd_ctx *ctx) */ } - wl = session_attach(dst, wl->window, data->dstidx); + wl = session_attach(s, wl->window, data->dstidx); if (wl == NULL) { ctx->error(ctx, "index in use: %d", data->dstidx); return; } if (!data->flag_detached) { - session_select(dst, wl->idx); - server_redraw_session(dst); + session_select(s, wl->idx); + server_redraw_session(s); } else - server_status_session(dst); + server_status_session(s); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -186,6 +195,7 @@ cmd_link_window_send(void *ptr, struct buffer *b) struct cmd_link_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); cmd_send_string(b, data->srcname); } @@ -196,6 +206,7 @@ cmd_link_window_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); data->srcname = cmd_recv_string(b); } @@ -204,6 +215,8 @@ cmd_link_window_free(void *ptr) { struct cmd_link_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); if (data->srcname != NULL) xfree(data->srcname); xfree(data); diff --git a/cmd-list-clients.c b/cmd-list-clients.c index 54743c42..e3624b2f 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-clients.c,v 1.3 2007-11-27 19:23:33 nicm Exp $ */ +/* $Id: cmd-list-clients.c,v 1.4 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -31,8 +31,9 @@ void cmd_list_clients_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_list_clients_entry = { - "list-clients", "lsc", "", - CMD_NOCLIENT|CMD_NOSESSION, + "list-clients", "lsc", + "", + 0, NULL, cmd_list_clients_exec, NULL, diff --git a/cmd-list-keys.c b/cmd-list-keys.c index f4bb6bf1..c5d622e9 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-keys.c,v 1.5 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-list-keys.c,v 1.6 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,8 +30,9 @@ void cmd_list_keys_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_list_keys_entry = { - "list-keys", "lsk", "", - CMD_NOCLIENT|CMD_NOSESSION, + "list-keys", "lsk", + "", + 0, NULL, cmd_list_keys_exec, NULL, diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c index 8b9fd201..2c86d7e5 100644 --- a/cmd-list-sessions.c +++ b/cmd-list-sessions.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-sessions.c,v 1.9 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-list-sessions.c,v 1.10 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -32,7 +32,7 @@ void cmd_list_sessions_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_list_sessions_entry = { "list-sessions", "ls", "", - CMD_NOCLIENT|CMD_NOSESSION, + 0, NULL, cmd_list_sessions_exec, NULL, diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 056af295..55d5a92f 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -1,4 +1,4 @@ -/* $Id: cmd-list-windows.c,v 1.15 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-list-windows.c,v 1.16 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,24 +30,29 @@ void cmd_list_windows_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_list_windows_entry = { - "list-windows", "lsw", NULL, - CMD_NOCLIENT, - NULL, + "list-windows", "lsw", + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_list_windows_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void cmd_list_windows_exec(unused void *ptr, struct cmd_ctx *ctx) { + struct session *s; struct winlink *wl; struct window *w; u_int i; unsigned long long size; - RB_FOREACH(wl, winlinks, &ctx->session->windows) { + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + + RB_FOREACH(wl, winlinks, &s->windows) { w = wl->window; size = 0; diff --git a/cmd-new-session.c b/cmd-new-session.c index aff19eab..02975173 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-session.c,v 1.19 2007-12-06 09:46:21 nicm Exp $ */ +/* $Id: cmd-new-session.c,v 1.20 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -26,7 +26,7 @@ * Create a new session and attach to the current terminal unless -d is given. */ -int cmd_new_session_parse(void **, int, char **, char **); +int cmd_new_session_parse(struct cmd *, void **, int, char **, char **); void cmd_new_session_exec(void *, struct cmd_ctx *); void cmd_new_session_send(void *, struct buffer *); void cmd_new_session_recv(void **, struct buffer *); @@ -42,7 +42,7 @@ struct cmd_new_session_data { const struct cmd_entry cmd_new_session_entry = { "new-session", "new", "[-d] [-s session-name] [-n window-name] [command]", - CMD_STARTSERVER|CMD_NOCLIENT|CMD_NOSESSION|CMD_CANTNEST, + CMD_STARTSERVER|CMD_CANTNEST, cmd_new_session_parse, cmd_new_session_exec, cmd_new_session_send, @@ -51,7 +51,8 @@ const struct cmd_entry cmd_new_session_entry = { }; int -cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause) +cmd_new_session_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_new_session_data *data; int opt; @@ -88,8 +89,7 @@ cmd_new_session_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_new_session_entry.name, cmd_new_session_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_new_session_free(data); return (-1); diff --git a/cmd-new-window.c b/cmd-new-window.c index 71d922f3..3ee85c17 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-new-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-new-window.c,v 1.15 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,13 +27,14 @@ * Create a new window. */ -int cmd_new_window_parse(void **, int, char **, char **); +int cmd_new_window_parse(struct cmd *, void **, int, char **, char **); void cmd_new_window_exec(void *, struct cmd_ctx *); void cmd_new_window_send(void *, struct buffer *); void cmd_new_window_recv(void **, struct buffer *); void cmd_new_window_free(void *); struct cmd_new_window_data { + char *sname; char *name; char *cmd; int idx; @@ -41,8 +42,9 @@ struct cmd_new_window_data { }; const struct cmd_entry cmd_new_window_entry = { - "new-window", "neww", "[-d] [-i index] [-n name] [command]", - CMD_NOCLIENT, + "new-window", "neww", + "[-d] [-s session-name] [-i index] [-n name] [command]", + 0, cmd_new_window_parse, cmd_new_window_exec, cmd_new_window_send, @@ -51,19 +53,21 @@ const struct cmd_entry cmd_new_window_entry = { }; int -cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_new_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_new_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->idx = -1; data->flag_detached = 0; data->name = NULL; data->cmd = NULL; - while ((opt = getopt(argc, argv, "di:n:")) != EOF) { + while ((opt = getopt(argc, argv, "di:n:s:")) != EOF) { switch (opt) { case 'i': data->idx = strtonum(optarg, 0, INT_MAX, &errstr); @@ -78,6 +82,9 @@ cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause) case 'd': data->flag_detached = 1; break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -93,8 +100,7 @@ cmd_new_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_new_window_entry.name, cmd_new_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_new_window_free(data); @@ -105,7 +111,8 @@ void cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_new_window_data *data = ptr; - struct cmd_new_window_data std = { NULL, NULL, -1, 0 }; + struct cmd_new_window_data std = { NULL, NULL, NULL, -1, 0 }; + struct session *s; struct winlink *wl; char *cmd; @@ -116,18 +123,21 @@ cmd_new_window_exec(void *ptr, struct cmd_ctx *ctx) if (cmd == NULL) cmd = default_command; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if (data->idx < 0) data->idx = -1; - wl = session_new(ctx->session, data->name, cmd, data->idx); + wl = session_new(s, data->name, cmd, data->idx); if (wl == NULL) { ctx->error(ctx, "command failed: %s", cmd); return; } if (!data->flag_detached) { - session_select(ctx->session, wl->idx); - server_redraw_session(ctx->session); + session_select(s, wl->idx); + server_redraw_session(s); } else - server_status_session(ctx->session); + server_status_session(s); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -139,6 +149,7 @@ cmd_new_window_send(void *ptr, struct buffer *b) struct cmd_new_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); cmd_send_string(b, data->name); cmd_send_string(b, data->cmd); } @@ -150,6 +161,7 @@ cmd_new_window_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); data->name = cmd_recv_string(b); data->cmd = cmd_recv_string(b); } @@ -159,6 +171,8 @@ cmd_new_window_free(void *ptr) { struct cmd_new_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); if (data->name != NULL) xfree(data->name); if (data->cmd != NULL) diff --git a/cmd-next-window.c b/cmd-next-window.c index 4495558e..e07aaa0b 100644 --- a/cmd-next-window.c +++ b/cmd-next-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-next-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-next-window.c,v 1.7 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,20 +30,26 @@ void cmd_next_window_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_next_window_entry = { - "next-window", "next", "", - CMD_NOCLIENT, - NULL, + "next-window", "next", + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_next_window_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void -cmd_next_window_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_next_window_exec(void *ptr, struct cmd_ctx *ctx) { - if (session_next(ctx->session) == 0) - server_redraw_session(ctx->session); + struct session *s; + + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + + if (session_next(s) == 0) + server_redraw_session(s); else ctx->error(ctx, "no next window"); diff --git a/cmd-paste-buffer.c b/cmd-paste-buffer.c index 349feb48..30146ad4 100644 --- a/cmd-paste-buffer.c +++ b/cmd-paste-buffer.c @@ -1,4 +1,4 @@ -/* $Id: cmd-paste-buffer.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-paste-buffer.c,v 1.3 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -31,25 +31,29 @@ void cmd_paste_buffer_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_paste_buffer_entry = { - "paste-buffer", NULL, "paste", - CMD_NOCLIENT, - NULL, + "paste-buffer", "paste", + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_paste_buffer_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void cmd_paste_buffer_exec(unused void *ptr, struct cmd_ctx *ctx) { - struct window *w = ctx->session->curw->window; + struct session *s; + struct window *w; - if (ctx->flags & CMD_KEY) { - if (paste_buffer != NULL && *paste_buffer != '\0') { - buffer_write( - w->out, paste_buffer, strlen(paste_buffer)); - } + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + w = s->curw->window; + + if (ctx->flags & CMD_KEY && + paste_buffer != NULL && *paste_buffer != '\0') { + buffer_write(w->out, paste_buffer, strlen(paste_buffer)); } if (ctx->cmdclient != NULL) diff --git a/cmd-previous-window.c b/cmd-previous-window.c index d0423998..dd7560ce 100644 --- a/cmd-previous-window.c +++ b/cmd-previous-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-previous-window.c,v 1.6 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-previous-window.c,v 1.7 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,20 +30,26 @@ void cmd_previous_window_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_previous_window_entry = { - "previous-window", "prev", "", - CMD_NOCLIENT, - NULL, + "previous-window", "prev", + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_previous_window_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void -cmd_previous_window_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_previous_window_exec(void *ptr, struct cmd_ctx *ctx) { - if (session_previous(ctx->session) == 0) - server_redraw_session(ctx->session); + struct session *s; + + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; + + if (session_previous(s) == 0) + server_redraw_session(s); else ctx->error(ctx, "no previous window"); diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index ba2ce5bf..4c1e6327 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -1,4 +1,4 @@ -/* $Id: cmd-refresh-client.c,v 1.1 2007-11-16 21:12:31 nicm Exp $ */ +/* $Id: cmd-refresh-client.c,v 1.2 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -29,19 +29,25 @@ void cmd_refresh_client_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_refresh_client_entry = { - "refresh-client", "refresh", "", + "refresh-client", "refresh", + CMD_CLIENTONLY_USAGE, 0, - NULL, + cmd_clientonly_parse, cmd_refresh_client_exec, - NULL, - NULL, - NULL + cmd_clientonly_send, + cmd_clientonly_recv, + cmd_clientonly_free }; void -cmd_refresh_client_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_refresh_client_exec(void *ptr, struct cmd_ctx *ctx) { - server_redraw_client(ctx->client); + struct client *c; + + if ((c = cmd_clientonly_get(ptr, ctx)) == NULL) + return; + + server_redraw_client(c); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-rename-session.c b/cmd-rename-session.c index 498bacd2..8a057543 100644 --- a/cmd-rename-session.c +++ b/cmd-rename-session.c @@ -1,4 +1,4 @@ -/* $Id: cmd-rename-session.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-rename-session.c,v 1.5 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,19 +27,21 @@ * Change session name. */ -int cmd_rename_session_parse(void **, int, char **, char **); +int cmd_rename_session_parse(struct cmd *, void **, int, char **, char **); void cmd_rename_session_exec(void *, struct cmd_ctx *); void cmd_rename_session_send(void *, struct buffer *); void cmd_rename_session_recv(void **, struct buffer *); void cmd_rename_session_free(void *); struct cmd_rename_session_data { + char *sname; char *newname; }; const struct cmd_entry cmd_rename_session_entry = { - "rename-session", "rename", "new-name", - CMD_NOCLIENT, + "rename-session", "rename", + "[-s session-name] new-name", + 0, cmd_rename_session_parse, cmd_rename_session_exec, cmd_rename_session_send, @@ -48,16 +50,21 @@ const struct cmd_entry cmd_rename_session_entry = { }; int -cmd_rename_session_parse(void **ptr, int argc, char **argv, char **cause) +cmd_rename_session_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_rename_session_data *data; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->newname = NULL; - while ((opt = getopt(argc, argv, "")) != EOF) { + while ((opt = getopt(argc, argv, "s:")) != EOF) { switch (opt) { + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -72,8 +79,7 @@ cmd_rename_session_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_rename_session_entry.name, cmd_rename_session_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_rename_session_free(data); return (-1); @@ -83,12 +89,16 @@ void cmd_rename_session_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_rename_session_data *data = ptr; + struct session *s; if (data == NULL) return; - xfree(ctx->session->name); - ctx->session->name = xstrdup(data->newname); + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + + xfree(s->name); + s->name = xstrdup(data->newname); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -100,6 +110,7 @@ cmd_rename_session_send(void *ptr, struct buffer *b) struct cmd_rename_session_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); cmd_send_string(b, data->newname); } @@ -110,6 +121,7 @@ cmd_rename_session_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); data->newname = cmd_recv_string(b); } @@ -118,6 +130,8 @@ cmd_rename_session_free(void *ptr) { struct cmd_rename_session_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); if (data->newname != NULL) xfree(data->newname); xfree(data); diff --git a/cmd-rename-window.c b/cmd-rename-window.c index 5ed0c161..c0d20acf 100644 --- a/cmd-rename-window.c +++ b/cmd-rename-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-rename-window.c,v 1.14 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-rename-window.c,v 1.15 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,20 +27,22 @@ * Rename window by index. */ -int cmd_rename_window_parse(void **, int, char **, char **); +int cmd_rename_window_parse(struct cmd *, void **, int, char **, char **); void cmd_rename_window_exec(void *, struct cmd_ctx *); void cmd_rename_window_send(void *, struct buffer *); void cmd_rename_window_recv(void **, struct buffer *); void cmd_rename_window_free(void *); struct cmd_rename_window_data { + char *sname; int idx; char *newname; }; const struct cmd_entry cmd_rename_window_entry = { - "rename-window", "renamew", "[-i index] new-name", - CMD_NOCLIENT, + "rename-window", "renamew", + "[-i index] [-s session-name] new-name", + 0, cmd_rename_window_parse, cmd_rename_window_exec, cmd_rename_window_send, @@ -49,17 +51,19 @@ const struct cmd_entry cmd_rename_window_entry = { }; int -cmd_rename_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_rename_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_rename_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->idx = -1; data->newname = NULL; - while ((opt = getopt(argc, argv, "i:")) != EOF) { + while ((opt = getopt(argc, argv, "i:s:")) != EOF) { switch (opt) { case 'i': data->idx = strtonum(optarg, 0, INT_MAX, &errstr); @@ -68,6 +72,9 @@ cmd_rename_window_parse(void **ptr, int argc, char **argv, char **cause) goto error; } break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -82,8 +89,7 @@ cmd_rename_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_rename_window_entry.name, cmd_rename_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_rename_window_free(data); @@ -94,22 +100,25 @@ void cmd_rename_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_rename_window_data *data = ptr; - struct winlinks *wwl = &ctx->session->windows; + struct session *s; struct winlink *wl; if (data == NULL) return; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if (data->idx == -1) - wl = ctx->session->curw; - else if ((wl = winlink_find_by_index(wwl, data->idx)) == NULL) { + wl = s->curw; + else if ((wl = winlink_find_by_index(&s->windows, data->idx)) == NULL) { ctx->error(ctx, "no window %d", data->idx); return; } xfree(wl->window->name); wl->window->name = xstrdup(data->newname); - server_status_session(ctx->session); + server_status_session(s); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -121,6 +130,7 @@ cmd_rename_window_send(void *ptr, struct buffer *b) struct cmd_rename_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); cmd_send_string(b, data->newname); } @@ -131,6 +141,7 @@ cmd_rename_window_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); data->newname = cmd_recv_string(b); } @@ -139,6 +150,8 @@ cmd_rename_window_free(void *ptr) { struct cmd_rename_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); if (data->newname != NULL) xfree(data->newname); xfree(data); diff --git a/cmd-scroll-mode.c b/cmd-scroll-mode.c index 2d444a9a..a7252e8b 100644 --- a/cmd-scroll-mode.c +++ b/cmd-scroll-mode.c @@ -1,4 +1,4 @@ -/* $Id: cmd-scroll-mode.c,v 1.6 2007-12-06 10:04:42 nicm Exp $ */ +/* $Id: cmd-scroll-mode.c,v 1.7 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,22 +30,26 @@ void cmd_scroll_mode_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_scroll_mode_entry = { - "scroll-mode", NULL, "", - CMD_NOCLIENT, - NULL, + "scroll-mode", NULL, + CMD_SESSIONONLY_USAGE, + 0, + cmd_sessiononly_parse, cmd_scroll_mode_exec, - NULL, - NULL, - NULL + cmd_sessiononly_send, + cmd_sessiononly_recv, + cmd_sessiononly_free }; void -cmd_scroll_mode_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_scroll_mode_exec(void *ptr, struct cmd_ctx *ctx) { - struct window *w = ctx->session->curw->window; + struct session *s; + + if ((s = cmd_sessiononly_get(ptr, ctx)) == NULL) + return; if (ctx->flags & CMD_KEY) - window_set_mode(w, &window_scroll_mode); + window_set_mode(s->curw->window, &window_scroll_mode); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-select-window.c b/cmd-select-window.c index 896b18cb..c3eee8b9 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-select-window.c,v 1.11 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-select-window.c,v 1.12 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,19 +27,21 @@ * Select window by index. */ -int cmd_select_window_parse(void **, int, char **, char **); +int cmd_select_window_parse(struct cmd *, void **, int, char **, char **); void cmd_select_window_exec(void *, struct cmd_ctx *); void cmd_select_window_send(void *, struct buffer *); void cmd_select_window_recv(void **, struct buffer *); void cmd_select_window_free(void *); struct cmd_select_window_data { + char *sname; int idx; }; const struct cmd_entry cmd_select_window_entry = { - "select-window", "selectw", "index", - CMD_NOCLIENT, + "select-window", "selectw", + "[-s session-name] index", + 0, cmd_select_window_parse, cmd_select_window_exec, cmd_select_window_send, @@ -58,20 +60,26 @@ cmd_select_window_default(void **ptr, int key) struct cmd_select_window_data *data; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->idx = key - '0'; } int -cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_select_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_select_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; - while ((opt = getopt(argc, argv, "")) != EOF) { + while ((opt = getopt(argc, argv, "s:")) != EOF) { switch (opt) { + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -90,8 +98,7 @@ cmd_select_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_select_window_entry.name, cmd_select_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_select_window_free(data); @@ -102,13 +109,17 @@ void cmd_select_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_select_window_data *data = ptr; + struct session *s; if (data == NULL) return; - switch (session_select(ctx->session, data->idx)) { + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + + switch (session_select(s, data->idx)) { case 0: - server_redraw_session(ctx->session); + server_redraw_session(s); break; case 1: break; @@ -127,6 +138,7 @@ cmd_select_window_send(void *ptr, struct buffer *b) struct cmd_select_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); } void @@ -136,6 +148,7 @@ cmd_select_window_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); } void @@ -143,5 +156,7 @@ cmd_select_window_free(void *ptr) { struct cmd_select_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); xfree(data); } diff --git a/cmd-send-keys.c b/cmd-send-keys.c index 25ee1c48..c4ffc366 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-keys.c,v 1.1 2008-06-01 20:20:25 nicm Exp $ */ +/* $Id: cmd-send-keys.c,v 1.2 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -27,19 +27,20 @@ * Change session name. */ -int cmd_send_keys_parse(void **, int, char **, char **); +int cmd_send_keys_parse(struct cmd *, void **, int, char **, char **); void cmd_send_keys_exec(void *, struct cmd_ctx *); void cmd_send_keys_send(void *, struct buffer *); void cmd_send_keys_recv(void **, struct buffer *); void cmd_send_keys_free(void *); struct cmd_send_keys_data { + char *cname; u_int nkeys; int *keys; }; const struct cmd_entry cmd_send_keys_entry = { - "send-keys", "send", "key ...", + "send-keys", "send", "[-c client-name] key ...", 0, cmd_send_keys_parse, cmd_send_keys_exec, @@ -49,18 +50,23 @@ const struct cmd_entry cmd_send_keys_entry = { }; int -cmd_send_keys_parse(void **ptr, int argc, char **argv, char **cause) +cmd_send_keys_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_send_keys_data *data; int opt, key; char *s; *ptr = data = xmalloc(sizeof *data); + data->cname = NULL; data->nkeys = 0; data->keys = NULL; - while ((opt = getopt(argc, argv, "")) != EOF) { + while ((opt = getopt(argc, argv, "c:")) != EOF) { switch (opt) { + case 'c': + data->cname = xstrdup(optarg); + break; default: goto usage; } @@ -89,8 +95,7 @@ cmd_send_keys_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_send_keys_entry.name, cmd_send_keys_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_send_keys_free(data); return (-1); @@ -100,13 +105,17 @@ void cmd_send_keys_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_send_keys_data *data = ptr; + struct client *c; u_int i; if (data == NULL) return; + if ((c = cmd_find_client(ctx, data->cname)) == NULL) + return; + for (i = 0; i < data->nkeys; i++) - window_key(ctx->client->session->curw->window, data->keys[i]); + window_key(c->session->curw->window, data->keys[i]); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -118,6 +127,7 @@ cmd_send_keys_send(void *ptr, struct buffer *b) struct cmd_send_keys_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->cname); buffer_write(b, data->keys, data->nkeys * sizeof *data->keys); } @@ -128,6 +138,7 @@ cmd_send_keys_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->cname = cmd_recv_string(b); data->keys = xcalloc(data->nkeys, sizeof *data->keys); buffer_read(b, data->keys, data->nkeys * sizeof *data->keys); } @@ -137,6 +148,8 @@ cmd_send_keys_free(void *ptr) { struct cmd_send_keys_data *data = ptr; + if (data->cname != NULL) + xfree(data->cname); if (data->keys != NULL) xfree(data->keys); xfree(data); diff --git a/cmd-send-prefix.c b/cmd-send-prefix.c index eb13b673..ce887dd7 100644 --- a/cmd-send-prefix.c +++ b/cmd-send-prefix.c @@ -1,4 +1,4 @@ -/* $Id: cmd-send-prefix.c,v 1.7 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-send-prefix.c,v 1.8 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -30,19 +30,25 @@ void cmd_send_prefix_exec(void *, struct cmd_ctx *); const struct cmd_entry cmd_send_prefix_entry = { - "send-prefix", NULL, NULL, + "send-prefix", NULL, + CMD_CLIENTONLY_USAGE, 0, - NULL, + cmd_clientonly_parse, cmd_send_prefix_exec, - NULL, - NULL, - NULL + cmd_clientonly_send, + cmd_clientonly_recv, + cmd_clientonly_free }; void -cmd_send_prefix_exec(unused void *ptr, struct cmd_ctx *ctx) +cmd_send_prefix_exec(void *ptr, struct cmd_ctx *ctx) { - window_key(ctx->client->session->curw->window, prefix_key); + struct client *c; + + if ((c = cmd_clientonly_get(ptr, ctx)) == NULL) + return; + + window_key(c->session->curw->window, prefix_key); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); diff --git a/cmd-set-option.c b/cmd-set-option.c index d0e86c89..b349b0eb 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $Id: cmd-set-option.c,v 1.15 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-set-option.c,v 1.16 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,7 +28,7 @@ * Set an option. */ -int cmd_set_option_parse(void **, int, char **, char **); +int cmd_set_option_parse(struct cmd *, void **, int, char **, char **); void cmd_set_option_exec(void *, struct cmd_ctx *); void cmd_set_option_send(void *, struct buffer *); void cmd_set_option_recv(void **, struct buffer *); @@ -40,8 +40,9 @@ struct cmd_set_option_data { }; const struct cmd_entry cmd_set_option_entry = { - "set-option", "set", "option value", - CMD_NOCLIENT|CMD_NOSESSION, + "set-option", "set", + "option value", + 0, cmd_set_option_parse, cmd_set_option_exec, cmd_set_option_send, @@ -50,7 +51,8 @@ const struct cmd_entry cmd_set_option_entry = { }; int -cmd_set_option_parse(void **ptr, int argc, char **argv, char **cause) +cmd_set_option_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_set_option_data *data; int opt; @@ -77,8 +79,7 @@ cmd_set_option_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_set_option_entry.name, cmd_set_option_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_set_option_free(data); return (-1); diff --git a/cmd-swap-window.c b/cmd-swap-window.c index 6c4cac0f..4044ad84 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-swap-window.c,v 1.4 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-swap-window.c,v 1.5 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,13 +27,14 @@ * Swap one window with another. */ -int cmd_swap_window_parse(void **, int, char **, char **); +int cmd_swap_window_parse(struct cmd *, void **, int, char **, char **); void cmd_swap_window_exec(void *, struct cmd_ctx *); void cmd_swap_window_send(void *, struct buffer *); void cmd_swap_window_recv(void **, struct buffer *); void cmd_swap_window_free(void *); struct cmd_swap_window_data { + char *sname; int dstidx; int srcidx; char *srcname; @@ -41,8 +42,9 @@ struct cmd_swap_window_data { }; const struct cmd_entry cmd_swap_window_entry = { - "swap-window", "swapw", "[-i index] name index", - CMD_NOCLIENT, + "swap-window", "swapw", + "[-i index] [-s session-name] session-name index", + 0, cmd_swap_window_parse, cmd_swap_window_exec, cmd_swap_window_send, @@ -51,20 +53,25 @@ const struct cmd_entry cmd_swap_window_entry = { }; int -cmd_swap_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_swap_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_swap_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->flag_detached = 0; data->dstidx = -1; data->srcidx = -1; data->srcname = NULL; - while ((opt = getopt(argc, argv, "di:")) != EOF) { + while ((opt = getopt(argc, argv, "di:s:")) != EOF) { switch (opt) { + case 'd': + data->flag_detached = 1; + break; case 'i': data->dstidx = strtonum(optarg, 0, INT_MAX, &errstr); if (errstr != NULL) { @@ -72,8 +79,8 @@ cmd_swap_window_parse(void **ptr, int argc, char **argv, char **cause) goto error; } break; - case 'd': - data->flag_detached = 1; + case 's': + data->sname = xstrdup(optarg); break; default: goto usage; @@ -94,8 +101,7 @@ cmd_swap_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_swap_window_entry.name, cmd_swap_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_swap_window_free(data); @@ -106,13 +112,16 @@ void cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_swap_window_data *data = ptr; - struct session *dst = ctx->session, *src; + struct session *s, *src; struct winlink *srcwl, *dstwl; struct window *w; if (data == NULL) return; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if ((src = session_find(data->srcname)) == NULL) { ctx->error(ctx, "session not found: %s", data->srcname); return; @@ -133,9 +142,9 @@ cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx) if (data->dstidx < 0) data->dstidx = -1; if (data->dstidx == -1) - dstwl = dst->curw; + dstwl = s->curw; else { - dstwl = winlink_find_by_index(&dst->windows, data->dstidx); + dstwl = winlink_find_by_index(&s->windows, data->dstidx); if (dstwl == NULL) { ctx->error(ctx, "no window %d", data->dstidx); return; @@ -147,13 +156,13 @@ cmd_swap_window_exec(void *ptr, struct cmd_ctx *ctx) srcwl->window = w; if (!data->flag_detached) { - session_select(dst, dstwl->idx); - if (src != dst) + session_select(s, dstwl->idx); + if (src != s) session_select(src, srcwl->idx); } server_redraw_session(src); - if (src != dst) - server_redraw_session(dst); + if (src != s) + server_redraw_session(s); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -165,6 +174,7 @@ cmd_swap_window_send(void *ptr, struct buffer *b) struct cmd_swap_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); cmd_send_string(b, data->srcname); } @@ -175,6 +185,7 @@ cmd_swap_window_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->sname = cmd_recv_string(b); data->srcname = cmd_recv_string(b); } @@ -183,6 +194,8 @@ cmd_swap_window_free(void *ptr) { struct cmd_swap_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); if (data->srcname != NULL) xfree(data->srcname); xfree(data); diff --git a/cmd-switch-client.c b/cmd-switch-client.c index ca122879..45373469 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -1,4 +1,4 @@ -/* $Id: cmd-switch-client.c,v 1.2 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-switch-client.c,v 1.3 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -28,19 +28,21 @@ * Switch client to a different session. */ -int cmd_switch_client_parse(void **, int, char **, char **); +int cmd_switch_client_parse(struct cmd *, void **, int, char **, char **); void cmd_switch_client_exec(void *, struct cmd_ctx *); void cmd_switch_client_send(void *, struct buffer *); void cmd_switch_client_recv(void **, struct buffer *); void cmd_switch_client_free(void *); struct cmd_switch_client_data { + char *cname; char *name; }; const struct cmd_entry cmd_switch_client_entry = { - "switch-client", "switchc", "session-name", - CMD_NOSESSION, + "switch-client", "switchc", + "session-name", + 0, cmd_switch_client_parse, cmd_switch_client_exec, cmd_switch_client_send, @@ -49,16 +51,21 @@ const struct cmd_entry cmd_switch_client_entry = { }; int -cmd_switch_client_parse(void **ptr, int argc, char **argv, char **cause) +cmd_switch_client_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_switch_client_data *data; int opt; *ptr = data = xmalloc(sizeof *data); + data->cname = NULL; data->name = NULL; - while ((opt = getopt(argc, argv, "")) != EOF) { + while ((opt = getopt(argc, argv, "c:")) != EOF) { switch (opt) { + case 'c': + data->cname = xstrdup(optarg); + break; default: goto usage; } @@ -73,8 +80,7 @@ cmd_switch_client_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_switch_client_entry.name, cmd_switch_client_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); cmd_switch_client_free(data); return (-1); @@ -84,20 +90,23 @@ void cmd_switch_client_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_switch_client_data *data = ptr; + struct client *c; struct session *s; if (data == NULL) return; + if ((c = cmd_find_client(ctx, data->cname)) == NULL) + return; + if ((s = session_find(data->name)) == NULL) { ctx->error(ctx, "session not found: %s", data->name); return; } - - ctx->client->session = s; + c->session = s; recalculate_sizes(); - server_redraw_client(ctx->client); + server_redraw_client(c); if (ctx->cmdclient != NULL) server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); @@ -109,6 +118,7 @@ cmd_switch_client_send(void *ptr, struct buffer *b) struct cmd_switch_client_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->cname); cmd_send_string(b, data->name); } @@ -119,6 +129,7 @@ cmd_switch_client_recv(void **ptr, struct buffer *b) *ptr = data = xmalloc(sizeof *data); buffer_read(b, data, sizeof *data); + data->cname = cmd_recv_string(b); data->name = cmd_recv_string(b); } @@ -127,6 +138,8 @@ cmd_switch_client_free(void *ptr) { struct cmd_switch_client_data *data = ptr; + if (data->cname != NULL) + xfree(data->cname); if (data->name != NULL) xfree(data->name); xfree(data); diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c index fd4e775f..68e61dec 100644 --- a/cmd-unbind-key.c +++ b/cmd-unbind-key.c @@ -1,4 +1,4 @@ -/* $Id: cmd-unbind-key.c,v 1.8 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-unbind-key.c,v 1.9 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -26,7 +26,7 @@ * Unbind key from command. */ -int cmd_unbind_key_parse(void **, int, char **, char **); +int cmd_unbind_key_parse(struct cmd *, void **, int, char **, char **); void cmd_unbind_key_exec(void *, struct cmd_ctx *); void cmd_unbind_key_send(void *, struct buffer *); void cmd_unbind_key_recv(void **, struct buffer *); @@ -37,8 +37,9 @@ struct cmd_unbind_key_data { }; const struct cmd_entry cmd_unbind_key_entry = { - "unbind-key", "unbind", "key", - CMD_NOCLIENT|CMD_NOSESSION, + "unbind-key", "unbind", + "key", + 0, cmd_unbind_key_parse, cmd_unbind_key_exec, cmd_unbind_key_send, @@ -47,7 +48,8 @@ const struct cmd_entry cmd_unbind_key_entry = { }; int -cmd_unbind_key_parse(void **ptr, int argc, char **argv, char **cause) +cmd_unbind_key_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_unbind_key_data *data; int opt; @@ -73,8 +75,7 @@ cmd_unbind_key_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_unbind_key_entry.name, cmd_unbind_key_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: xfree(data); diff --git a/cmd-unlink-window.c b/cmd-unlink-window.c index 577a2e2d..46f45035 100644 --- a/cmd-unlink-window.c +++ b/cmd-unlink-window.c @@ -1,4 +1,4 @@ -/* $Id: cmd-unlink-window.c,v 1.5 2007-12-06 09:46:22 nicm Exp $ */ +/* $Id: cmd-unlink-window.c,v 1.6 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -27,19 +27,21 @@ * Unlink a window, unless it would be destroyed by doing so (only one link). */ -int cmd_unlink_window_parse(void **, int, char **, char **); +int cmd_unlink_window_parse(struct cmd *, void **, int, char **, char **); void cmd_unlink_window_exec(void *, struct cmd_ctx *); void cmd_unlink_window_send(void *, struct buffer *); void cmd_unlink_window_recv(void **, struct buffer *); void cmd_unlink_window_free(void *); struct cmd_unlink_window_data { - int idx; + char *sname; + int idx; }; const struct cmd_entry cmd_unlink_window_entry = { - "unlink-window", "unlinkw", "[-i index]", - CMD_NOCLIENT, + "unlink-window", "unlinkw", + "[-i index] [-s session-name]", + 0, cmd_unlink_window_parse, cmd_unlink_window_exec, cmd_unlink_window_send, @@ -48,16 +50,18 @@ const struct cmd_entry cmd_unlink_window_entry = { }; int -cmd_unlink_window_parse(void **ptr, int argc, char **argv, char **cause) +cmd_unlink_window_parse( + struct cmd *self, void **ptr, int argc, char **argv, char **cause) { struct cmd_unlink_window_data *data; const char *errstr; int opt; *ptr = data = xmalloc(sizeof *data); + data->sname = NULL; data->idx = -1; - while ((opt = getopt(argc, argv, "i:")) != EOF) { + while ((opt = getopt(argc, argv, "i:s:")) != EOF) { switch (opt) { case 'i': data->idx = strtonum(optarg, 0, INT_MAX, &errstr); @@ -66,6 +70,9 @@ cmd_unlink_window_parse(void **ptr, int argc, char **argv, char **cause) goto error; } break; + case 's': + data->sname = xstrdup(optarg); + break; default: goto usage; } @@ -78,8 +85,7 @@ cmd_unlink_window_parse(void **ptr, int argc, char **argv, char **cause) return (0); usage: - usage(cause, "%s %s", - cmd_unlink_window_entry.name, cmd_unlink_window_entry.usage); + usage(cause, "%s %s", self->entry->name, self->entry->usage); error: cmd_unlink_window_free(data); @@ -90,8 +96,8 @@ void cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx) { struct cmd_unlink_window_data *data = ptr; + struct session *s; struct client *c; - struct winlinks *wwl = &ctx->session->windows; struct winlink *wl; u_int i; int destroyed; @@ -99,12 +105,15 @@ cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx) if (data == NULL) return; + if ((s = cmd_find_session(ctx, data->sname)) == NULL) + return; + if (data->idx < 0) data->idx = -1; if (data->idx == -1) - wl = ctx->session->curw; + wl = s->curw; else { - wl = winlink_find_by_index(wwl, data->idx); + wl = winlink_find_by_index(&s->windows, data->idx); if (wl == NULL) { ctx->error(ctx, "no window %d", data->idx); return; @@ -116,10 +125,10 @@ cmd_unlink_window_exec(void *ptr, struct cmd_ctx *ctx) return; } - destroyed = session_detach(ctx->session, wl); + destroyed = session_detach(s, wl); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != ctx->session) + if (c == NULL || c->session != s) continue; if (destroyed) { c->session = NULL; @@ -138,6 +147,7 @@ cmd_unlink_window_send(void *ptr, struct buffer *b) struct cmd_unlink_window_data *data = ptr; buffer_write(b, data, sizeof *data); + cmd_send_string(b, data->sname); } void @@ -154,5 +164,7 @@ cmd_unlink_window_free(void *ptr) { struct cmd_unlink_window_data *data = ptr; + if (data->sname != NULL) + xfree(data->sname); xfree(data); } diff --git a/cmd.c b/cmd.c index 52a2cf83..2232af16 100644 --- a/cmd.c +++ b/cmd.c @@ -1,4 +1,4 @@ -/* $Id: cmd.c,v 1.34 2008-06-01 20:20:25 nicm Exp $ */ +/* $Id: cmd.c,v 1.35 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -20,6 +20,7 @@ #include #include +#include #include "tmux.h" @@ -105,7 +106,7 @@ cmd_parse(int argc, char **argv, char **cause) cmd = xmalloc(sizeof *cmd); cmd->entry = entry; if (entry->parse != NULL) { - if (entry->parse(&cmd->data, argc, argv, cause) != 0) { + if (entry->parse(cmd, &cmd->data, argc, argv, cause) != 0) { xfree(cmd); return (NULL); } @@ -226,3 +227,89 @@ cmd_recv_string(struct buffer *b) return (s); } + +/* + * Attempt to establish session. This looks first at the command-line argument + * if any, then sees if there is a session in the context, then finally tries + * the session data passed up from the client $TMUX variable. + */ +struct session * +cmd_find_session(struct cmd_ctx *ctx, const char *arg) +{ + struct session *s; + struct msg_command_data *data = ctx->msgdata; + u_int i, n; + + if (arg != NULL) { + if ((s = session_find(arg)) == NULL) { + ctx->error(ctx, "session not found: %s", arg); + return (NULL); + } + return (s); + } + + if (ctx->cursession != NULL) + return (ctx->cursession); + + if (data != NULL && data->pid != -1) { + if (data->pid != getpid()) { + ctx->error(ctx, "wrong server: %lld", data->pid); + return (NULL); + } + if (data->idx > ARRAY_LENGTH(&sessions)) { + ctx->error(ctx, "index out of range: %d", data->idx); + return (NULL); + } + if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) { + ctx->error(ctx, "session doesn't exist: %u", data->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) { + ctx->error(ctx, "no sessions found"); + return (NULL); + } + if (n != 1) { + ctx->error(ctx, "multiple sessions and session not specified"); + return (NULL); + } + return (s); +} + +/* + * Figure out the client. Try the current client (if any) first, then try to + * figure it out from the argument. + */ +struct client * +cmd_find_client(unused struct cmd_ctx *ctx, const char *arg) +{ + struct client *c; + u_int i; + + if (ctx->curclient != NULL) + return (ctx->curclient); + + if (arg == NULL) { + ctx->error(ctx, "must specify a client"); + return (NULL); + } + + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c != NULL && strcmp(arg, c->tty.path) == 0) + return (c); + } + + ctx->error(ctx, "client not found: %s", arg); + return (NULL); +} diff --git a/key-bindings.c b/key-bindings.c index 8acf71f1..96a220f2 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -1,4 +1,4 @@ -/* $Id: key-bindings.c,v 1.25 2007-12-06 21:42:00 nicm Exp $ */ +/* $Id: key-bindings.c,v 1.26 2008-06-02 18:08:16 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -155,14 +155,14 @@ key_bindings_error(struct cmd_ctx *ctx, const char *fmt, ...) va_end(ap); *msg = toupper((u_char) *msg); - server_write_message(ctx->client, "%s", msg); + server_write_message(ctx->curclient, "%s", msg); xfree(msg); } void printflike2 key_bindings_print(struct cmd_ctx *ctx, const char *fmt, ...) { - struct window *w = ctx->session->curw->window; + struct window *w = ctx->cursession->curw->window; va_list ap; window_set_mode(w, &window_more_mode); @@ -188,8 +188,8 @@ key_bindings_dispatch(int key, struct client *c) if (i == ARRAY_LENGTH(&key_bindings)) return; - ctx.session = c->session; - ctx.client = c; + ctx.cursession = c->session; + ctx.curclient = c; ctx.error = key_bindings_error; ctx.print = key_bindings_print; diff --git a/server-fn.c b/server-fn.c index 9da001f5..cf55e238 100644 --- a/server-fn.c +++ b/server-fn.c @@ -1,4 +1,4 @@ -/* $Id: server-fn.c,v 1.36 2007-12-06 09:46:23 nicm Exp $ */ +/* $Id: server-fn.c,v 1.37 2008-06-02 18:08:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -23,57 +23,6 @@ #include "tmux.h" -/* Find session from command message. */ -struct session * -server_extract_session(struct msg_command_data *data, char *name, char **cause) -{ - struct session *s; - u_int i, n; - - if (name != NULL) { - if ((s = session_find(name)) == NULL) { - xasprintf(cause, "session not found: %s", name); - return (NULL); - } - return (s); - } - - if (data->pid != -1) { - if (data->pid != getpid()) { - xasprintf(cause, "wrong server: %lld", data->pid); - return (NULL); - } - if (data->idx > ARRAY_LENGTH(&sessions)) { - xasprintf(cause, "index out of range: %d", data->idx); - return (NULL); - } - if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL) { - xasprintf( - cause, "session doesn't exist: %u", data->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 found"); - return (NULL); - } - if (n != 1) { - xasprintf(cause, "multiple sessions and session not specified"); - return (NULL); - } - return (s); -} - void server_write_client( struct client *c, enum hdrtype type, const void *buf, size_t len) diff --git a/server-msg.c b/server-msg.c index d92aa3c1..ed8b86b6 100644 --- a/server-msg.c +++ b/server-msg.c @@ -1,4 +1,4 @@ -/* $Id: server-msg.c,v 1.43 2007-12-13 18:59:42 nicm Exp $ */ +/* $Id: server-msg.c,v 1.44 2008-06-02 18:08:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -111,16 +111,10 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) struct msg_command_data data; struct cmd_ctx ctx; struct cmd *cmd; - char *name, *client, *cause; - u_int i; - - /* XXX I hate this function. Split it? */ if (hdr->size < sizeof data) fatalx("bad MSG_COMMAND size"); buffer_read(c->in, &data, sizeof data); - name = cmd_recv_string(c->in); - client = cmd_recv_string(c->in); cmd = cmd_recv(c->in); log_debug("got command %s from client %d", cmd->entry->name, c->fd); @@ -128,64 +122,23 @@ server_msg_fn_command(struct hdr *hdr, struct client *c) ctx.error = server_msg_fn_command_error; ctx.print = server_msg_fn_command_print; + ctx.curclient = NULL; + ctx.cursession = NULL; + ctx.msgdata = &data; + ctx.cmdclient = c; ctx.flags = 0; + /* XXX */ if (data.pid != -1 && (cmd->entry->flags & CMD_CANTNEST)) { server_msg_fn_command_error(&ctx, "sessions " "should be nested with care. unset $TMUX to force"); - goto out; - } - - ctx.client = NULL; - if (cmd->entry->flags & CMD_NOCLIENT) { - if (client != NULL) { - server_msg_fn_command_error(&ctx, - "%s: cannot specify a client", cmd->entry->name); - goto out; - } - } else { - if (client == NULL) { - server_msg_fn_command_error(&ctx, - "%s: must specify a client", cmd->entry->name); - goto out; - } - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - /* XXX fnmatch, multi clients etc */ - c = ARRAY_ITEM(&clients, i); - if (c != NULL && strcmp(client, c->tty.path) == 0) - ctx.client = c; - } - if (ctx.client == NULL) { - server_msg_fn_command_error(&ctx, "%s: " - "client not found: %s", cmd->entry->name, client); - goto out; - } - } - - ctx.session = NULL; - if (cmd->entry->flags & CMD_NOSESSION) { - if (name != NULL) { - server_msg_fn_command_error(&ctx, - "%s: cannot specify a session", cmd->entry->name); - goto out; - } - } else { - ctx.session = server_extract_session(&data, name, &cause); - if (ctx.session == NULL) { - server_msg_fn_command_error( - &ctx, "%s: %s", cmd->entry->name, cause); - xfree(cause); - goto out; - } + cmd_free(cmd); + return (0); } cmd_exec(cmd, &ctx); cmd_free(cmd); - -out: - if (name != NULL) - xfree(name); return (0); } diff --git a/server.c b/server.c index dcd115f3..8cfc607c 100644 --- a/server.c +++ b/server.c @@ -1,4 +1,4 @@ -/* $Id: server.c,v 1.45 2008-05-31 20:04:15 nicm Exp $ */ +/* $Id: server.c,v 1.46 2008-06-02 18:08:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -62,6 +62,7 @@ server_start(const char *path) size_t size; mode_t mask; int n, fd, mode; + char *cause; switch (fork()) { case -1: @@ -109,6 +110,13 @@ server_start(const char *path) if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) fatal("fcntl failed"); + /* Load configuration. */ + if (cfg_file != NULL && load_cfg(cfg_file, &cause) != 0) { + log_warnx("%s", cause); + xfree(cause); + exit(1); + } + if (daemon(1, 1) != 0) fatal("daemon failed"); log_debug("server daemonised, pid now %ld", (long) getpid()); @@ -135,7 +143,7 @@ server_main(const char *srv_path, int srv_fd) ARRAY_INIT(&sessions); key_bindings_init(); - + pfds = NULL; while (!sigterm) { /* Initialise pollfd array. */ diff --git a/tmux.c b/tmux.c index c7ee8e49..89c7fca7 100644 --- a/tmux.c +++ b/tmux.c @@ -1,4 +1,4 @@ -/* $Id: tmux.c,v 1.46 2007-12-06 18:28:55 nicm Exp $ */ +/* $Id: tmux.c,v 1.47 2008-06-02 18:08:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -42,6 +42,7 @@ const char *_malloc_options = "AJX"; volatile sig_atomic_t sigwinch; volatile sig_atomic_t sigterm; +char *cfg_file; char *default_command; char *paste_buffer; int bell_action; @@ -59,8 +60,7 @@ usage(char **ptr, const char *fmt, ...) char *msg; va_list ap; -#define USAGE \ - "usage: %s [-v] [-S socket-path] [-s session-name] [-c client-tty]" +#define USAGE "usage: %s [-v] [-f file] [-S socket-path]" if (fmt == NULL) { xasprintf(ptr, USAGE " command [flags]", __progname); } else { @@ -182,22 +182,19 @@ main(int argc, char **argv) struct hdr hdr; const char *shell; struct passwd *pw; - char *client, *path, *name, *cause; + char *client, *path, *name, *cause, *home; char rpath[MAXPATHLEN]; int n, opt; client = path = name = NULL; - while ((opt = getopt(argc, argv, "c:S:s:vV")) != EOF) { + while ((opt = getopt(argc, argv, "c:f:S:s:vV")) != EOF) { switch (opt) { - case 'c': - client = xstrdup(optarg); + case 'f': + cfg_file = xstrdup(optarg); break; case 'S': path = xstrdup(optarg); break; - case 's': - name = xstrdup(optarg); - break; case 'v': debug_level++; break; @@ -225,6 +222,26 @@ main(int argc, char **argv) paste_buffer = NULL; + if (cfg_file == NULL) { + home = getenv("HOME"); + if (home == NULL || *home == '\0') { + pw = getpwuid(getuid()); + if (pw != NULL) + home = pw->pw_dir; + endpwent(); + } + xasprintf(&cfg_file, "%s/%s", home, DEFAULT_CFG); + if (access(cfg_file, R_OK) != 0) { + xfree(cfg_file); + cfg_file = NULL; + } + } else { + if (access(cfg_file, R_OK) != 0) { + log_warn("%s", cfg_file); + exit(1); + } + } + if (path == NULL) { xasprintf(&path, "%s/%s-%lu", _PATH_TMP, __progname, (u_long) getuid()); @@ -265,14 +282,10 @@ main(int argc, char **argv) } memset(&cctx, 0, sizeof cctx); - if (!(cmd->entry->flags & CMD_NOSESSION) || - (cmd->entry->flags & CMD_CANTNEST)) - client_fill_session(&data); + client_fill_session(&data); if (client_init(rpath, &cctx, cmd->entry->flags & CMD_STARTSERVER) != 0) exit(1); b = buffer_create(BUFSIZ); - cmd_send_string(b, name); - cmd_send_string(b, client); cmd_send(cmd, b); cmd_free(cmd); @@ -280,9 +293,6 @@ main(int argc, char **argv) MSG_COMMAND, &data, sizeof data, BUFFER_OUT(b), BUFFER_USED(b)); buffer_destroy(b); - if (name != NULL) - xfree(name); - for (;;) { pfd.fd = cctx.srv_fd; pfd.events = POLLIN; diff --git a/tmux.h b/tmux.h index ff5dbb41..830e059b 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.116 2008-06-01 20:20:25 nicm Exp $ */ +/* $Id: tmux.h,v 1.117 2008-06-02 18:08:17 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -63,6 +63,9 @@ extern char *__progname; #define TTY_NAME_MAX 32 #endif +/* Default configuration file. */ +#define DEFAULT_CFG ".tmux.conf" + /* Fatal errors. */ #define fatal(msg) log_fatal("%s: %s", __func__, msg); #define fatalx(msg) log_fatalx("%s: %s", __func__, msg); @@ -621,8 +624,9 @@ struct client_ctx { struct cmd_ctx { struct client *cmdclient; - struct client *client; - struct session *session; + struct client *curclient; + struct session *cursession; + struct msg_command_data *msgdata; void (*print)(struct cmd_ctx *, const char *, ...); void (*error)(struct cmd_ctx *, const char *, ...); @@ -631,29 +635,27 @@ struct cmd_ctx { int flags; }; +struct cmd { + const struct cmd_entry *entry; + void *data; +}; + struct cmd_entry { const char *name; const char *alias; const char *usage; #define CMD_STARTSERVER 0x1 -#define CMD_NOSESSION 0x2 -#define CMD_NOCLIENT 0x4 -#define CMD_CANTNEST 0x8 +#define CMD_CANTNEST 0x2 int flags; - int (*parse)(void **, int, char **, char **); + int (*parse)(struct cmd *, void **, int, char **, char **); void (*exec)(void *, struct cmd_ctx *); void (*send)(void *, struct buffer *); void (*recv)(void **, struct buffer *); void (*free)(void *); }; -struct cmd { - const struct cmd_entry *entry; - void *data; -}; - /* Key binding. */ struct binding { int key; @@ -683,6 +685,7 @@ extern volatile sig_atomic_t sigterm; #define BELL_ANY 1 #define BELL_CURRENT 2 extern char *default_command; +extern char *cfg_file; extern char *paste_buffer; extern int bell_action; extern int debug_level; @@ -695,6 +698,9 @@ void logfile(const char *); void siginit(void); void sigreset(void); +/* cfg.c */ +int load_cfg(const char *, char **x); + /* tty.c */ void tty_init(struct tty *, char *, char *); int tty_open(struct tty *, char **); @@ -725,6 +731,8 @@ struct cmd *cmd_recv(struct buffer *); void cmd_free(struct cmd *); void cmd_send_string(struct buffer *, const char *); char *cmd_recv_string(struct buffer *); +struct session *cmd_find_session(struct cmd_ctx *, const char *); +struct client *cmd_find_client(struct cmd_ctx *, const char *); extern const struct cmd_entry cmd_attach_session_entry; extern const struct cmd_entry cmd_bind_key_entry; extern const struct cmd_entry cmd_copy_mode_entry; @@ -757,6 +765,22 @@ extern const struct cmd_entry cmd_unbind_key_entry; extern const struct cmd_entry cmd_unlink_window_entry; void cmd_select_window_default(void **, int); +/* cmd-generic.c */ +#define CMD_CLIENTONLY_USAGE "[-c client-name]" +int cmd_clientonly_parse(struct cmd *, void **, int, char **, char **); +void cmd_clientonly_exec(void *, struct cmd_ctx *); +void cmd_clientonly_send(void *, struct buffer *); +void cmd_clientonly_recv(void **, struct buffer *); +void cmd_clientonly_free(void *); +struct client *cmd_clientonly_get(void *, struct cmd_ctx *); +#define CMD_SESSIONONLY_USAGE "[-s session-name]" +int cmd_sessiononly_parse(struct cmd *, void **, int, char **, char **); +void cmd_sessiononly_exec(void *, struct cmd_ctx *); +void cmd_sessiononly_send(void *, struct buffer *); +void cmd_sessiononly_recv(void **, struct buffer *); +void cmd_sessiononly_free(void *); +struct session *cmd_sessiononly_get(void *, struct cmd_ctx *); + /* client.c */ int client_init(const char *, struct client_ctx *, int); int client_flush(struct client_ctx *);