mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Break the argument escaping code into a separate function and use it to
escape key bindings in list-keys. Also escape ~ and ; and $ properly.
This commit is contained in:
		
							
								
								
									
										53
									
								
								arguments.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								arguments.c
									
									
									
									
									
								
							@@ -141,22 +141,14 @@ static void
 | 
				
			|||||||
args_print_add_value(char **buf, size_t *len, struct args_entry *entry,
 | 
					args_print_add_value(char **buf, size_t *len, struct args_entry *entry,
 | 
				
			||||||
    struct args_value *value)
 | 
					    struct args_value *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const char	 quoted[] = " #\"';$";
 | 
					 | 
				
			||||||
	char	*escaped;
 | 
						char	*escaped;
 | 
				
			||||||
	int			 flags;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (**buf != '\0')
 | 
						if (**buf != '\0')
 | 
				
			||||||
		args_print_add(buf, len, " -%c ", entry->flag);
 | 
							args_print_add(buf, len, " -%c ", entry->flag);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		args_print_add(buf, len, "-%c ", entry->flag);
 | 
							args_print_add(buf, len, "-%c ", entry->flag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flags = VIS_OCTAL|VIS_TAB|VIS_NL;
 | 
						escaped = args_escape(value->value);
 | 
				
			||||||
	if (value->value[strcspn(value->value, quoted)] != '\0')
 | 
					 | 
				
			||||||
		flags |= VIS_DQ;
 | 
					 | 
				
			||||||
	utf8_stravis(&escaped, value->value, flags);
 | 
					 | 
				
			||||||
	if (flags & VIS_DQ)
 | 
					 | 
				
			||||||
		args_print_add(buf, len, "\"%s\"", escaped);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	args_print_add(buf, len, "%s", escaped);
 | 
						args_print_add(buf, len, "%s", escaped);
 | 
				
			||||||
	free(escaped);
 | 
						free(escaped);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -165,20 +157,12 @@ args_print_add_value(char **buf, size_t *len, struct args_entry *entry,
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
args_print_add_argument(char **buf, size_t *len, const char *argument)
 | 
					args_print_add_argument(char **buf, size_t *len, const char *argument)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static const char	 quoted[] = " #\"';$";
 | 
					 | 
				
			||||||
	char	*escaped;
 | 
						char	*escaped;
 | 
				
			||||||
	int			 flags;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (**buf != '\0')
 | 
						if (**buf != '\0')
 | 
				
			||||||
		args_print_add(buf, len, " ");
 | 
							args_print_add(buf, len, " ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flags = VIS_OCTAL|VIS_TAB|VIS_NL;
 | 
						escaped = args_escape(argument);
 | 
				
			||||||
	if (argument[strcspn(argument, quoted)] != '\0')
 | 
					 | 
				
			||||||
		flags |= VIS_DQ;
 | 
					 | 
				
			||||||
	utf8_stravis(&escaped, argument, flags);
 | 
					 | 
				
			||||||
	if (flags & VIS_DQ)
 | 
					 | 
				
			||||||
		args_print_add(buf, len, "\"%s\"", escaped);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	args_print_add(buf, len, "%s", escaped);
 | 
						args_print_add(buf, len, "%s", escaped);
 | 
				
			||||||
	free(escaped);
 | 
						free(escaped);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -219,6 +203,39 @@ args_print(struct args *args)
 | 
				
			|||||||
	return (buf);
 | 
						return (buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Escape an argument. */
 | 
				
			||||||
 | 
					char *
 | 
				
			||||||
 | 
					args_escape(const char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static const char	 quoted[] = " #\"';$";
 | 
				
			||||||
 | 
						char			*escaped, *result;
 | 
				
			||||||
 | 
						int			 flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((strchr(quoted, s[0]) != NULL || s[0] == '~') && s[1] == '\0') {
 | 
				
			||||||
 | 
							xasprintf(&escaped, "\\%c", s[0]);
 | 
				
			||||||
 | 
							return (escaped);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags = VIS_OCTAL|VIS_TAB|VIS_NL;
 | 
				
			||||||
 | 
						if (s[strcspn(s, quoted)] != '\0')
 | 
				
			||||||
 | 
							flags |= VIS_DQ;
 | 
				
			||||||
 | 
						utf8_stravis(&escaped, s, flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (flags & VIS_DQ) {
 | 
				
			||||||
 | 
							if (*escaped == '~')
 | 
				
			||||||
 | 
								xasprintf(&result, "\"\\%s\"", escaped);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								xasprintf(&result, "\"%s\"", escaped);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (*escaped == '~')
 | 
				
			||||||
 | 
								xasprintf(&result, "\\%s", escaped);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								result = xstrdup(escaped);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(escaped);
 | 
				
			||||||
 | 
						return (result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return if an argument is present. */
 | 
					/* Return if an argument is present. */
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
args_has(struct args *args, u_char ch)
 | 
					args_has(struct args *args, u_char ch)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -60,8 +60,8 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
	struct key_table	*table;
 | 
						struct key_table	*table;
 | 
				
			||||||
	struct key_binding	*bd;
 | 
						struct key_binding	*bd;
 | 
				
			||||||
	const char		*key, *tablename, *r;
 | 
						const char		*tablename, *r;
 | 
				
			||||||
	char			*cp, tmp[BUFSIZ];
 | 
						char			*key, *cp, tmp[BUFSIZ];
 | 
				
			||||||
	int			 repeat, width, tablewidth, keywidth;
 | 
						int			 repeat, width, tablewidth, keywidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (self->entry == &cmd_list_commands_entry)
 | 
						if (self->entry == &cmd_list_commands_entry)
 | 
				
			||||||
@@ -83,7 +83,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		bd = key_bindings_first(table);
 | 
							bd = key_bindings_first(table);
 | 
				
			||||||
		while (bd != NULL) {
 | 
							while (bd != NULL) {
 | 
				
			||||||
			key = key_string_lookup_key(bd->key);
 | 
								key = args_escape(key_string_lookup_key(bd->key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (bd->flags & KEY_BINDING_REPEAT)
 | 
								if (bd->flags & KEY_BINDING_REPEAT)
 | 
				
			||||||
				repeat = 1;
 | 
									repeat = 1;
 | 
				
			||||||
@@ -95,6 +95,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
			if (width > keywidth)
 | 
								if (width > keywidth)
 | 
				
			||||||
				keywidth = width;
 | 
									keywidth = width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								free(key);
 | 
				
			||||||
			bd = key_bindings_next(table, bd);
 | 
								bd = key_bindings_next(table, bd);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		table = key_bindings_next_table(table);
 | 
							table = key_bindings_next_table(table);
 | 
				
			||||||
@@ -108,7 +109,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		bd = key_bindings_first(table);
 | 
							bd = key_bindings_first(table);
 | 
				
			||||||
		while (bd != NULL) {
 | 
							while (bd != NULL) {
 | 
				
			||||||
			key = key_string_lookup_key(bd->key);
 | 
								key = args_escape(key_string_lookup_key(bd->key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!repeat)
 | 
								if (!repeat)
 | 
				
			||||||
				r = "";
 | 
									r = "";
 | 
				
			||||||
@@ -128,11 +129,13 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
			strlcat(tmp, " ", sizeof tmp);
 | 
								strlcat(tmp, " ", sizeof tmp);
 | 
				
			||||||
			free(cp);
 | 
								free(cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cp = cmd_list_print(bd->cmdlist);
 | 
								cp = cmd_list_print(bd->cmdlist, 1);
 | 
				
			||||||
			strlcat(tmp, cp, sizeof tmp);
 | 
								strlcat(tmp, cp, sizeof tmp);
 | 
				
			||||||
			free(cp);
 | 
								free(cp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cmdq_print(item, "bind-key %s", tmp);
 | 
								cmdq_print(item, "bind-key %s", tmp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								free(key);
 | 
				
			||||||
			bd = key_bindings_next(table, bd);
 | 
								bd = key_bindings_next(table, bd);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		table = key_bindings_next_table(table);
 | 
							table = key_bindings_next_table(table);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								cmd-list.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								cmd-list.c
									
									
									
									
									
								
							@@ -129,7 +129,7 @@ cmd_list_free(struct cmd_list *cmdlist)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *
 | 
					char *
 | 
				
			||||||
cmd_list_print(struct cmd_list *cmdlist)
 | 
					cmd_list_print(struct cmd_list *cmdlist, int escaped)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd	*cmd;
 | 
						struct cmd	*cmd;
 | 
				
			||||||
	char		*buf, *this;
 | 
						char		*buf, *this;
 | 
				
			||||||
@@ -141,12 +141,16 @@ cmd_list_print(struct cmd_list *cmdlist)
 | 
				
			|||||||
	TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
 | 
						TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
 | 
				
			||||||
		this = cmd_print(cmd);
 | 
							this = cmd_print(cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len += strlen(this) + 3;
 | 
							len += strlen(this) + 4;
 | 
				
			||||||
		buf = xrealloc(buf, len);
 | 
							buf = xrealloc(buf, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		strlcat(buf, this, len);
 | 
							strlcat(buf, this, len);
 | 
				
			||||||
		if (TAILQ_NEXT(cmd, qentry) != NULL)
 | 
							if (TAILQ_NEXT(cmd, qentry) != NULL) {
 | 
				
			||||||
 | 
								if (escaped)
 | 
				
			||||||
 | 
									strlcat(buf, " \\; ", len);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
				strlcat(buf, " ; ", len);
 | 
									strlcat(buf, " ; ", len);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		free(this);
 | 
							free(this);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -663,7 +663,7 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi)
 | 
				
			|||||||
		cmd_list_free(cmdlist);
 | 
							cmd_list_free(cmdlist);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = cmd_list_print(result);
 | 
						s = cmd_list_print(result, 0);
 | 
				
			||||||
	log_debug("%s: %s", __func__, s);
 | 
						log_debug("%s: %s", __func__, s);
 | 
				
			||||||
	free(s);
 | 
						free(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,7 +122,7 @@ options_value_tostring(struct options_entry *o, union options_value *ov,
 | 
				
			|||||||
	char	*s;
 | 
						char	*s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (OPTIONS_IS_COMMAND(o))
 | 
						if (OPTIONS_IS_COMMAND(o))
 | 
				
			||||||
		return (cmd_list_print(ov->cmdlist));
 | 
							return (cmd_list_print(ov->cmdlist, 0));
 | 
				
			||||||
	if (OPTIONS_IS_STYLE(o))
 | 
						if (OPTIONS_IS_STYLE(o))
 | 
				
			||||||
		return (xstrdup(style_tostring(&ov->style)));
 | 
							return (xstrdup(style_tostring(&ov->style)));
 | 
				
			||||||
	if (OPTIONS_IS_NUMBER(o)) {
 | 
						if (OPTIONS_IS_NUMBER(o)) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1950,6 +1950,7 @@ void		 args_set(struct args *, u_char, const char *);
 | 
				
			|||||||
struct args	*args_parse(const char *, int, char **);
 | 
					struct args	*args_parse(const char *, int, char **);
 | 
				
			||||||
void		 args_free(struct args *);
 | 
					void		 args_free(struct args *);
 | 
				
			||||||
char		*args_print(struct args *);
 | 
					char		*args_print(struct args *);
 | 
				
			||||||
 | 
					char		*args_escape(const char *);
 | 
				
			||||||
int		 args_has(struct args *, u_char);
 | 
					int		 args_has(struct args *, u_char);
 | 
				
			||||||
const char	*args_get(struct args *, u_char);
 | 
					const char	*args_get(struct args *, u_char);
 | 
				
			||||||
const char	*args_first_value(struct args *, u_char, struct args_value **);
 | 
					const char	*args_first_value(struct args *, u_char, struct args_value **);
 | 
				
			||||||
@@ -2022,7 +2023,7 @@ void		 cmd_list_append(struct cmd_list *, struct cmd *);
 | 
				
			|||||||
void		 cmd_list_move(struct cmd_list *, struct cmd_list *);
 | 
					void		 cmd_list_move(struct cmd_list *, struct cmd_list *);
 | 
				
			||||||
struct cmd_list	*cmd_list_parse(int, char **, const char *, u_int, char **);
 | 
					struct cmd_list	*cmd_list_parse(int, char **, const char *, u_int, char **);
 | 
				
			||||||
void		 cmd_list_free(struct cmd_list *);
 | 
					void		 cmd_list_free(struct cmd_list *);
 | 
				
			||||||
char		*cmd_list_print(struct cmd_list *);
 | 
					char		*cmd_list_print(struct cmd_list *, int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* cmd-queue.c */
 | 
					/* cmd-queue.c */
 | 
				
			||||||
struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
 | 
					struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								utf8.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								utf8.c
									
									
									
									
									
								
							@@ -18,6 +18,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <ctype.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@@ -182,7 +183,11 @@ utf8_strvis(char *dst, const char *src, size_t len, int flag)
 | 
				
			|||||||
			/* Not a complete, valid UTF-8 character. */
 | 
								/* Not a complete, valid UTF-8 character. */
 | 
				
			||||||
			src -= ud.have;
 | 
								src -= ud.have;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (src < end - 1)
 | 
							if (src[0] == '$' && src < end - 1) {
 | 
				
			||||||
 | 
								if (isalpha((u_char)src[1]) || src[1] == '_')
 | 
				
			||||||
 | 
									*dst++ = '\\';
 | 
				
			||||||
 | 
								*dst++ = '$';
 | 
				
			||||||
 | 
							} else if (src < end - 1)
 | 
				
			||||||
			dst = vis(dst, src[0], flag, src[1]);
 | 
								dst = vis(dst, src[0], flag, src[1]);
 | 
				
			||||||
		else if (src < end)
 | 
							else if (src < end)
 | 
				
			||||||
			dst = vis(dst, src[0], flag, '\0');
 | 
								dst = vis(dst, src[0], flag, '\0');
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user