mirror of
https://github.com/tmux/tmux.git
synced 2025-11-05 18:36:10 +00:00
Merge branch 'obsd-master'
This commit is contained in:
7
client.c
7
client.c
@@ -251,17 +251,14 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
|
|||||||
* flag.
|
* flag.
|
||||||
*/
|
*/
|
||||||
cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause);
|
cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause);
|
||||||
if (cmdlist == NULL) {
|
if (cmdlist != NULL) {
|
||||||
fprintf(stderr, "%s\n", cause);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
cmdflags &= ~CMD_STARTSERVER;
|
|
||||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||||
cmdflags |= CMD_STARTSERVER;
|
cmdflags |= CMD_STARTSERVER;
|
||||||
}
|
}
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create client process structure (starts logging). */
|
/* Create client process structure (starts logging). */
|
||||||
client_proc = proc_start("client", base, 0, client_signal);
|
client_proc = proc_start("client", base, 0, client_signal);
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
|||||||
struct client *c = item->client, *c_loop;
|
struct client *c = item->client, *c_loop;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->state.tflag.wl;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->state.tflag.wp;
|
||||||
const char *update;
|
|
||||||
char *cause, *cwd;
|
char *cause, *cwd;
|
||||||
struct format_tree *ft;
|
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);
|
server_client_detach(c_loop, MSG_DETACH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!Eflag)
|
||||||
if (!Eflag) {
|
environ_update(s->options, c->environ, s->environ);
|
||||||
update = options_get_string(s->options,
|
|
||||||
"update-environment");
|
|
||||||
environ_update(update, c->environ, s->environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
c->session = s;
|
c->session = s;
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
@@ -116,7 +111,6 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
|||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rflag)
|
if (rflag)
|
||||||
c->flags |= CLIENT_READONLY;
|
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);
|
server_client_detach(c_loop, MSG_DETACH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!Eflag)
|
||||||
if (!Eflag) {
|
environ_update(s->options, c->environ, s->environ);
|
||||||
update = options_get_string(s->options,
|
|
||||||
"update-environment");
|
|
||||||
environ_update(update, c->environ, s->environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
c->session = s;
|
c->session = s;
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct window *w;
|
struct window *w;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
struct termios tio, *tiop;
|
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;
|
const char *path, *cmd, *cwd, *to_free = NULL;
|
||||||
char **argv, *cause, *cp;
|
char **argv, *cause, *cp;
|
||||||
int detached, already_attached, idx, argc;
|
int detached, already_attached, idx, argc;
|
||||||
@@ -234,11 +234,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
/* Construct the environment. */
|
/* Construct the environment. */
|
||||||
env = environ_create();
|
env = environ_create();
|
||||||
if (c != NULL && !args_has(args, 'E')) {
|
if (c != NULL && !args_has(args, 'E'))
|
||||||
update = options_get_string(global_s_options,
|
environ_update(global_s_options, c->environ, env);
|
||||||
"update-environment");
|
|
||||||
environ_update(update, c->environ, env);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the new session. */
|
/* Create the new session. */
|
||||||
idx = -1 - options_get_number(global_s_options, "base-index");
|
idx = -1 - options_get_number(global_s_options, "base-index");
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ static enum cmd_retval
|
|||||||
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
int append = args_has(args, 'a');
|
||||||
struct cmd_find_state *fs = &item->state.tflag;
|
struct cmd_find_state *fs = &item->state.tflag;
|
||||||
struct session *s = fs->s;
|
struct session *s = fs->s;
|
||||||
struct winlink *wl = fs->wl;
|
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]);
|
cmdq_error(item, "not an array: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
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. */
|
/* 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);
|
options_remove(o);
|
||||||
} else
|
} else
|
||||||
options_array_set(o, idx, NULL, 0);
|
options_array_set(o, idx, NULL, 0);
|
||||||
} else if (*name == '@')
|
} else if (*name == '@') {
|
||||||
options_set_string(oo, name, args_has(args, 'a'), "%s", value);
|
if (value == NULL) {
|
||||||
else if (idx == -1) {
|
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);
|
error = cmd_set_option_set(self, item, oo, parent, value);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
} else {
|
} else {
|
||||||
|
if (value == NULL) {
|
||||||
|
cmdq_error(item, "empty value");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_empty(oo, options_table_entry(parent));
|
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]);
|
cmdq_error(item, "invalid index: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,17 +44,6 @@ const struct cmd_entry cmd_show_messages_entry = {
|
|||||||
.exec = cmd_show_messages_exec
|
.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_terminals(struct cmdq_item *, int);
|
||||||
static int cmd_show_messages_jobs(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;
|
int done, blank;
|
||||||
|
|
||||||
done = blank = 0;
|
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);
|
blank = cmd_show_messages_terminals(item, blank);
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
|
if (args_has(args, 'J')) {
|
||||||
cmd_show_messages_jobs(item, blank);
|
cmd_show_messages_jobs(item, blank);
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
80
cmd-string.c
80
cmd-string.c
@@ -54,17 +54,15 @@ cmd_string_ungetc(size_t *p)
|
|||||||
(*p)--;
|
(*p)--;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd_list *
|
int
|
||||||
cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
|
cmd_string_split(const char *s, int *rargc, char ***rargv)
|
||||||
{
|
{
|
||||||
size_t p = 0;
|
size_t p = 0;
|
||||||
int ch, i, argc = 0;
|
int ch, argc = 0, append = 0;
|
||||||
char **argv = NULL, *buf = NULL, *t;
|
char **argv = NULL, *buf = NULL, *t;
|
||||||
const char *whitespace, *equals;
|
const char *whitespace, *equals;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
struct cmd_list *cmdlist = NULL;
|
|
||||||
|
|
||||||
*cause = NULL;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ch = cmd_string_getc(s, &p);
|
ch = cmd_string_getc(s, &p);
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@@ -115,43 +113,67 @@ cmd_string_parse(const char *s, const char *file, u_int line, char **cause)
|
|||||||
argc--;
|
argc--;
|
||||||
memmove(argv, argv + 1, argc * (sizeof *argv));
|
memmove(argv, argv + 1, argc * (sizeof *argv));
|
||||||
}
|
}
|
||||||
if (argc == 0)
|
goto done;
|
||||||
goto out;
|
|
||||||
|
|
||||||
cmdlist = cmd_list_parse(argc, argv, file, line, cause);
|
|
||||||
goto out;
|
|
||||||
case '~':
|
case '~':
|
||||||
if (buf == NULL) {
|
if (buf != NULL) {
|
||||||
|
append = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
t = cmd_string_expand_tilde(s, &p);
|
t = cmd_string_expand_tilde(s, &p);
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
cmd_string_copy(&buf, t, &len);
|
cmd_string_copy(&buf, t, &len);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
default:
|
default:
|
||||||
if (len >= SIZE_MAX - 2)
|
append = 1;
|
||||||
goto error;
|
|
||||||
|
|
||||||
buf = xrealloc(buf, len + 1);
|
|
||||||
buf[len++] = ch;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (append) {
|
||||||
|
if (len >= SIZE_MAX - 2)
|
||||||
|
goto error;
|
||||||
|
buf = xrealloc(buf, len + 1);
|
||||||
|
buf[len++] = ch;
|
||||||
}
|
}
|
||||||
|
append = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
*rargc = argc;
|
||||||
|
*rargv = argv;
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
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:
|
error:
|
||||||
xasprintf(cause, "invalid or unknown command: %s", s);
|
xasprintf(cause, "invalid or unknown command: %s", s);
|
||||||
|
return (NULL);
|
||||||
out:
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
if (argv != NULL) {
|
|
||||||
for (i = 0; i < argc; i++)
|
|
||||||
free(argv[i]);
|
|
||||||
free(argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (cmdlist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct client *c = state->c;
|
struct client *c = state->c;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->state.tflag.s;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char *tablename, *update;
|
const char *tablename;
|
||||||
struct key_table *table;
|
struct key_table *table;
|
||||||
|
|
||||||
if (args_has(args, 'r'))
|
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')) {
|
if (!args_has(args, 'E'))
|
||||||
update = options_get_string(s->options, "update-environment");
|
environ_update(s->options, c->environ, s->environ);
|
||||||
environ_update(update, c->environ, s->environ);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->session != NULL && c->session != s)
|
if (c->session != NULL && c->session != s)
|
||||||
c->last_session = c->session;
|
c->last_session = c->session;
|
||||||
|
|||||||
70
cmd.c
70
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_select_window_entry;
|
||||||
extern const struct cmd_entry cmd_send_keys_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_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_buffer_entry;
|
||||||
extern const struct cmd_entry cmd_set_environment_entry;
|
extern const struct cmd_entry cmd_set_environment_entry;
|
||||||
extern const struct cmd_entry cmd_set_hook_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_select_window_entry,
|
||||||
&cmd_send_keys_entry,
|
&cmd_send_keys_entry,
|
||||||
&cmd_send_prefix_entry,
|
&cmd_send_prefix_entry,
|
||||||
&cmd_server_info_entry,
|
|
||||||
&cmd_set_buffer_entry,
|
&cmd_set_buffer_entry,
|
||||||
&cmd_set_environment_entry,
|
&cmd_set_environment_entry,
|
||||||
&cmd_set_hook_entry,
|
&cmd_set_hook_entry,
|
||||||
@@ -307,21 +305,74 @@ cmd_stringify_argv(int argc, char **argv)
|
|||||||
return (buf);
|
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 *
|
struct cmd *
|
||||||
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||||
{
|
{
|
||||||
|
const char *name;
|
||||||
const struct cmd_entry **entryp, *entry;
|
const struct cmd_entry **entryp, *entry;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
struct args *args;
|
struct args *args;
|
||||||
char s[BUFSIZ];
|
char s[BUFSIZ];
|
||||||
int ambiguous = 0;
|
int ambiguous, allocated = 0;
|
||||||
|
|
||||||
*cause = NULL;
|
*cause = NULL;
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
xasprintf(cause, "no command");
|
xasprintf(cause, "no command");
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
name = argv[0];
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ambiguous = 0;
|
||||||
entry = NULL;
|
entry = NULL;
|
||||||
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
||||||
if ((*entryp)->alias != NULL &&
|
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)
|
if (strcmp(entry->name, argv[0]) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((ambiguous || entry == NULL) &&
|
||||||
|
server_proc != NULL &&
|
||||||
|
!allocated &&
|
||||||
|
cmd_try_alias(&argc, &argv) == 0) {
|
||||||
|
allocated = 1;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
if (ambiguous)
|
if (ambiguous)
|
||||||
goto ambiguous;
|
goto ambiguous;
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
xasprintf(cause, "unknown command: %s", argv[0]);
|
xasprintf(cause, "unknown command: %s", name);
|
||||||
return (NULL);
|
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->file = xstrdup(file);
|
||||||
cmd->line = line;
|
cmd->line = line;
|
||||||
|
|
||||||
|
if (allocated)
|
||||||
|
cmd_free_argv(argc, argv);
|
||||||
return (cmd);
|
return (cmd);
|
||||||
|
|
||||||
ambiguous:
|
ambiguous:
|
||||||
@@ -377,7 +437,7 @@ ambiguous:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s[strlen(s) - 2] = '\0';
|
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);
|
return (NULL);
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
|
|||||||
28
environ.c
28
environ.c
@@ -169,25 +169,27 @@ environ_unset(struct environ *env, const char *name)
|
|||||||
free(envent);
|
free(envent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Copy variables from a destination into a source * environment. */
|
||||||
* Copy a space-separated list of variables from a destination into a source
|
|
||||||
* environment.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
environ_update(const char *vars, struct environ *srcenv,
|
environ_update(struct options *oo, struct environ *src, struct environ *dst)
|
||||||
struct environ *dstenv)
|
|
||||||
{
|
{
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
char *copyvars, *var, *next;
|
struct options_entry *o;
|
||||||
|
u_int size, idx;
|
||||||
|
const char *value;
|
||||||
|
|
||||||
copyvars = next = xstrdup(vars);
|
o = options_get(oo, "update-environment");
|
||||||
while ((var = strsep(&next, " ")) != NULL) {
|
if (o == NULL || options_array_size(o, &size) == -1)
|
||||||
if ((envent = environ_find(srcenv, var)) == NULL)
|
return;
|
||||||
environ_clear(dstenv, var);
|
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
|
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(). */
|
/* Push environment into the real environment - use after fork(). */
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ key_bindings_init(void)
|
|||||||
for (i = 0; i < nitems(defaults); i++) {
|
for (i = 0; i < nitems(defaults); i++) {
|
||||||
cmdlist = cmd_string_parse(defaults[i], "<default>", i, &cause);
|
cmdlist = cmd_string_parse(defaults[i], "<default>", i, &cause);
|
||||||
if (cmdlist == NULL)
|
if (cmdlist == NULL)
|
||||||
fatalx("bad default key");
|
fatalx("bad default key: %s", defaults[i]);
|
||||||
cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
|
cmdq_append(NULL, cmdq_get_command(cmdlist, NULL, NULL, 0));
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,16 @@ const struct options_table_entry options_table[] = {
|
|||||||
.default_num = 20
|
.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",
|
{ .name = "default-terminal",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_STRING,
|
||||||
.scope = OPTIONS_TABLE_SERVER,
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
@@ -111,11 +121,12 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "terminal-overrides",
|
{ .name = "terminal-overrides",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_ARRAY,
|
||||||
.scope = OPTIONS_TABLE_SERVER,
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
.default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
|
.default_str = "xterm*:XT:Ms=\\E]52;%p1%s;%p2%s\\007"
|
||||||
":Cs=\\E]12;%p1%s\\007:Cr=\\E]112\\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",
|
{ .name = "assume-paste-time",
|
||||||
@@ -470,11 +481,10 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "update-environment",
|
{ .name = "update-environment",
|
||||||
.type = OPTIONS_TABLE_STRING,
|
.type = OPTIONS_TABLE_ARRAY,
|
||||||
.scope = OPTIONS_TABLE_SESSION,
|
.scope = OPTIONS_TABLE_SESSION,
|
||||||
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
|
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
|
||||||
"SSH_CONNECTION WINDOWID XAUTHORITY"
|
"SSH_CONNECTION WINDOWID XAUTHORITY"
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "visual-activity",
|
{ .name = "visual-activity",
|
||||||
|
|||||||
2
pty.c
2
pty.c
@@ -53,7 +53,7 @@ pty_fork(int ptmfd, int *fd, char *name, size_t namelen, struct winsize *ws)
|
|||||||
struct ptmget ptm;
|
struct ptmget ptm;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
if ((ioctl(ptmfd, PTMGET, &ptm) == -1))
|
if (ioctl(ptmfd, PTMGET, &ptm) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
strlcpy(name, ptm.sn, namelen);
|
strlcpy(name, ptm.sn, namelen);
|
||||||
|
|||||||
66
tmux.1
66
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,
|
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
|
old ones are removed from the bottom if necessary to maintain this maximum
|
||||||
length.
|
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
|
.It Ic default-terminal Ar terminal
|
||||||
Set the default terminal for new windows created in this session - the
|
Set the default terminal for new windows created in this session - the
|
||||||
default value of the
|
default value of the
|
||||||
@@ -2475,12 +2499,12 @@ disallowedWindowOps: 20,21,SetXprop
|
|||||||
Or changing this property from the
|
Or changing this property from the
|
||||||
.Xr xterm 1
|
.Xr xterm 1
|
||||||
interactive menu when required.
|
interactive menu when required.
|
||||||
.It Ic terminal-overrides Ar string
|
.It Ic terminal-overrides[] Ar string
|
||||||
Contains a list of entries which override terminal descriptions read using
|
Allow terminal descriptions read using
|
||||||
.Xr terminfo 5 .
|
.Xr terminfo 5
|
||||||
.Ar string
|
to be overriden.
|
||||||
is a comma-separated list of items each a colon-separated string made up of a
|
Each entry is a colon-separated string made up of a terminal type pattern
|
||||||
terminal type pattern (matched using
|
(matched using
|
||||||
.Xr fnmatch 3 )
|
.Xr fnmatch 3 )
|
||||||
and a set of
|
and a set of
|
||||||
.Em name=value
|
.Em name=value
|
||||||
@@ -2491,26 +2515,14 @@ For example, to set the
|
|||||||
.Xr terminfo 5
|
.Xr terminfo 5
|
||||||
entry to
|
entry to
|
||||||
.Ql \ee[H\ee[2J
|
.Ql \ee[H\ee[2J
|
||||||
for all terminal types and the
|
for all terminal types matching
|
||||||
.Ql dch1
|
.Ql rxvt* :
|
||||||
entry to
|
.Pp
|
||||||
.Ql \ee[P
|
.Dl "rxvt*:clear=\ee[H\ee[2J"
|
||||||
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
|
|
||||||
.Pp
|
.Pp
|
||||||
The terminal entry value is passed through
|
The terminal entry value is passed through
|
||||||
.Xr strunvis 3
|
.Xr strunvis 3
|
||||||
before interpretation.
|
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
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Available session options are:
|
Available session options are:
|
||||||
@@ -2861,19 +2873,15 @@ For how to specify
|
|||||||
see the
|
see the
|
||||||
.Ic message-command-style
|
.Ic message-command-style
|
||||||
option.
|
option.
|
||||||
.It Ic update-environment Ar variables
|
.It Ic update-environment[] Ar variable
|
||||||
Set a space-separated string containing a list of environment variables to be
|
Set list of environment variables to be copied into the session environment
|
||||||
copied into the session environment when a new session is created or an
|
when a new session is created or an existing session is attached.
|
||||||
existing session is attached.
|
|
||||||
Any variables that do not exist in the source environment are set to be
|
Any variables that do not exist in the source environment are set to be
|
||||||
removed from the session environment (as if
|
removed from the session environment (as if
|
||||||
.Fl r
|
.Fl r
|
||||||
was given to the
|
was given to the
|
||||||
.Ic set-environment
|
.Ic set-environment
|
||||||
command).
|
command).
|
||||||
The default is
|
|
||||||
"DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID SSH_CONNECTION WINDOWID
|
|
||||||
XAUTHORITY".
|
|
||||||
.It Xo Ic visual-activity
|
.It Xo Ic visual-activity
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
|
|||||||
3
tmux.h
3
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_clear(struct environ *, const char *);
|
||||||
void environ_put(struct environ *, const char *);
|
void environ_put(struct environ *, const char *);
|
||||||
void environ_unset(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_push(struct environ *);
|
||||||
void environ_log(struct environ *, const char *);
|
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 *, ...);
|
void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
|
||||||
|
|
||||||
/* cmd-string.c */
|
/* cmd-string.c */
|
||||||
|
int cmd_string_split(const char *, int *, char ***);
|
||||||
struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **);
|
struct cmd_list *cmd_string_parse(const char *, const char *, u_int, char **);
|
||||||
|
|
||||||
/* cmd-wait-for.c */
|
/* cmd-wait-for.c */
|
||||||
|
|||||||
89
tty-term.c
89
tty-term.c
@@ -297,56 +297,54 @@ tty_term_strip(const char *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
const struct tty_term_code_entry *ent;
|
||||||
struct tty_code *code;
|
struct tty_code *code;
|
||||||
char *termnext, *termstr;
|
char *next, *s, *copy, *cp, *value;
|
||||||
char *entnext, *entstr;
|
|
||||||
char *s, *ptr, *val;
|
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
u_int i;
|
u_int i;
|
||||||
int n, removeflag;
|
int n, remove;
|
||||||
|
|
||||||
s = xstrdup(overrides);
|
copy = next = xstrdup(override);
|
||||||
|
|
||||||
termnext = s;
|
s = strsep(&next, ":");
|
||||||
while ((termstr = strsep(&termnext, ",")) != NULL) {
|
if (s == NULL || next == NULL || fnmatch(s, term->name, 0) != 0) {
|
||||||
entnext = termstr;
|
free(copy);
|
||||||
|
return;
|
||||||
entstr = strsep(&entnext, ":");
|
|
||||||
if (entstr == NULL || entnext == NULL)
|
|
||||||
continue;
|
|
||||||
if (fnmatch(entstr, term->name, 0) != 0)
|
|
||||||
continue;
|
|
||||||
while ((entstr = strsep(&entnext, ":")) != NULL) {
|
|
||||||
if (*entstr == '\0')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
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",
|
while ((s = strsep(&next, ":")) != NULL) {
|
||||||
term->name, entstr, removeflag ? "@" : val);
|
if (*s == '\0')
|
||||||
|
continue;
|
||||||
|
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++) {
|
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||||
ent = &tty_term_codes[i];
|
ent = &tty_term_codes[i];
|
||||||
if (strcmp(entstr, ent->name) != 0)
|
if (strcmp(s, ent->name) != 0)
|
||||||
continue;
|
continue;
|
||||||
code = &term->codes[i];
|
code = &term->codes[i];
|
||||||
|
|
||||||
if (removeflag) {
|
if (remove) {
|
||||||
code->type = TTYCODE_NONE;
|
code->type = TTYCODE_NONE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -356,11 +354,11 @@ tty_term_override(struct tty_term *term, const char *overrides)
|
|||||||
case TTYCODE_STRING:
|
case TTYCODE_STRING:
|
||||||
if (code->type == TTYCODE_STRING)
|
if (code->type == TTYCODE_STRING)
|
||||||
free(code->value.string);
|
free(code->value.string);
|
||||||
code->value.string = xstrdup(val);
|
code->value.string = xstrdup(value);
|
||||||
code->type = ent->type;
|
code->type = ent->type;
|
||||||
break;
|
break;
|
||||||
case TTYCODE_NUMBER:
|
case TTYCODE_NUMBER:
|
||||||
n = strtonum(val, 0, INT_MAX, &errstr);
|
n = strtonum(value, 0, INT_MAX, &errstr);
|
||||||
if (errstr != NULL)
|
if (errstr != NULL)
|
||||||
break;
|
break;
|
||||||
code->value.number = n;
|
code->value.number = n;
|
||||||
@@ -373,10 +371,8 @@ tty_term_override(struct tty_term *term, const char *overrides)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(val);
|
free(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +382,8 @@ tty_term_find(char *name, int fd, char **cause)
|
|||||||
struct tty_term *term;
|
struct tty_term *term;
|
||||||
const struct tty_term_code_entry *ent;
|
const struct tty_term_code_entry *ent;
|
||||||
struct tty_code *code;
|
struct tty_code *code;
|
||||||
u_int i;
|
struct options_entry *o;
|
||||||
|
u_int size, i;
|
||||||
int n, error;
|
int n, error;
|
||||||
const char *s, *acs;
|
const char *s, *acs;
|
||||||
|
|
||||||
@@ -460,8 +457,14 @@ tty_term_find(char *name, int fd, char **cause)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Apply terminal overrides. */
|
/* Apply terminal overrides. */
|
||||||
s = options_get_string(global_options, "terminal-overrides");
|
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);
|
tty_term_override(term, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete curses data. */
|
/* Delete curses data. */
|
||||||
#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
|
#if !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR > 5 || \
|
||||||
|
|||||||
Reference in New Issue
Block a user