summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2017-01-24 22:01:13 +0000
committerThomas Adam <thomas@xteddy.org>2017-01-24 22:01:13 +0000
commit418ab1a553f46996d3524bab5c81b2c66fa7efc6 (patch)
treeb29b61f95da6d7732628cdfb6dcf5e23c2fede5e
parentf38a6bbd816533d01d14c8bbafbb51621e5e1326 (diff)
parentffc28a7765f4b560427404c9679966232655e67e (diff)
Merge branch 'obsd-master'
-rw-r--r--client.c15
-rw-r--r--cmd-attach-session.c18
-rw-r--r--cmd-new-session.c9
-rw-r--r--cmd-set-option.c30
-rw-r--r--cmd-show-messages.c15
-rw-r--r--cmd-string.c82
-rw-r--r--cmd-switch-client.c8
-rw-r--r--cmd.c70
-rw-r--r--environ.c28
-rw-r--r--key-bindings.c2
-rw-r--r--options-table.c18
-rw-r--r--pty.c2
-rw-r--r--tmux.166
-rw-r--r--tmux.h3
-rw-r--r--tty-term.c139
15 files changed, 291 insertions, 214 deletions
diff --git a/client.c b/client.c
index 9be2934c..2f538964 100644
--- a/client.c
+++ b/client.c
@@ -251,16 +251,13 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
* flag.
*/
cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause);
- if (cmdlist == NULL) {
- fprintf(stderr, "%s\n", cause);
- return (1);
- }
- cmdflags &= ~CMD_STARTSERVER;
- TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
- if (cmd->entry->flags & CMD_STARTSERVER)
- cmdflags |= CMD_STARTSERVER;
+ if (cmdlist != NULL) {
+ TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
+ if (cmd->entry->flags & CMD_STARTSERVER)
+ cmdflags |= CMD_STARTSERVER;
+ }
+ cmd_list_free(cmdlist);
}
- cmd_list_free(cmdlist);
}
/* Create client process structure (starts logging). */
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 5807eefc..f61b5930 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -54,7 +54,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
struct client *c = item->client, *c_loop;
struct winlink *wl = item->state.tflag.wl;
struct window_pane *wp = item->state.tflag.wp;
- const char *update;
char *cause, *cwd;
struct format_tree *ft;
@@ -95,12 +94,8 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
server_client_detach(c_loop, MSG_DETACH);
}
}
-
- if (!Eflag) {
- update = options_get_string(s->options,
- "update-environment");
- environ_update(update, c->environ, s->environ);
- }
+ if (!Eflag)
+ environ_update(s->options, c->environ, s->environ);
c->session = s;
server_client_set_key_table(c, NULL);
@@ -116,7 +111,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
free(cause);
return (CMD_RETURN_ERROR);
}
-
if (rflag)
c->flags |= CLIENT_READONLY;
@@ -127,12 +121,8 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
server_client_detach(c_loop, MSG_DETACH);
}
}
-
- if (!Eflag) {
- update = options_get_string(s->options,
- "update-environment");
- environ_update(update, c->environ, s->environ);
- }
+ if (!Eflag)
+ environ_update(s->options, c->environ, s->environ);
c->session = s;
server_client_set_key_table(c, NULL);
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 7df7dcb6..10304bc0 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -73,7 +73,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
struct window *w;
struct environ *env;
struct termios tio, *tiop;
- const char *newname, *target, *update, *errstr, *template;
+ const char *newname, *target, *errstr, *template;
const char *path, *cmd, *cwd, *to_free = NULL;
char **argv, *cause, *cp;
int detached, already_attached, idx, argc;
@@ -234,11 +234,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
/* Construct the environment. */
env = environ_create();
- if (c != NULL && !args_has(args, 'E')) {
- update = options_get_string(global_s_options,
- "update-environment");
- environ_update(update, c->environ, env);
- }
+ if (c != NULL && !args_has(args, 'E'))
+ environ_update(global_s_options, c->environ, env);
/* Create the new session. */
idx = -1 - options_get_number(global_s_options, "base-index");
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 84c12e56..f7e6b730 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -68,6 +68,7 @@ static enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
+ int append = args_has(args, 'a');
struct cmd_find_state *fs = &item->state.tflag;
struct session *s = fs->s;
struct winlink *wl = fs->wl;
@@ -160,17 +161,6 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "not an array: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
- } else if (*name != '@' && options_array_size(parent, NULL) != -1) {
- if (value == NULL) {
- cmdq_error(item, "empty value");
- return (-1);
- }
- if (o == NULL)
- o = options_empty(oo, options_table_entry(parent));
- if (!args_has(args, 'a'))
- options_array_clear(o);
- options_array_assign(o, value);
- return (CMD_RETURN_NORMAL);
}
/* With -o, check this option is not already set. */
@@ -204,16 +194,26 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
options_remove(o);
} else
options_array_set(o, idx, NULL, 0);
- } else if (*name == '@')
- options_set_string(oo, name, args_has(args, 'a'), "%s", value);
- else if (idx == -1) {
+ } else if (*name == '@') {
+ if (value == NULL) {
+ cmdq_error(item, "empty value");
+ return (CMD_RETURN_ERROR);
+ }
+ options_set_string(oo, name, append, "%s", value);
+ } else if (idx == -1 && options_array_size(parent, NULL) == -1) {
error = cmd_set_option_set(self, item, oo, parent, value);
if (error != 0)
return (CMD_RETURN_ERROR);
} else {
+ if (value == NULL) {
+ cmdq_error(item, "empty value");
+ return (CMD_RETURN_ERROR);
+ }
if (o == NULL)
o = options_empty(oo, options_table_entry(parent));
- if (options_array_set(o, idx, value, 1) != 0) {
+ if (idx == -1)
+ options_array_assign(o, value);
+ else if (options_array_set(o, idx, value, append) != 0) {
cmdq_error(item, "invalid index: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-show-messages.c b/cmd-show-messages.c
index 6eaf35d0..143218ba 100644
--- a/cmd-show-messages.c
+++ b/cmd-show-messages.c
@@ -44,17 +44,6 @@ const struct cmd_entry cmd_show_messages_entry = {
.exec = cmd_show_messages_exec
};
-const struct cmd_entry cmd_server_info_entry = {
- .name = "server-info",
- .alias = "info",
-
- .args = { "", 0, 0 },
- .usage = "",
-
- .flags = CMD_AFTERHOOK,
- .exec = cmd_show_messages_exec
-};
-
static int cmd_show_messages_terminals(struct cmdq_item *, int);
static int cmd_show_messages_jobs(struct cmdq_item *, int);
@@ -108,11 +97,11 @@ cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
int done, blank;
done = blank = 0;
- if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
+ if (args_has(args, 'T')) {
blank = cmd_show_messages_terminals(item, blank);
done = 1;
}
- if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
+ if (args_has(args, 'J')) {
cmd_show_messages_jobs(item, blank);
done = 1;
}
diff --git a/cmd-string.c b/cmd-string.c
index 1b96b280..822d35b5 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -54,17 +54,15 @@ cmd_string_ungetc(size_t *p)
(*p)--;
}
-struct cmd_list *
-cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
+int
+cmd_string_split(const char *s, int *rargc, char ***rargv)
{
- size_t p = 0;
- int ch, i, argc = 0;
- char **argv = NULL, *buf = NULL, *t;
- const char *whitespace, *equals;
- size_t len = 0;
- struct cmd_list *cmdlist = NULL;
+ size_t p = 0;
+ int ch, argc = 0, append = 0;
+ char **argv = NULL, *buf = NULL, *t;
+ const char *whitespace, *equals;
+ size_t len = 0;
- *cause = NULL;
for (;;) {
ch = cmd_string_getc(s, &p);
switch (ch) {
@@ -115,43 +113,67 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
argc--;
memmove(argv, argv + 1, argc * (sizeof *argv));
}
- if (argc == 0)
- goto out;
-
- cmdlist = cmd_list_parse(argc, argv, file, line, cause);
- goto out;
+ goto done;
case '~':
- if (buf == NULL) {
- t = cmd_string_expand_tilde(s, &p);
- if (t == NULL)
- goto error;
- cmd_string_copy(&buf, t, &len);
+ if (buf != NULL) {
+ append = 1;
break;
}
- /* FALLTHROUGH */
+ t = cmd_string_expand_tilde(s, &p);
+ if (t == NULL)
+ goto error;
+ cmd_string_copy(&buf, t, &len);
+ break;
default:
+ append = 1;
+ break;
+ }
+ if (append) {
if (len >= SIZE_MAX - 2)
goto error;
-
buf = xrealloc(buf, len + 1);
buf[len++] = ch;
- break;
}
+ append = 0;
}
-error:
- xasprintf(cause, "invalid or unknown command: %s", s);
+done:
+ *rargc = argc;
+ *rargv = argv;
-out:
free(buf);
+ return (0);
- if (argv != NULL) {
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
- }
+error:
+ if (argv != NULL)
+ cmd_free_argv(argc, argv);
+ free(buf);
+ return (-1);
+}
+struct cmd_list *
+cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
+{
+ struct cmd_list *cmdlist = NULL;
+ int argc;
+ char **argv;
+
+ *cause = NULL;
+ if (cmd_string_split(s, &argc, &argv) != 0)
+ goto error;
+ if (argc != 0) {
+ cmdlist = cmd_list_parse(argc, argv, file, line, cause);
+ if (cmdlist == NULL) {
+ cmd_free_argv(argc, argv);
+ goto error;
+ }
+ }
+ cmd_free_argv(argc, argv);
return (cmdlist);
+
+error:
+ xasprintf(cause, "invalid or unknown command: %s", s);
+ return (NULL);
}
static void
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 81f70d9c..cd46db39 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -53,7 +53,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
struct client *c = state->c;
struct session *s = item->state.tflag.s;
struct window_pane *wp;
- const char *tablename, *update;
+ const char *tablename;
struct key_table *table;
if (args_has(args, 'r'))
@@ -102,10 +102,8 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
}
}
- if (!args_has(args, 'E')) {
- update = options_get_string(s->options, "update-environment");
- environ_update(update, c->environ, s->environ);
- }
+ if (!args_has(args, 'E'))
+ environ_update(s->options, c->environ, s->environ);
if (c->session != NULL && c->session != s)
c->last_session = c->session;
diff --git a/cmd.c b/cmd.c
index 79a898ef..f9162fd0 100644
--- a/cmd.c
+++ b/cmd.c
@@ -92,7 +92,6 @@ extern const struct cmd_entry cmd_select_pane_entry;
extern const struct cmd_entry cmd_select_window_entry;
extern const struct cmd_entry cmd_send_keys_entry;
extern const struct cmd_entry cmd_send_prefix_entry;
-extern const struct cmd_entry cmd_server_info_entry;
extern const struct cmd_entry cmd_set_buffer_entry;
extern const struct cmd_entry cmd_set_environment_entry;
extern const struct cmd_entry cmd_set_hook_entry;
@@ -181,7 +180,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_select_window_entry,
&cmd_send_keys_entry,
&cmd_send_prefix_entry,
- &cmd_server_info_entry,
&cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_hook_entry,
@@ -307,21 +305,74 @@ cmd_stringify_argv(int argc, char **argv)
return (buf);
}
+static int
+cmd_try_alias(int *argc, char ***argv)
+{
+ struct options_entry *o;
+ int old_argc = *argc, new_argc;
+ char **old_argv = *argv, **new_argv;
+ u_int size, idx;
+ int i;
+ size_t wanted;
+ const char *s, *cp = NULL;
+
+ o = options_get_only(global_options, "command-alias");
+ if (o == NULL || options_array_size(o, &size) == -1 || size == 0)
+ return (-1);
+
+ wanted = strlen(old_argv[0]);
+ for (idx = 0; idx < size; idx++) {
+ s = options_array_get(o, idx);
+ if (s == NULL)
+ continue;
+
+ cp = strchr(s, '=');
+ if (cp == NULL || (size_t)(cp - s) != wanted)
+ continue;
+ if (strncmp(old_argv[0], s, wanted) == 0)
+ break;
+ }
+ if (idx == size)
+ return (-1);
+
+ if (cmd_string_split(cp + 1, &new_argc, &new_argv) != 0)
+ return (-1);
+
+ *argc = new_argc + old_argc - 1;
+ *argv = xcalloc((*argc) + 1, sizeof **argv);
+
+ for (i = 0; i < new_argc; i++)
+ (*argv)[i] = xstrdup(new_argv[i]);
+ for (i = 1; i < old_argc; i++)
+ (*argv)[new_argc + i - 1] = xstrdup(old_argv[i]);
+
+ log_debug("alias: %s=%s", old_argv[0], cp + 1);
+ for (i = 0; i < *argc; i++)
+ log_debug("alias: argv[%d] = %s", i, (*argv)[i]);
+
+ cmd_free_argv(new_argc, new_argv);
+ return (0);
+}
+
struct cmd *
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
{
+ const char *name;
const struct cmd_entry **entryp, *entry;
struct cmd *cmd;
struct args *args;
char s[BUFSIZ];
- int ambiguous = 0;
+ int ambiguous, allocated = 0;
*cause = NULL;
if (argc == 0) {
xasprintf(cause, "no command");
return (NULL);
}
+ name = argv[0];
+retry:
+ ambiguous = 0;
entry = NULL;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL &&
@@ -341,10 +392,17 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
if (strcmp(entry->name, argv[0]) == 0)
break;
}
+ if ((ambiguous || entry == NULL) &&
+ server_proc != NULL &&
+ !allocated &&
+ cmd_try_alias(&argc, &argv) == 0) {
+ allocated = 1;
+ goto retry;
+ }
if (ambiguous)
goto ambiguous;
if (entry == NULL) {
- xasprintf(cause, "unknown command: %s", argv[0]);
+ xasprintf(cause, "unknown command: %s", name);
return (NULL);
}
@@ -364,6 +422,8 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
cmd->file = xstrdup(file);
cmd->line = line;
+ if (allocated)
+ cmd_free_argv(argc, argv);
return (cmd);
ambiguous:
@@ -377,7 +437,7 @@ ambiguous:
break;
}
s[strlen(s) - 2] = '\0';
- xasprintf(cause, "ambiguous command: %s, could be: %s", argv[0], s);
+ xasprintf(cause, "ambiguous command: %s, could be: %s", name, s);
return (NULL);
usage:
diff --git a/environ.c b/environ.c
index 016d256a..4bb794dd 100644
--- a/environ.c
+++ b/environ.c
@@ -169,25 +169,27 @@ environ_unset(struct environ *env, const char *name)
free(envent);
}
-/*
- * Copy a space-separated list of variables from a destination into a source
- * environment.
- */
+/* Copy variables from a destination into a source * environment. */
void
-environ_update(const char *vars, struct environ *srcenv,
- struct environ *dstenv)
+environ_update(struct options *oo, struct environ *src, struct environ *dst)
{
struct environ_entry *envent;
- char *copyvars, *var, *next;
+ struct options_entry *o;
+ u_int size, idx;
+ const char *value;
- copyvars = next = xstrdup(vars);
- while ((var = strsep(&next, " ")) != NULL) {
- if ((envent = environ_find(srcenv, var)) == NULL)
- environ_clear(dstenv, var);
+ o = options_get(oo, "update-environment");
+ if (o == NULL || options_array_size(o, &size) == -1)
+ return;
+ for (idx = 0; idx < size; idx++) {
+ value = options_array_get(o, idx);
+ if (value == NULL)
+ continue;
+ if ((envent = environ_find(src, value)) == NULL)
+ environ_clear(dst, value);
else
- environ_set(dstenv, envent->name, "%s", envent->value);
+ environ_set(dst, envent->name, "%s", envent->value);
}
- free(copyvars);
}
/* Push environment into the real environment - use after fork(). */
diff --git a/key-bindings.c b/key-bindings.c
index 65cc9b10..4cbb34ec 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -383,7 +383,7 @@ key_bindings_init(void)
for (i = 0; i < nitems(defaults); i++) {
cmdlist = cmd_string_parse(defaults[i], "<default>", i, &cause);
if (cmdlist == NULL)
- fatalx("bad default key");
+ fatalx("bad default key: %s", defaults[i]);
cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
cmd_list_free(cmdlist);
}
diff --git a/options-table.c b/options-table.c
index 5eb2ad5d..403509ba 100644
--- a/options-table.c
+++ b/options-table.c
@@ -64,6 +64,16 @@ const struct options_table_entry options_table[] = {
.default_num = 20
},
+ { .name = "command-alias",
+ .type = OPTIONS_TABLE_ARRAY,
+ .scope = OPTIONS_TABLE_SERVER,
+ .default_str = "split-pane=split-window,"
+ "splitp=split-window,"
+ "server-info=show-messages -JT,"
+ "info=show-messages -JT",
+ .separator = ","
+ },
+
{ .name = "default-terminal",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,
@@ -111,11 +121,12 @@ const struct options_table_entry options_table[] = {
},
{ .name = "terminal-overrides",
- .type = OPTIONS_TABLE_STRING,
+ .type = OPTIONS_TABLE_ARRAY,
.scope = OPTIONS_TABLE_SERVER,
.default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\007"
- ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT"
+ ":Ss=\\E[%p1%d q:Se=\\E[2 q,screen*:XT",
+ .separator = ","
},
{ .name = "assume-paste-time",
@@ -470,11 +481,10 @@ const struct options_table_entry options_table[] = {
},
{ .name = "update-environment",
- .type = OPTIONS_TABLE_STRING,
+ .type = OPTIONS_TABLE_ARRAY,
.scope = OPTIONS_TABLE_SESSION,
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
"SSH_CONNECTION WINDOWID XAUTHORITY"
-
},
{ .name = "visual-activity",
diff --git a/pty.c b/pty.c
index df94623d..012e2f1c 100644
--- a/pty.c
+++ b/pty.c
@@ -53,7 +53,7 @@ pty_fork(int ptmfd, int *fd, char *name, size_t namelen, struct winsize *ws)
struct ptmget ptm;
pid_t pid;
- if ((ioctl(ptmfd, PTMGET, &ptm) == -1))
+ if (ioctl(ptmfd, PTMGET, &ptm) == -1)
return (-1);
strlcpy(name, ptm.sn, namelen);
diff --git a/tmux.1 b/tmux.1
index edb387f5..d0635345 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2414,6 +2414,30 @@ Available server options are:
Set the number of buffers; as new buffers are added to the top of the stack,
old ones are removed from the bottom if necessary to maintain this maximum
length.
+.It Xo Ic command-alias[]
+.Ar name=value
+.Xc
+This is an array of custom aliases for commands.
+If an unknown command matches
+.Ar name ,
+it is replaced with
+.Ar value .
+For example, after:
+.Pp
+.Dl set -s command-alias[2] zoom='resize-pane -Z'
+.Pp
+Using:
+.Pp
+.Dl zoom -t:.1
+.Pp
+Is equivalent to:
+.Pp
+.Dl resize-pane -Z -t:.1
+.Pp
+Note that aliases are expanded when a command is parsed rather than when it is
+executed, so binding an alias with
+.Ic bind-key
+will bind the expanded form.
.It Ic default-terminal Ar terminal
Set the default terminal for new windows created in this session - the
default value of the
@@ -2475,12 +2499,12 @@ disallowedWindowOps: 20,21,SetXprop
Or changing this property from the
.Xr xterm 1
interactive menu when required.
-.It Ic terminal-overrides Ar string
-Contains a list of entries which override terminal descriptions read using
-.Xr terminfo 5 .
-.Ar string
-is a comma-separated list of items each a colon-separated string made up of a
-terminal type pattern (matched using
+.It Ic terminal-overrides[] Ar string
+Allow terminal descriptions read using
+.Xr terminfo 5
+to be overriden.
+Each entry is a colon-separated string made up of a terminal type pattern
+(matched using
.Xr fnmatch 3 )
and a set of
.Em name=value
@@ -2491,26 +2515,14 @@ For example, to set the
.Xr terminfo 5
entry to
.Ql \ee[H\ee[2J
-for all terminal types and the
-.Ql dch1
-entry to
-.Ql \ee[P
-for the
-.Ql rxvt
-terminal type, the option could be set to the string:
-.Bd -literal -offset indent
-"*:clear=\ee[H\ee[2J,rxvt:dch1=\ee[P"
-.Ed
+for all terminal types matching
+.Ql rxvt* :
+.Pp
+.Dl "rxvt*:clear=\ee[H\ee[2J"
.Pp
The terminal entry value is passed through
.Xr strunvis 3
before interpretation.
-The default value forcibly corrects the
-.Ql colors
-entry for terminals which support 256 colours:
-.Bd -literal -offset indent
-"*256col*:colors=256,xterm*:XT"
-.Ed
.El
.Pp
Available session options are:
@@ -2861,19 +2873,15 @@ For how to specify
see the
.Ic message-command-style
option.
-.It Ic update-environment Ar variables
-Set a space-separated string containing a list of environment variables to be
-copied into the session environment when a new session is created or an
-existing session is attached.
+.It Ic update-environment[] Ar variable
+Set list of environment variables to be copied into the session environment
+when a new session is created or an existing session is attached.
Any variables that do not exist in the source environment are set to be
removed from the session environment (as if
.Fl r
was given to the
.Ic set-environment
command).
-The default is
-"DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID
-XAUTHORITY".
.It Xo Ic visual-activity
.Op Ic on | off
.Xc
diff --git a/tmux.h b/tmux.h
index 76a4968e..15fbb726 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1671,7 +1671,7 @@ void printflike(3, 4) environ_set(struct environ *, const char *, const char *,
void environ_clear(struct environ *, const char *);
void environ_put(struct environ *, const char *);
void environ_unset(struct environ *, const char *);
-void environ_update(const char *, struct environ *, struct environ *);
+void environ_update(struct options *, struct environ *, struct environ *);
void environ_push(struct environ *);
void environ_log(struct environ *, const char *);
@@ -1830,6 +1830,7 @@ void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...);
void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
/* cmd-string.c */
+int cmd_string_split(const char *, int *, char ***);
struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **);
/* cmd-wait-for.c */
diff --git a/tty-term.c b/tty-term.c
index 9e29188d..0fcf5205 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -297,86 +297,82 @@ tty_term_strip(const char *s)
}
static void
-tty_term_override(struct tty_term *term, const char *overrides)
+tty_term_override(struct tty_term *term, const char *override)
{
const struct tty_term_code_entry *ent;
struct tty_code *code;
- char *termnext, *termstr;
- char *entnext, *entstr;
- char *s, *ptr, *val;
+ char *next, *s, *copy, *cp, *value;
const char *errstr;
u_int i;
- int n, removeflag;
+ int n, remove;
- s = xstrdup(overrides);
+ copy = next = xstrdup(override);
- termnext = s;
- while ((termstr = strsep(&termnext, ",")) != NULL) {
- entnext = termstr;
+ s = strsep(&next, ":");
+ if (s == NULL || next == NULL || fnmatch(s, term->name, 0) != 0) {
+ free(copy);
+ return;
+ }
- entstr = strsep(&entnext, ":");
- if (entstr == NULL || entnext == NULL)
- continue;
- if (fnmatch(entstr, term->name, 0) != 0)
+ while ((s = strsep(&next, ":")) != NULL) {
+ if (*s == '\0')
continue;
- while ((entstr = strsep(&entnext, ":")) != NULL) {
- if (*entstr == '\0')
+ value = NULL;
+
+ remove = 0;
+ if ((cp = strchr(s, '=')) != NULL) {
+ *cp++ = '\0';
+ value = xstrdup(cp);
+ if (strunvis(value, cp) == -1) {
+ free(value);
+ value = xstrdup(cp);
+ }
+ } else if (s[strlen(s) - 1] == '@') {
+ s[strlen(s) - 1] = '\0';
+ remove = 1;
+ } else
+ value = xstrdup("");
+
+ if (remove)
+ log_debug("%s override: %s@", term->name, s);
+ else
+ log_debug("%s override: %s=%s", term->name, s, value);
+
+ for (i = 0; i < tty_term_ncodes(); i++) {
+ ent = &tty_term_codes[i];
+ if (strcmp(s, ent->name) != 0)
continue;
+ code = &term->codes[i];
- val = NULL;
- removeflag = 0;
- if ((ptr = strchr(entstr, '=')) != NULL) {
- *ptr++ = '\0';
- val = xstrdup(ptr);
- if (strunvis(val, ptr) == -1) {
- free(val);
- val = xstrdup(ptr);
- }
- } else if (entstr[strlen(entstr) - 1] == '@') {
- entstr[strlen(entstr) - 1] = '\0';
- removeflag = 1;
- } else
- val = xstrdup("");
-
- log_debug("%s override: %s %s",
- term->name, entstr, removeflag ? "@" : val);
- for (i = 0; i < tty_term_ncodes(); i++) {
- ent = &tty_term_codes[i];
- if (strcmp(entstr, ent->name) != 0)
- continue;
- code = &term->codes[i];
-
- if (removeflag) {
- code->type = TTYCODE_NONE;
- continue;
- }
- switch (ent->type) {
- case TTYCODE_NONE:
- break;
- case TTYCODE_STRING:
- if (code->type == TTYCODE_STRING)
- free(code->value.string);
- code->value.string = xstrdup(val);
- code->type = ent->type;
- break;
- case TTYCODE_NUMBER:
- n = strtonum(val, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- break;
- code->value.number = n;
- code->type = ent->type;
- break;
- case TTYCODE_FLAG:
- code->value.flag = 1;
- code->type = ent->type;
+ if (remove) {
+ code->type = TTYCODE_NONE;
+ continue;
+ }
+ switch (ent->type) {
+ case TTYCODE_NONE:
+ break;
+ case TTYCODE_STRING:
+ if (code->type == TTYCODE_STRING)
+ free(code->value.string);
+ code->value.string = xstrdup(value);
+ code->type = ent->type;
+ break;
+ case TTYCODE_NUMBER:
+ n = strtonum(value, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
break;
- }
+ code->value.number = n;
+ code->type = ent->type;
+ break;
+ case TTYCODE_FLAG:
+ code->value.flag = 1;
+ code->type = ent->type;
+ break;
}
-
- free(val);
}
- }
+ free(value);
+ }
free(s);
}
@@ -386,7 +382,8 @@ tty_term_find(char *name, int fd, char **cause)
struct tty_term *term;
const struct tty_term_code_entry *ent;
struct tty_code *code;
- u_int i;
+ struct options_entry *o;
+ u_int size, i;
int n, error;
const char *s, *acs;
@@ -460,8 +457,14 @@ tty_term_find(char *name, int fd, char **cause)
}
/* Apply terminal overrides. */
- s = options_get_string(global_options, "terminal-overrides");
- tty_term_override(term, s);
+ o = options_get_only(global_options, "terminal-overrides");
+ if (options_array_size(o, &size) != -1) {
+ for (i = 0; i < size; i++) {
+ s = options_array_get(o, i);
+ if (s != NULL)
+ tty_term_override(term, s);
+ }
+ }
/* Delete curses data. */
#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \