From d762ced298c35d58524433cacb08c5d0a7364f96 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 26 Nov 2012 11:35:28 +0000 Subject: [PATCH 1/7] Call realpath earlier on the socket directory path rather than on the socket file path because the latter may not exist yet and in that case realpath is allowed to fail. From Romain Francoise. --- tmux.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tmux.c b/tmux.c index e01017c9..7bce10ec 100644 --- a/tmux.c +++ b/tmux.c @@ -159,7 +159,7 @@ parseenvironment(void) char * makesocketpath(const char *label) { - char base[MAXPATHLEN], *path, *s; + char base[MAXPATHLEN], realbase[MAXPATHLEN], *path, *s; struct stat sb; u_int uid; @@ -183,7 +183,10 @@ makesocketpath(const char *label) return (NULL); } - xasprintf(&path, "%s/%s", base, label); + if (realpath(base, realbase) == NULL) + strlcpy(realbase, base, sizeof realbase); + + xasprintf(&path, "%s/%s", realbase, label); return (path); } @@ -384,8 +387,7 @@ main(int argc, char **argv) } } free(label); - if (realpath(path, socket_path) == NULL) - strlcpy(socket_path, path, sizeof socket_path); + strlcpy(socket_path, path, sizeof socket_path); free(path); /* Set process title. */ From 991bfcf443de261dfe9be35f9c4d26731f8a2dff Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 09:20:03 +0000 Subject: [PATCH 2/7] Fix session choice so that preferring unattached sessions actually works, reported by Drew Frank. --- cmd.c | 36 ++++++++++++++++++++++++------------ names.c | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/cmd.c b/cmd.c index 3a341b4e..a9594c07 100644 --- a/cmd.c +++ b/cmd.c @@ -116,6 +116,7 @@ const struct cmd_entry *cmd_table[] = { NULL }; +int cmd_session_better(struct session *, struct session *, int); struct session *cmd_choose_session_list(struct sessionslist *); struct session *cmd_choose_session(int); struct client *cmd_choose_client(struct clients *); @@ -371,6 +372,24 @@ cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached) return (cmd_choose_session(prefer_unattached)); } +/* Is this session better? */ +int +cmd_session_better(struct session *s, struct session *best, + int prefer_unattached) +{ + if (best == NULL) + return 1; + if (prefer_unattached) { + if (!(best->flags & SESSION_UNATTACHED) && + (s->flags & SESSION_UNATTACHED)) + return 1; + else if ((best->flags & SESSION_UNATTACHED) && + !(s->flags & SESSION_UNATTACHED)) + return 0; + } + return (timercmp(&s->activity_time, &best->activity_time, >)); +} + /* * Find the most recently used session, preferring unattached if the flag is * set. @@ -378,21 +397,14 @@ cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached) struct session * cmd_choose_session(int prefer_unattached) { - struct session *s, *sbest; - struct timeval *tv = NULL; + struct session *s, *best; - sbest = NULL; + best = NULL; RB_FOREACH(s, sessions, &sessions) { - if (tv == NULL || timercmp(&s->activity_time, tv, >) || - (prefer_unattached && - !(sbest->flags & SESSION_UNATTACHED) && - (s->flags & SESSION_UNATTACHED))) { - sbest = s; - tv = &s->activity_time; - } + if (cmd_session_better(s, best, prefer_unattached)) + best = s; } - - return (sbest); + return (best); } /* Find the most recently used session from a list. */ diff --git a/names.c b/names.c index 46708bce..1eb6a675 100644 --- a/names.c +++ b/names.c @@ -76,7 +76,7 @@ window_name_callback(unused int fd, unused short events, void *data) name != NULL && name[0] == '-' && name[1] != '\0') wname = parse_window_name(name + 1); else - wname = parse_window_name(name); + wname = parse_window_name(name); free(name); } From 93224260ae42b8d2c85e702453779b8ff583f561 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 13:52:23 +0000 Subject: [PATCH 3/7] Add window-status-last-* options, from Boris Faure. --- options-table.c | 15 +++++++++++++++ status.c | 11 +++++++++++ tmux.1 | 9 +++++++++ 3 files changed, 35 insertions(+) diff --git a/options-table.c b/options-table.c index 3e471908..d9bbe382 100644 --- a/options-table.c +++ b/options-table.c @@ -686,6 +686,21 @@ const struct options_table_entry window_options_table[] = { .default_str = "#I:#W#F" }, + { .name = "window-status-last-attr", + .type = OPTIONS_TABLE_ATTRIBUTES, + .default_num = 0 + }, + + { .name = "window-status-last-bg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + + { .name = "window-status-last-fg", + .type = OPTIONS_TABLE_COLOUR, + .default_num = 8 + }, + { .name = "window-status-fg", .type = OPTIONS_TABLE_COLOUR, .default_num = 8 diff --git a/status.c b/status.c index 6cbdc6c4..dd4c737c 100644 --- a/status.c +++ b/status.c @@ -705,6 +705,17 @@ status_print( gc->attr = attr; fmt = options_get_string(oo, "window-status-current-format"); } + if (wl == TAILQ_FIRST(&s->lastw)) { + fg = options_get_number(oo, "window-status-last-fg"); + if (fg != 8) + colour_set_fg(gc, fg); + bg = options_get_number(oo, "window-status-last-bg"); + if (bg != 8) + colour_set_bg(gc, bg); + attr = options_get_number(oo, "window-status-last-attr"); + if (attr != 0) + gc->attr = attr; + } if (wl->flags & WINLINK_BELL) { fg = options_get_number(oo, "window-status-bell-fg"); diff --git a/tmux.1 b/tmux.1 index 4bf55443..185a4303 100644 --- a/tmux.1 +++ b/tmux.1 @@ -2823,6 +2823,15 @@ Like .Ar window-status-format , but is the format used when the window is the current window. .Pp +.It Ic window-status-last-attr Ar attributes +Set status line attributes for the last active window. +.Pp +.It Ic window-status-last-bg Ar colour +Set status line background colour for the last active window. +.Pp +.It Ic window-status-last-fg Ar colour +Set status line foreground colour for the last active window. +.Pp .It Ic window-status-fg Ar colour Set status line foreground colour for a single window. .Pp From 6ef4f8e16ce4c8e77f3b5cd9a1f7b4387439d7b5 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 14:26:48 +0000 Subject: [PATCH 4/7] Revert last, after discussion it isn't necessary. From 1fcc7f50aca0e0f3d922f988963362299d75d21d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 14:42:56 +0000 Subject: [PATCH 5/7] When scrolling in copy mode with the mouse, scroll screen rather than moving cursor. This change from Ailin Nemui, alternative to a change from Stephen Hicks. --- window-copy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/window-copy.c b/window-copy.c index 97899595..097c056a 100644 --- a/window-copy.c +++ b/window-copy.c @@ -832,10 +832,10 @@ window_copy_mouse( if (m->event == MOUSE_EVENT_WHEEL) { if (m->wheel == MOUSE_WHEEL_UP) { for (i = 0; i < 5; i++) - window_copy_cursor_up(wp, 0); + window_copy_cursor_up(wp, 1); } else if (m->wheel == MOUSE_WHEEL_DOWN) { for (i = 0; i < 5; i++) - window_copy_cursor_down(wp, 0); + window_copy_cursor_down(wp, 1); if (data->oy == 0) goto reset_mode; } From 4aa4e9fb267a2169c6446da5cc2edaafd56b0195 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 15:09:35 +0000 Subject: [PATCH 6/7] Allow cmd-run-shell to accept -t to specify the pane to display the output, requested by Alexander Tsepkov. --- cmd-run-shell.c | 45 ++++++++++++++++++++++++++++++++++++--------- tmux.1 | 10 ++++++++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/cmd-run-shell.c b/cmd-run-shell.c index dcbcb375..0fe7620b 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -30,13 +30,15 @@ */ enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmd_ctx *); -void cmd_run_shell_callback(struct job *); -void cmd_run_shell_free(void *); + +void cmd_run_shell_callback(struct job *); +void cmd_run_shell_free(void *); +void cmd_run_shell_print(struct job *, const char *); const struct cmd_entry cmd_run_shell_entry = { "run-shell", "run", - "", 1, 1, - "command", + "t:", 1, 1, + CMD_TARGET_PANE_USAGE " command", 0, NULL, NULL, @@ -46,17 +48,42 @@ const struct cmd_entry cmd_run_shell_entry = { struct cmd_run_shell_data { char *cmd; struct cmd_ctx ctx; + u_int wp_id; }; +void +cmd_run_shell_print(struct job *job, const char *msg) +{ + struct cmd_run_shell_data *cdata = job->data; + struct cmd_ctx *ctx = &cdata->ctx; + struct window_pane *wp; + + wp = window_pane_find_by_id(cdata->wp_id); + if (wp == NULL) { + ctx->print(ctx, "%s", msg); + return; + } + + if (window_pane_set_mode(wp, &window_copy_mode) == 0) + window_copy_init_for_output(wp); + if (wp->mode == &window_copy_mode) + window_copy_add(wp, "%s", msg); +} + enum cmd_retval cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct cmd_run_shell_data *cdata; const char *shellcmd = args->argv[0]; + struct window_pane *wp; + + if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) + return (CMD_RETURN_ERROR); cdata = xmalloc(sizeof *cdata); cdata->cmd = xstrdup(args->argv[0]); + cdata->wp_id = wp->id; memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); if (ctx->cmdclient != NULL) @@ -87,7 +114,7 @@ cmd_run_shell_callback(struct job *job) lines = 0; do { if ((line = evbuffer_readline(job->event->input)) != NULL) { - ctx->print(ctx, "%s", line); + cmd_run_shell_print (job, line); lines++; } } while (line != NULL); @@ -98,7 +125,7 @@ cmd_run_shell_callback(struct job *job) memcpy(line, EVBUFFER_DATA(job->event->input), size); line[size] = '\0'; - ctx->print(ctx, "%s", line); + cmd_run_shell_print(job, line); lines++; free(line); @@ -115,10 +142,10 @@ cmd_run_shell_callback(struct job *job) xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode); } if (msg != NULL) { - if (lines != 0) - ctx->print(ctx, "%s", msg); - else + if (lines == 0) ctx->info(ctx, "%s", msg); + else + cmd_run_shell_print(job, msg); free(msg); } } diff --git a/tmux.1 b/tmux.1 index 185a4303..349c23f2 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3394,12 +3394,18 @@ otherwise. Lock each client individually by running the command specified by the .Ic lock-command option. -.It Ic run-shell Ar shell-command +.It Xo Ic run-shell +.Op Fl t Ar target-pane +.Ar shell-command +.Xc .D1 (alias: Ic run ) Execute .Ar shell-command in the background without creating a window. -After it finishes, any output to stdout is displayed in copy mode. +After it finishes, any output to stdout is displayed in copy mode (in the pane +specified by +.Fl t +or the current pane if omitted). If the command doesn't return success, the exit status is also displayed. .It Ic server-info .D1 (alias: Ic info ) From 9b8998aeec9c4dff695ae4108965677d90d9c9c7 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 27 Nov 2012 16:12:29 +0000 Subject: [PATCH 7/7] Correctly aggregate together errors from nested config files (with source-file). Fix by Thomas Adam, reported by Sam Livingstone-Gray --- cfg.c | 11 ++++++++--- cmd-source-file.c | 41 +++++++++++++++++++---------------------- tmux.c | 2 ++ tmux.h | 1 + 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/cfg.c b/cfg.c index ae7d9a30..3da6ea4d 100644 --- a/cfg.c +++ b/cfg.c @@ -34,9 +34,10 @@ void printflike2 cfg_print(struct cmd_ctx *, const char *, ...); void printflike2 cfg_error(struct cmd_ctx *, const char *, ...); -char *cfg_cause; -int cfg_finished; -struct causelist cfg_causes = ARRAY_INITIALIZER; +char *cfg_cause; +int cfg_finished; +int cfg_references; +struct causelist cfg_causes; /* ARGSUSED */ void printflike2 @@ -89,6 +90,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) } n = 0; + cfg_references++; + line = NULL; retval = CMD_RETURN_NORMAL; while ((buf = fgetln(f, &len))) { @@ -171,6 +174,8 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) } fclose(f); + cfg_references--; + return (retval); } diff --git a/cmd-source-file.c b/cmd-source-file.c index 758f959a..0a180d89 100644 --- a/cmd-source-file.c +++ b/cmd-source-file.c @@ -42,35 +42,32 @@ enum cmd_retval cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; - struct causelist causes; - char *cause; - struct window_pane *wp; int retval; u_int i; + char *cause; - ARRAY_INIT(&causes); + retval = load_cfg(args->argv[0], ctx, &cfg_causes); - retval = load_cfg(args->argv[0], ctx, &causes); - if (ARRAY_EMPTY(&causes)) + /* + * If the context for the cmdclient came from tmux's configuration + * file, then return the status of this command now, regardless of the + * error condition. Any errors from parsing a configuration file at + * startup will be handled for us by the server. + */ + if (cfg_references > 0 || + (ctx->curclient == NULL && ctx->cmdclient == NULL)) return (retval); - if (retval == 1 && !RB_EMPTY(&sessions) && ctx->cmdclient != NULL) { - wp = RB_MIN(sessions, &sessions)->curw->window->active; - window_pane_set_mode(wp, &window_copy_mode); - window_copy_init_for_output(wp); - for (i = 0; i < ARRAY_LENGTH(&causes); i++) { - cause = ARRAY_ITEM(&causes, i); - window_copy_add(wp, "%s", cause); - free(cause); - } - } else { - for (i = 0; i < ARRAY_LENGTH(&causes); i++) { - cause = ARRAY_ITEM(&causes, i); - ctx->print(ctx, "%s", cause); - free(cause); - } + /* + * We were called from the command-line in which case print the errors + * gathered here directly. + */ + for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { + cause = ARRAY_ITEM(&cfg_causes, i); + ctx->print(ctx, "%s", cause); + free(cause); } - ARRAY_FREE(&causes); + ARRAY_FREE(&cfg_causes); return (retval); } diff --git a/tmux.c b/tmux.c index 7bce10ec..2428a404 100644 --- a/tmux.c +++ b/tmux.c @@ -330,6 +330,8 @@ main(int argc, char **argv) options_init(&global_w_options, NULL); options_table_populate_tree(window_options_table, &global_w_options); + ARRAY_INIT(&cfg_causes); + /* Enable UTF-8 if the first client is on UTF-8 terminal. */ if (flags & IDENTIFY_UTF8) { options_set_number(&global_s_options, "status-utf8", 1); diff --git a/tmux.h b/tmux.h index 98677f78..2b5f19d8 100644 --- a/tmux.h +++ b/tmux.h @@ -1517,6 +1517,7 @@ __dead void shell_exec(const char *, const char *); /* cfg.c */ extern int cfg_finished; +extern int cfg_references; extern struct causelist cfg_causes; void printflike2 cfg_add_cause(struct causelist *, const char *, ...); int load_cfg(const char *, struct cmd_ctx *, struct causelist *);