mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Setting the cmdlist pointer in the bind-key to NULL to prevent it being freed
after the command is executing is bogus because it may still be needed if the same command is going to be executed again (for example if you "bind-key a bind-key b ..."). Making a copy is hard, so instead add a reference count to the cmd_list. While here, also print bind-key -n and the rest of the flags properly. Fixes problem reported by mcbride@.
This commit is contained in:
		@@ -130,7 +130,7 @@ cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
 | 
				
			|||||||
		return (cmd_bind_key_table(self, ctx));
 | 
							return (cmd_bind_key_table(self, ctx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key_bindings_add(data->key, data->can_repeat, data->cmdlist);
 | 
						key_bindings_add(data->key, data->can_repeat, data->cmdlist);
 | 
				
			||||||
	data->cmdlist = NULL;	/* avoid free */
 | 
						data->cmdlist->references++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -192,8 +192,17 @@ cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
 | 
				
			|||||||
	off += xsnprintf(buf, len, "%s", self->entry->name);
 | 
						off += xsnprintf(buf, len, "%s", self->entry->name);
 | 
				
			||||||
	if (data == NULL)
 | 
						if (data == NULL)
 | 
				
			||||||
		return (off);
 | 
							return (off);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (off < len && data->command_key)
 | 
				
			||||||
 | 
							off += xsnprintf(buf + off, len - off, " -c");
 | 
				
			||||||
 | 
						if (off < len && !(data->key & KEYC_PREFIX))
 | 
				
			||||||
 | 
							off += xsnprintf(buf + off, len - off, " -n");
 | 
				
			||||||
 | 
						if (off < len && data->can_repeat)
 | 
				
			||||||
 | 
							off += xsnprintf(buf + off, len - off, " -r");
 | 
				
			||||||
 | 
						if (off < len && data->tablename != NULL)
 | 
				
			||||||
 | 
							off += cmd_prarg(buf + off, len - off, " -t ", data->tablename);
 | 
				
			||||||
	if (off < len) {
 | 
						if (off < len) {
 | 
				
			||||||
		skey = key_string_lookup_key(data->key);
 | 
							skey = key_string_lookup_key(data->key & ~KEYC_PREFIX);
 | 
				
			||||||
		off += xsnprintf(buf + off, len - off, " %s ", skey);
 | 
							off += xsnprintf(buf + off, len - off, " %s ", skey);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (off < len)
 | 
						if (off < len)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								cmd-list.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								cmd-list.c
									
									
									
									
									
								
							@@ -32,7 +32,8 @@ cmd_list_parse(int argc, char **argv, char **cause)
 | 
				
			|||||||
	char	       **new_argv;
 | 
						char	       **new_argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmdlist = xmalloc(sizeof *cmdlist);
 | 
						cmdlist = xmalloc(sizeof *cmdlist);
 | 
				
			||||||
	TAILQ_INIT(cmdlist);
 | 
						cmdlist->references = 1;
 | 
				
			||||||
 | 
						TAILQ_INIT(&cmdlist->list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lastsplit = 0;
 | 
						lastsplit = 0;
 | 
				
			||||||
	for (i = 0; i < argc; i++) {
 | 
						for (i = 0; i < argc; i++) {
 | 
				
			||||||
@@ -54,7 +55,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
 | 
				
			|||||||
		cmd = cmd_parse(new_argc, new_argv, cause);
 | 
							cmd = cmd_parse(new_argc, new_argv, cause);
 | 
				
			||||||
		if (cmd == NULL)
 | 
							if (cmd == NULL)
 | 
				
			||||||
			goto bad;
 | 
								goto bad;
 | 
				
			||||||
		TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
 | 
							TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		lastsplit = i + 1;
 | 
							lastsplit = i + 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -63,7 +64,7 @@ cmd_list_parse(int argc, char **argv, char **cause)
 | 
				
			|||||||
		cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
 | 
							cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause);
 | 
				
			||||||
		if (cmd == NULL)
 | 
							if (cmd == NULL)
 | 
				
			||||||
			goto bad;
 | 
								goto bad;
 | 
				
			||||||
		TAILQ_INSERT_TAIL(cmdlist, cmd, qentry);
 | 
							TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (cmdlist);
 | 
						return (cmdlist);
 | 
				
			||||||
@@ -80,7 +81,7 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
 | 
				
			|||||||
	int		 n, retval;
 | 
						int		 n, retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = 0;
 | 
						retval = 0;
 | 
				
			||||||
	TAILQ_FOREACH(cmd, cmdlist, qentry) {
 | 
						TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
 | 
				
			||||||
		if ((n = cmd_exec(cmd, ctx)) == -1)
 | 
							if ((n = cmd_exec(cmd, ctx)) == -1)
 | 
				
			||||||
			return (-1);
 | 
								return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,9 +115,12 @@ cmd_list_free(struct cmd_list *cmdlist)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd	*cmd;
 | 
						struct cmd	*cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!TAILQ_EMPTY(cmdlist)) {
 | 
						if (--cmdlist->references != 0)
 | 
				
			||||||
		cmd = TAILQ_FIRST(cmdlist);
 | 
							return;
 | 
				
			||||||
		TAILQ_REMOVE(cmdlist, cmd, qentry);
 | 
					
 | 
				
			||||||
 | 
						while (!TAILQ_EMPTY(&cmdlist->list)) {
 | 
				
			||||||
 | 
							cmd = TAILQ_FIRST(&cmdlist->list);
 | 
				
			||||||
 | 
							TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
 | 
				
			||||||
		cmd_free(cmd);
 | 
							cmd_free(cmd);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	xfree(cmdlist);
 | 
						xfree(cmdlist);
 | 
				
			||||||
@@ -129,7 +133,7 @@ cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
 | 
				
			|||||||
	size_t		 off;
 | 
						size_t		 off;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	off = 0;
 | 
						off = 0;
 | 
				
			||||||
	TAILQ_FOREACH(cmd, cmdlist, qentry) {
 | 
						TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
 | 
				
			||||||
		if (off >= len)
 | 
							if (off >= len)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		off += cmd_print(cmd, buf + off, len - off);
 | 
							off += cmd_print(cmd, buf + off, len - off);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -178,14 +178,15 @@ key_bindings_init(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < nitems(table); i++) {
 | 
						for (i = 0; i < nitems(table); i++) {
 | 
				
			||||||
		cmdlist = xmalloc(sizeof *cmdlist);
 | 
							cmdlist = xmalloc(sizeof *cmdlist);
 | 
				
			||||||
		TAILQ_INIT(cmdlist);
 | 
							TAILQ_INIT(&cmdlist->list);
 | 
				
			||||||
 | 
							cmdlist->references = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cmd = xmalloc(sizeof *cmd);
 | 
							cmd = xmalloc(sizeof *cmd);
 | 
				
			||||||
		cmd->entry = table[i].entry;
 | 
							cmd->entry = table[i].entry;
 | 
				
			||||||
		cmd->data = NULL;
 | 
							cmd->data = NULL;
 | 
				
			||||||
		if (cmd->entry->init != NULL)
 | 
							if (cmd->entry->init != NULL)
 | 
				
			||||||
			cmd->entry->init(cmd, table[i].key);
 | 
								cmd->entry->init(cmd, table[i].key);
 | 
				
			||||||
		TAILQ_INSERT_HEAD(cmdlist, cmd, qentry);
 | 
							TAILQ_INSERT_HEAD(&cmdlist->list, cmd, qentry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key_bindings_add(
 | 
							key_bindings_add(
 | 
				
			||||||
		    table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
 | 
							    table[i].key | KEYC_PREFIX, table[i].can_repeat, cmdlist);
 | 
				
			||||||
@@ -259,7 +260,7 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c)
 | 
				
			|||||||
	ctx.cmdclient = NULL;
 | 
						ctx.cmdclient = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	readonly = 1;
 | 
						readonly = 1;
 | 
				
			||||||
	TAILQ_FOREACH(cmd, bd->cmdlist, qentry) {
 | 
						TAILQ_FOREACH(cmd, &bd->cmdlist->list, qentry) {
 | 
				
			||||||
		if (!(cmd->entry->flags & CMD_READONLY))
 | 
							if (!(cmd->entry->flags & CMD_READONLY))
 | 
				
			||||||
			readonly = 0;
 | 
								readonly = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.c
									
									
									
									
									
								
							@@ -517,7 +517,7 @@ main(int argc, char **argv)
 | 
				
			|||||||
			exit(1);
 | 
								exit(1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		cmdflags &= ~CMD_STARTSERVER;
 | 
							cmdflags &= ~CMD_STARTSERVER;
 | 
				
			||||||
		TAILQ_FOREACH(cmd, cmdlist, 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;
 | 
				
			||||||
			if (cmd->entry->flags & CMD_SENDENVIRON)
 | 
								if (cmd->entry->flags & CMD_SENDENVIRON)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user