mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Break new window and pane creation common code from various commands and
window.c into a separate file spawn.c.
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							@@ -104,6 +104,7 @@ SRCS=	alerts.c \
 | 
				
			|||||||
	server-fn.c \
 | 
						server-fn.c \
 | 
				
			||||||
	server.c \
 | 
						server.c \
 | 
				
			||||||
	session.c \
 | 
						session.c \
 | 
				
			||||||
 | 
						spawn.c \
 | 
				
			||||||
	status.c \
 | 
						status.c \
 | 
				
			||||||
	style.c \
 | 
						style.c \
 | 
				
			||||||
	tmux.c \
 | 
						tmux.c \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (wl != NULL) {
 | 
						if (wl != NULL) {
 | 
				
			||||||
		if (wp != NULL)
 | 
							if (wp != NULL)
 | 
				
			||||||
			window_set_active_pane(wp->window, wp);
 | 
								window_set_active_pane(wp->window, wp, 1);
 | 
				
			||||||
		session_set_current(s, wl);
 | 
							session_set_current(s, wl);
 | 
				
			||||||
		if (wp != NULL)
 | 
							if (wp != NULL)
 | 
				
			||||||
			cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
								cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	int			 size, percentage, dst_idx;
 | 
						int			 size, percentage, dst_idx;
 | 
				
			||||||
	enum layout_type	 type;
 | 
						enum layout_type	 type;
 | 
				
			||||||
	struct layout_cell	*lc;
 | 
						struct layout_cell	*lc;
 | 
				
			||||||
	int			 not_same_window;
 | 
						int			 not_same_window, flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (self->entry == &cmd_join_pane_entry)
 | 
						if (self->entry == &cmd_join_pane_entry)
 | 
				
			||||||
		not_same_window = 1;
 | 
							not_same_window = 1;
 | 
				
			||||||
@@ -124,7 +124,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		else
 | 
							else
 | 
				
			||||||
			size = (dst_wp->sx * percentage) / 100;
 | 
								size = (dst_wp->sx * percentage) / 100;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b'), 0);
 | 
						if (args_has(args, 'b'))
 | 
				
			||||||
 | 
							flags = SPAWN_BEFORE;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							flags = 0;
 | 
				
			||||||
 | 
						lc = layout_split_pane(dst_wp, type, size, flags);
 | 
				
			||||||
	if (lc == NULL) {
 | 
						if (lc == NULL) {
 | 
				
			||||||
		cmdq_error(item, "create pane failed: pane too small");
 | 
							cmdq_error(item, "create pane failed: pane too small");
 | 
				
			||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
@@ -145,7 +149,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	server_redraw_window(dst_w);
 | 
						server_redraw_window(dst_w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(args, 'd')) {
 | 
						if (!args_has(args, 'd')) {
 | 
				
			||||||
		window_set_active_pane(dst_w, src_wp);
 | 
							window_set_active_pane(dst_w, src_wp, 1);
 | 
				
			||||||
		session_select(dst_s, dst_idx);
 | 
							session_select(dst_s, dst_idx);
 | 
				
			||||||
		cmd_find_from_session(current, dst_s, 0);
 | 
							cmd_find_from_session(current, dst_s, 0);
 | 
				
			||||||
		server_redraw_session(dst_s);
 | 
							server_redraw_session(dst_s);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,12 +61,12 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
 | 
							RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
 | 
				
			||||||
			if (sloop != s) {
 | 
								if (sloop != s) {
 | 
				
			||||||
				server_destroy_session(sloop);
 | 
									server_destroy_session(sloop);
 | 
				
			||||||
				session_destroy(sloop, __func__);
 | 
									session_destroy(sloop, 1, __func__);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		server_destroy_session(s);
 | 
							server_destroy_session(s);
 | 
				
			||||||
		session_destroy(s, __func__);
 | 
							session_destroy(s, 1, __func__);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,20 +69,17 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
	struct client		*c = item->client;
 | 
						struct client		*c = item->client;
 | 
				
			||||||
	struct session		*s, *as, *groupwith;
 | 
						struct session		*s, *as, *groupwith;
 | 
				
			||||||
	struct window		*w;
 | 
					 | 
				
			||||||
	struct environ		*env;
 | 
						struct environ		*env;
 | 
				
			||||||
	struct options		*oo;
 | 
						struct options		*oo;
 | 
				
			||||||
	struct termios		 tio, *tiop;
 | 
						struct termios		 tio, *tiop;
 | 
				
			||||||
	struct session_group	*sg;
 | 
						struct session_group	*sg;
 | 
				
			||||||
	const char		*errstr, *template, *group, *prefix;
 | 
						const char		*errstr, *template, *group, *prefix, *tmp;
 | 
				
			||||||
	const char		*path, *cmd, *tmp, *value;
 | 
						char			*cause, *cwd = NULL, *cp, *newname = NULL;
 | 
				
			||||||
	char		       **argv, *cause, *cp, *newname, *cwd = NULL;
 | 
						int			 detached, already_attached, is_control = 0;
 | 
				
			||||||
	int			 detached, already_attached, idx, argc;
 | 
						u_int			 sx, sy, dsx, dsy;
 | 
				
			||||||
	int			 is_control = 0;
 | 
						struct spawn_context	 sc;
 | 
				
			||||||
	u_int			 sx, sy, dsx = 80, dsy = 24;
 | 
					 | 
				
			||||||
	struct environ_entry	*envent;
 | 
					 | 
				
			||||||
	struct cmd_find_state	 fs;
 | 
					 | 
				
			||||||
	enum cmd_retval		 retval;
 | 
						enum cmd_retval		 retval;
 | 
				
			||||||
 | 
						struct cmd_find_state    fs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (self->entry == &cmd_has_session_entry) {
 | 
						if (self->entry == &cmd_has_session_entry) {
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
@@ -97,13 +94,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	newname = NULL;
 | 
					 | 
				
			||||||
	if (args_has(args, 's')) {
 | 
						if (args_has(args, 's')) {
 | 
				
			||||||
		newname = format_single(item, args_get(args, 's'), c, NULL,
 | 
							newname = format_single(item, args_get(args, 's'), c, NULL,
 | 
				
			||||||
		    NULL, NULL);
 | 
							    NULL, NULL);
 | 
				
			||||||
		if (!session_check_name(newname)) {
 | 
							if (!session_check_name(newname)) {
 | 
				
			||||||
			cmdq_error(item, "bad session name: %s", newname);
 | 
								cmdq_error(item, "bad session name: %s", newname);
 | 
				
			||||||
			goto error;
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ((as = session_find(newname)) != NULL) {
 | 
							if ((as = session_find(newname)) != NULL) {
 | 
				
			||||||
			if (args_has(args, 'A')) {
 | 
								if (args_has(args, 'A')) {
 | 
				
			||||||
@@ -114,7 +110,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
				return (retval);
 | 
									return (retval);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			cmdq_error(item, "duplicate session: %s", newname);
 | 
								cmdq_error(item, "duplicate session: %s", newname);
 | 
				
			||||||
			goto error;
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,7 +121,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		if (groupwith == NULL) {
 | 
							if (groupwith == NULL) {
 | 
				
			||||||
			if (!session_check_name(group)) {
 | 
								if (!session_check_name(group)) {
 | 
				
			||||||
				cmdq_error(item, "bad group name: %s", group);
 | 
									cmdq_error(item, "bad group name: %s", group);
 | 
				
			||||||
				goto error;
 | 
									goto fail;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			sg = session_group_find(group);
 | 
								sg = session_group_find(group);
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
@@ -173,7 +169,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		if (server_client_check_nested(item->client)) {
 | 
							if (server_client_check_nested(item->client)) {
 | 
				
			||||||
			cmdq_error(item, "sessions should be nested with care, "
 | 
								cmdq_error(item, "sessions should be nested with care, "
 | 
				
			||||||
			    "unset $TMUX to force");
 | 
								    "unset $TMUX to force");
 | 
				
			||||||
			return (CMD_RETURN_ERROR);
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (tcgetattr(c->tty.fd, &tio) != 0)
 | 
							if (tcgetattr(c->tty.fd, &tio) != 0)
 | 
				
			||||||
			fatal("tcgetattr failed");
 | 
								fatal("tcgetattr failed");
 | 
				
			||||||
@@ -186,7 +182,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		if (server_client_open(c, &cause) != 0) {
 | 
							if (server_client_open(c, &cause) != 0) {
 | 
				
			||||||
			cmdq_error(item, "open terminal failed: %s", cause);
 | 
								cmdq_error(item, "open terminal failed: %s", cause);
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
			goto error;
 | 
								goto fail;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -200,7 +196,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
			dsx = strtonum(tmp, 1, USHRT_MAX, &errstr);
 | 
								dsx = strtonum(tmp, 1, USHRT_MAX, &errstr);
 | 
				
			||||||
			if (errstr != NULL) {
 | 
								if (errstr != NULL) {
 | 
				
			||||||
				cmdq_error(item, "width %s", errstr);
 | 
									cmdq_error(item, "width %s", errstr);
 | 
				
			||||||
				goto error;
 | 
									goto fail;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -213,7 +209,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
			dsy = strtonum(tmp, 1, USHRT_MAX, &errstr);
 | 
								dsy = strtonum(tmp, 1, USHRT_MAX, &errstr);
 | 
				
			||||||
			if (errstr != NULL) {
 | 
								if (errstr != NULL) {
 | 
				
			||||||
				cmdq_error(item, "height %s", errstr);
 | 
									cmdq_error(item, "height %s", errstr);
 | 
				
			||||||
				goto error;
 | 
									goto fail;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -225,8 +221,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		if (sy > 0 && options_get_number(global_s_options, "status"))
 | 
							if (sy > 0 && options_get_number(global_s_options, "status"))
 | 
				
			||||||
			sy--;
 | 
								sy--;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		value = options_get_string(global_s_options, "default-size");
 | 
							tmp = options_get_string(global_s_options, "default-size");
 | 
				
			||||||
		if (sscanf(value, "%ux%u", &sx, &sy) != 2) {
 | 
							if (sscanf(tmp, "%ux%u", &sx, &sy) != 2) {
 | 
				
			||||||
			sx = 80;
 | 
								sx = 80;
 | 
				
			||||||
			sy = 24;
 | 
								sy = 24;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -240,59 +236,34 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	if (sy == 0)
 | 
						if (sy == 0)
 | 
				
			||||||
		sy = 1;
 | 
							sy = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Figure out the command for the new window. */
 | 
						/* Create the new session. */
 | 
				
			||||||
	argc = -1;
 | 
					 | 
				
			||||||
	argv = NULL;
 | 
					 | 
				
			||||||
	if (!args_has(args, 't') && args->argc != 0) {
 | 
					 | 
				
			||||||
		argc = args->argc;
 | 
					 | 
				
			||||||
		argv = args->argv;
 | 
					 | 
				
			||||||
	} else if (sg == NULL && groupwith == NULL) {
 | 
					 | 
				
			||||||
		cmd = options_get_string(global_s_options, "default-command");
 | 
					 | 
				
			||||||
		if (cmd != NULL && *cmd != '\0') {
 | 
					 | 
				
			||||||
			argc = 1;
 | 
					 | 
				
			||||||
			argv = (char **)&cmd;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			argc = 0;
 | 
					 | 
				
			||||||
			argv = NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	path = NULL;
 | 
					 | 
				
			||||||
	if (c != NULL && c->session == NULL)
 | 
					 | 
				
			||||||
		envent = environ_find(c->environ, "PATH");
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		envent = environ_find(global_environ, "PATH");
 | 
					 | 
				
			||||||
	if (envent != NULL)
 | 
					 | 
				
			||||||
		path = envent->value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Construct the environment. */
 | 
					 | 
				
			||||||
	env = environ_create();
 | 
					 | 
				
			||||||
	if (c != NULL && !args_has(args, 'E'))
 | 
					 | 
				
			||||||
		environ_update(global_s_options, c->environ, env);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Set up the options. */
 | 
					 | 
				
			||||||
	oo = options_create(global_s_options);
 | 
						oo = options_create(global_s_options);
 | 
				
			||||||
	if (args_has(args, 'x') || args_has(args, 'y'))
 | 
						if (args_has(args, 'x') || args_has(args, 'y'))
 | 
				
			||||||
		options_set_string(oo, "default-size", 0, "%ux%u", dsx, dsy);
 | 
							options_set_string(oo, "default-size", 0, "%ux%u", dsx, dsy);
 | 
				
			||||||
 | 
						env = environ_create();
 | 
				
			||||||
 | 
						if (c != NULL && !args_has(args, 'E'))
 | 
				
			||||||
 | 
							environ_update(global_s_options, c->environ, env);
 | 
				
			||||||
 | 
						s = session_create(prefix, newname, cwd, env, oo, tiop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create the new session. */
 | 
						/* Spawn the initial window. */
 | 
				
			||||||
	idx = -1 - options_get_number(global_s_options, "base-index");
 | 
						memset(&sc, 0, sizeof sc);
 | 
				
			||||||
	s = session_create(prefix, newname, argc, argv, path, cwd, env, oo,
 | 
						sc.item = item;
 | 
				
			||||||
	    tiop, idx, &cause);
 | 
						sc.s = s;
 | 
				
			||||||
	environ_free(env);
 | 
					
 | 
				
			||||||
	if (s == NULL) {
 | 
						sc.name = args_get(args, 'n');
 | 
				
			||||||
		cmdq_error(item, "create session failed: %s", cause);
 | 
						sc.argc = args->argc;
 | 
				
			||||||
 | 
						sc.argv = args->argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.idx = -1;
 | 
				
			||||||
 | 
						sc.cwd = args_get(args, 'c');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spawn_window(&sc, &cause) == NULL) {
 | 
				
			||||||
 | 
							session_destroy(s, 0, __func__);
 | 
				
			||||||
 | 
							cmdq_error(item, "create window failed: %s", cause);
 | 
				
			||||||
		free(cause);
 | 
							free(cause);
 | 
				
			||||||
		goto error;
 | 
							goto fail;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Set the initial window name if one given. */
 | 
					 | 
				
			||||||
	if (argc >= 0 && (tmp = args_get(args, 'n')) != NULL) {
 | 
					 | 
				
			||||||
		cp = format_single(item, tmp, c, s, NULL, NULL);
 | 
					 | 
				
			||||||
		w = s->curw->window;
 | 
					 | 
				
			||||||
		window_set_name(w, cp);
 | 
					 | 
				
			||||||
		options_set_number(w->options, "automatic-rename", 0);
 | 
					 | 
				
			||||||
		free(cp);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -364,7 +335,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	free(newname);
 | 
						free(newname);
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error:
 | 
					fail:
 | 
				
			||||||
	free(cwd);
 | 
						free(cwd);
 | 
				
			||||||
	free(newname);
 | 
						free(newname);
 | 
				
			||||||
	return (CMD_RETURN_ERROR);
 | 
						return (CMD_RETURN_ERROR);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										103
									
								
								cmd-new-window.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								cmd-new-window.c
									
									
									
									
									
								
							@@ -53,87 +53,45 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
	struct cmd_find_state	*current = &item->shared->current;
 | 
						struct cmd_find_state	*current = &item->shared->current;
 | 
				
			||||||
 | 
						struct spawn_context	 sc;
 | 
				
			||||||
 | 
						struct client		*c = cmd_find_client(item, NULL, 1);
 | 
				
			||||||
	struct session		*s = item->target.s;
 | 
						struct session		*s = item->target.s;
 | 
				
			||||||
	struct winlink		*wl = item->target.wl;
 | 
						struct winlink		*wl = item->target.wl;
 | 
				
			||||||
	struct client		*c = cmd_find_client(item, NULL, 1);
 | 
					 | 
				
			||||||
	int			 idx = item->target.idx;
 | 
						int			 idx = item->target.idx;
 | 
				
			||||||
	const char		*cmd, *path, *template, *tmp;
 | 
						struct winlink		*new_wl;
 | 
				
			||||||
	char		       **argv, *cause, *cp, *cwd, *name;
 | 
						char			*cause = NULL, *cp;
 | 
				
			||||||
	int			 argc, detached;
 | 
						const char		*template;
 | 
				
			||||||
	struct environ_entry	*envent;
 | 
					 | 
				
			||||||
	struct cmd_find_state	 fs;
 | 
						struct cmd_find_state	 fs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args_has(args, 'a') && wl != NULL) {
 | 
						if (args_has(args, 'a') && (idx = winlink_shuffle_up(s, wl)) == -1) {
 | 
				
			||||||
		if ((idx = winlink_shuffle_up(s, wl)) == -1) {
 | 
							cmdq_error(item, "couldn't get a window index");
 | 
				
			||||||
			cmdq_error(item, "no free window indexes");
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
			return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	detached = args_has(args, 'd');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (args->argc == 0) {
 | 
					 | 
				
			||||||
		cmd = options_get_string(s->options, "default-command");
 | 
					 | 
				
			||||||
		if (cmd != NULL && *cmd != '\0') {
 | 
					 | 
				
			||||||
			argc = 1;
 | 
					 | 
				
			||||||
			argv = (char **)&cmd;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			argc = 0;
 | 
					 | 
				
			||||||
			argv = NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		argc = args->argc;
 | 
					 | 
				
			||||||
		argv = args->argv;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	path = NULL;
 | 
						memset(&sc, 0, sizeof sc);
 | 
				
			||||||
	if (item->client != NULL && item->client->session == NULL)
 | 
						sc.item = item;
 | 
				
			||||||
		envent = environ_find(item->client->environ, "PATH");
 | 
						sc.s = s;
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		envent = environ_find(s->environ, "PATH");
 | 
					 | 
				
			||||||
	if (envent != NULL)
 | 
					 | 
				
			||||||
		path = envent->value;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((tmp = args_get(args, 'c')) != NULL)
 | 
						sc.name = args_get(args, 'n');
 | 
				
			||||||
		cwd = format_single(item, tmp, c, s, NULL, NULL);
 | 
						sc.argc = args->argc;
 | 
				
			||||||
	else
 | 
						sc.argv = args->argv;
 | 
				
			||||||
		cwd = xstrdup(server_client_get_cwd(item->client, s));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((tmp = args_get(args, 'n')) != NULL)
 | 
						sc.idx = idx;
 | 
				
			||||||
		name = format_single(item, tmp, c, s, NULL, NULL);
 | 
						sc.cwd = args_get(args, 'c');
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		name = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (idx != -1)
 | 
						sc.flags = 0;
 | 
				
			||||||
		wl = winlink_find_by_index(&s->windows, idx);
 | 
						if (args_has(args, 'd'))
 | 
				
			||||||
	if (wl != NULL && args_has(args, 'k')) {
 | 
							sc.flags |= SPAWN_DETACHED;
 | 
				
			||||||
		/*
 | 
						if (args_has(args, 'k'))
 | 
				
			||||||
		 * Can't use session_detach as it will destroy session if this
 | 
							sc.flags |= SPAWN_KILL;
 | 
				
			||||||
		 * makes it empty.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		notify_session_window("window-unlinked", s, wl->window);
 | 
					 | 
				
			||||||
		wl->flags &= ~WINLINK_ALERTFLAGS;
 | 
					 | 
				
			||||||
		winlink_stack_remove(&s->lastw, wl);
 | 
					 | 
				
			||||||
		winlink_remove(&s->windows, wl);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Force select/redraw if current. */
 | 
						if ((new_wl = spawn_window(&sc, &cause)) == NULL) {
 | 
				
			||||||
		if (wl == s->curw) {
 | 
					 | 
				
			||||||
			detached = 0;
 | 
					 | 
				
			||||||
			s->curw = NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (idx == -1)
 | 
					 | 
				
			||||||
		idx = -1 - options_get_number(s->options, "base-index");
 | 
					 | 
				
			||||||
	wl = session_new(s, name, argc, argv, path, cwd, idx,
 | 
					 | 
				
			||||||
		&cause);
 | 
					 | 
				
			||||||
	if (wl == NULL) {
 | 
					 | 
				
			||||||
		cmdq_error(item, "create window failed: %s", cause);
 | 
							cmdq_error(item, "create window failed: %s", cause);
 | 
				
			||||||
		free(cause);
 | 
							free(cause);
 | 
				
			||||||
		goto error;
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!detached) {
 | 
						if (!args_has(args, 'd') || new_wl == s->curw) {
 | 
				
			||||||
		session_select(s, wl->idx);
 | 
							cmd_find_from_winlink(current, new_wl, 0);
 | 
				
			||||||
		cmd_find_from_winlink(current, wl, 0);
 | 
					 | 
				
			||||||
		server_redraw_session_group(s);
 | 
							server_redraw_session_group(s);
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		server_status_session_group(s);
 | 
							server_status_session_group(s);
 | 
				
			||||||
@@ -141,20 +99,13 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
	if (args_has(args, 'P')) {
 | 
						if (args_has(args, 'P')) {
 | 
				
			||||||
		if ((template = args_get(args, 'F')) == NULL)
 | 
							if ((template = args_get(args, 'F')) == NULL)
 | 
				
			||||||
			template = NEW_WINDOW_TEMPLATE;
 | 
								template = NEW_WINDOW_TEMPLATE;
 | 
				
			||||||
		cp = format_single(item, template, c, s, wl, NULL);
 | 
							cp = format_single(item, template, c, s, new_wl, NULL);
 | 
				
			||||||
		cmdq_print(item, "%s", cp);
 | 
							cmdq_print(item, "%s", cp);
 | 
				
			||||||
		free(cp);
 | 
							free(cp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd_find_from_winlink(&fs, wl, 0);
 | 
						cmd_find_from_winlink(&fs, new_wl, 0);
 | 
				
			||||||
	hooks_insert(s->hooks, item, &fs, "after-new-window");
 | 
						hooks_insert(s->hooks, item, &fs, "after-new-window");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(name);
 | 
					 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
error:
 | 
					 | 
				
			||||||
	free(name);
 | 
					 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
	return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,7 @@ cmdq_remove(struct cmdq_item *item)
 | 
				
			|||||||
	if (item->client != NULL)
 | 
						if (item->client != NULL)
 | 
				
			||||||
		server_client_unref(item->client);
 | 
							server_client_unref(item->client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (item->type == CMDQ_COMMAND)
 | 
						if (item->cmdlist != NULL)
 | 
				
			||||||
		cmd_list_free(item->cmdlist);
 | 
							cmd_list_free(item->cmdlist);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TAILQ_REMOVE(item->queue, item, entry);
 | 
						TAILQ_REMOVE(item->queue, item, entry);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	.args = { "c:kt:", 0, -1 },
 | 
						.args = { "c:kt:", 0, -1 },
 | 
				
			||||||
	.usage = "[-c start-directory] [-k] " CMD_TARGET_PANE_USAGE
 | 
						.usage = "[-c start-directory] [-k] " CMD_TARGET_PANE_USAGE
 | 
				
			||||||
	         " [command]",
 | 
							 " [command]",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
						.target = { 't', CMD_FIND_PANE, 0 },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,53 +48,39 @@ static enum cmd_retval
 | 
				
			|||||||
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
					cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
	struct winlink		*wl = item->target.wl;
 | 
						struct spawn_context	 sc;
 | 
				
			||||||
	struct window		*w = wl->window;
 | 
					 | 
				
			||||||
	struct window_pane	*wp = item->target.wp;
 | 
					 | 
				
			||||||
	struct client           *c = cmd_find_client(item, NULL, 1);
 | 
					 | 
				
			||||||
	struct session		*s = item->target.s;
 | 
						struct session		*s = item->target.s;
 | 
				
			||||||
	struct environ		*env;
 | 
						struct winlink		*wl = item->target.wl;
 | 
				
			||||||
	const char		*path = NULL, *cp;
 | 
						struct window_pane	*wp = item->target.wp;
 | 
				
			||||||
	char			*cause, *cwd = NULL;
 | 
						char			*cause = NULL;
 | 
				
			||||||
	u_int			 idx;
 | 
					 | 
				
			||||||
	struct environ_entry	*envent;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(self->args, 'k') && wp->fd != -1) {
 | 
						memset(&sc, 0, sizeof sc);
 | 
				
			||||||
		if (window_pane_index(wp, &idx) != 0)
 | 
						sc.item = item;
 | 
				
			||||||
			fatalx("index not found");
 | 
						sc.s = s;
 | 
				
			||||||
		cmdq_error(item, "pane still active: %s:%d.%u",
 | 
						sc.wl = wl;
 | 
				
			||||||
		    s->name, wl->idx, idx);
 | 
					 | 
				
			||||||
		return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_pane_reset_mode_all(wp);
 | 
						sc.wp0 = wp;
 | 
				
			||||||
	screen_reinit(&wp->base);
 | 
						sc.lc = NULL;
 | 
				
			||||||
	input_init(wp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (item->client != NULL && item->client->session == NULL)
 | 
						sc.name = NULL;
 | 
				
			||||||
		envent = environ_find(item->client->environ, "PATH");
 | 
						sc.argc = args->argc;
 | 
				
			||||||
	else
 | 
						sc.argv = args->argv;
 | 
				
			||||||
		envent = environ_find(s->environ, "PATH");
 | 
					 | 
				
			||||||
	if (envent != NULL)
 | 
					 | 
				
			||||||
		path = envent->value;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((cp = args_get(args, 'c')) != NULL)
 | 
						sc.idx = -1;
 | 
				
			||||||
		cwd = format_single(item, cp, c, s, NULL, NULL);
 | 
						sc.cwd = args_get(args, 'c');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	env = environ_for_session(s, 0);
 | 
						sc.flags = SPAWN_RESPAWN;
 | 
				
			||||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, cwd, env,
 | 
						if (args_has(args, 'k'))
 | 
				
			||||||
	    s->tio, &cause) != 0) {
 | 
							sc.flags |= SPAWN_KILL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spawn_pane(&sc, &cause) == NULL) {
 | 
				
			||||||
		cmdq_error(item, "respawn pane failed: %s", cause);
 | 
							cmdq_error(item, "respawn pane failed: %s", cause);
 | 
				
			||||||
		free(cause);
 | 
							free(cause);
 | 
				
			||||||
		environ_free(env);
 | 
					 | 
				
			||||||
		free(cwd);
 | 
					 | 
				
			||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	environ_free(env);
 | 
					 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wp->flags |= PANE_REDRAW;
 | 
						wp->flags |= PANE_REDRAW;
 | 
				
			||||||
	server_status_window(w);
 | 
						server_status_window(wp->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,64 +48,34 @@ static enum cmd_retval
 | 
				
			|||||||
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
					cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
 | 
						struct spawn_context	 sc;
 | 
				
			||||||
	struct session		*s = item->target.s;
 | 
						struct session		*s = item->target.s;
 | 
				
			||||||
	struct winlink		*wl = item->target.wl;
 | 
						struct winlink		*wl = item->target.wl;
 | 
				
			||||||
	struct window		*w = wl->window;
 | 
						char			*cause = NULL;
 | 
				
			||||||
	struct window_pane	*wp;
 | 
					 | 
				
			||||||
	struct client           *c = cmd_find_client(item, NULL, 1);
 | 
					 | 
				
			||||||
	struct environ		*env;
 | 
					 | 
				
			||||||
	const char		*path = NULL, *cp;
 | 
					 | 
				
			||||||
	char		 	*cause, *cwd = NULL;
 | 
					 | 
				
			||||||
	struct environ_entry	*envent;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(self->args, 'k')) {
 | 
						memset(&sc, 0, sizeof sc);
 | 
				
			||||||
		TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
						sc.item = item;
 | 
				
			||||||
			if (wp->fd == -1)
 | 
						sc.s = s;
 | 
				
			||||||
				continue;
 | 
						sc.wl = wl;
 | 
				
			||||||
			cmdq_error(item, "window still active: %s:%d", s->name,
 | 
					 | 
				
			||||||
			    wl->idx);
 | 
					 | 
				
			||||||
			return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wp = TAILQ_FIRST(&w->panes);
 | 
						sc.name = NULL;
 | 
				
			||||||
	TAILQ_REMOVE(&w->panes, wp, entry);
 | 
						sc.argc = args->argc;
 | 
				
			||||||
	layout_free(w);
 | 
						sc.argv = args->argv;
 | 
				
			||||||
	window_destroy_panes(w);
 | 
					 | 
				
			||||||
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
					 | 
				
			||||||
	window_pane_resize(wp, w->sx, w->sy);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (item->client != NULL && item->client->session == NULL)
 | 
						sc.idx = -1;
 | 
				
			||||||
		envent = environ_find(item->client->environ, "PATH");
 | 
						sc.cwd = args_get(args, 'c');
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		envent = environ_find(s->environ, "PATH");
 | 
					 | 
				
			||||||
	if (envent != NULL)
 | 
					 | 
				
			||||||
		path = envent->value;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((cp = args_get(args, 'c')) != NULL)
 | 
						sc.flags = SPAWN_RESPAWN;
 | 
				
			||||||
		cwd = format_single(item, cp, c, s, NULL, NULL);
 | 
						if (args_has(args, 'k'))
 | 
				
			||||||
 | 
							sc.flags |= SPAWN_KILL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	env = environ_for_session(s, 0);
 | 
						if (spawn_window(&sc, &cause) == NULL) {
 | 
				
			||||||
	if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, cwd, env,
 | 
					 | 
				
			||||||
	    s->tio, &cause) != 0) {
 | 
					 | 
				
			||||||
		cmdq_error(item, "respawn window failed: %s", cause);
 | 
							cmdq_error(item, "respawn window failed: %s", cause);
 | 
				
			||||||
		free(cause);
 | 
							free(cause);
 | 
				
			||||||
		environ_free(env);
 | 
					 | 
				
			||||||
		free(cwd);
 | 
					 | 
				
			||||||
		server_destroy_pane(wp, 0);
 | 
					 | 
				
			||||||
		return (CMD_RETURN_ERROR);
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	environ_free(env);
 | 
					 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	layout_init(w, wp);
 | 
						server_redraw_window(wl->window);
 | 
				
			||||||
	window_pane_reset_mode_all(wp);
 | 
					 | 
				
			||||||
	screen_reinit(&wp->base);
 | 
					 | 
				
			||||||
	input_init(wp);
 | 
					 | 
				
			||||||
	window_set_active_pane(w, wp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	recalculate_sizes();
 | 
					 | 
				
			||||||
	server_redraw_window(w);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
 | 
							if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
 | 
				
			||||||
			wp = TAILQ_LAST(&w->panes, window_panes);
 | 
								wp = TAILQ_LAST(&w->panes, window_panes);
 | 
				
			||||||
		window_set_active_pane(w, wp);
 | 
							window_set_active_pane(w, wp, 1);
 | 
				
			||||||
		cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
							cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
				
			||||||
		server_redraw_window(w);
 | 
							server_redraw_window(w);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
@@ -105,7 +105,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
 | 
							if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
 | 
				
			||||||
			wp = TAILQ_FIRST(&w->panes);
 | 
								wp = TAILQ_FIRST(&w->panes);
 | 
				
			||||||
		window_set_active_pane(w, wp);
 | 
							window_set_active_pane(w, wp, 1);
 | 
				
			||||||
		cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
							cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
				
			||||||
		server_redraw_window(w);
 | 
							server_redraw_window(w);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -112,7 +112,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		else {
 | 
							else {
 | 
				
			||||||
			server_unzoom_window(w);
 | 
								server_unzoom_window(w);
 | 
				
			||||||
			window_redraw_active_switch(w, lastwp);
 | 
								window_redraw_active_switch(w, lastwp);
 | 
				
			||||||
			if (window_set_active_pane(w, lastwp)) {
 | 
								if (window_set_active_pane(w, lastwp, 1)) {
 | 
				
			||||||
				cmd_find_from_winlink(current, wl, 0);
 | 
									cmd_find_from_winlink(current, wl, 0);
 | 
				
			||||||
				cmd_select_pane_redraw(w);
 | 
									cmd_select_pane_redraw(w);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -194,7 +194,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		return (CMD_RETURN_NORMAL);
 | 
							return (CMD_RETURN_NORMAL);
 | 
				
			||||||
	server_unzoom_window(wp->window);
 | 
						server_unzoom_window(wp->window);
 | 
				
			||||||
	window_redraw_active_switch(w, wp);
 | 
						window_redraw_active_switch(w, wp);
 | 
				
			||||||
	if (window_set_active_pane(w, wp)) {
 | 
						if (window_set_active_pane(w, wp, 1)) {
 | 
				
			||||||
		cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
							cmd_find_from_winlink_pane(current, wl, wp, 0);
 | 
				
			||||||
		hooks_insert(s->hooks, item, current, "after-select-pane");
 | 
							hooks_insert(s->hooks, item, current, "after-select-pane");
 | 
				
			||||||
		cmd_select_pane_redraw(w);
 | 
							cmd_select_pane_redraw(w);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,111 +53,87 @@ const struct cmd_entry cmd_split_window_entry = {
 | 
				
			|||||||
static enum cmd_retval
 | 
					static enum cmd_retval
 | 
				
			||||||
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
					cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd_find_state	*current = &item->shared->current;
 | 
					 | 
				
			||||||
	struct args		*args = self->args;
 | 
						struct args		*args = self->args;
 | 
				
			||||||
 | 
						struct cmd_find_state	*current = &item->shared->current;
 | 
				
			||||||
 | 
						struct spawn_context	 sc;
 | 
				
			||||||
	struct client		*c = cmd_find_client(item, NULL, 1);
 | 
						struct client		*c = cmd_find_client(item, NULL, 1);
 | 
				
			||||||
	struct session		*s = item->target.s;
 | 
						struct session		*s = item->target.s;
 | 
				
			||||||
	struct winlink		*wl = item->target.wl;
 | 
						struct winlink		*wl = item->target.wl;
 | 
				
			||||||
	struct window		*w = wl->window;
 | 
						struct window_pane	*wp = item->target.wp, *new_wp;
 | 
				
			||||||
	struct window_pane	*wp = item->target.wp, *new_wp = NULL;
 | 
					 | 
				
			||||||
	struct environ		*env;
 | 
					 | 
				
			||||||
	const char		*cmd, *path, *shell, *template, *tmp;
 | 
					 | 
				
			||||||
	char		       **argv, *cause, *new_cause, *cp, *cwd;
 | 
					 | 
				
			||||||
	u_int			 hlimit;
 | 
					 | 
				
			||||||
	int			 argc, size, percentage, before;
 | 
					 | 
				
			||||||
	enum layout_type	 type;
 | 
						enum layout_type	 type;
 | 
				
			||||||
	struct layout_cell	*lc;
 | 
						struct layout_cell	*lc;
 | 
				
			||||||
	struct environ_entry	*envent;
 | 
						struct cmd_find_state	 fs;
 | 
				
			||||||
	struct cmd_find_state    fs;
 | 
						int			 size, percentage, flags;
 | 
				
			||||||
 | 
						const char		*template;
 | 
				
			||||||
 | 
						char			*cause, *cp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	server_unzoom_window(w);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (args->argc == 0) {
 | 
					 | 
				
			||||||
		cmd = options_get_string(s->options, "default-command");
 | 
					 | 
				
			||||||
		if (cmd != NULL && *cmd != '\0') {
 | 
					 | 
				
			||||||
			argc = 1;
 | 
					 | 
				
			||||||
			argv = (char **)&cmd;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			argc = 0;
 | 
					 | 
				
			||||||
			argv = NULL;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		argc = args->argc;
 | 
					 | 
				
			||||||
		argv = args->argv;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((tmp = args_get(args, 'c')) != NULL)
 | 
					 | 
				
			||||||
		cwd = format_single(item, tmp, c, s, NULL, NULL);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		cwd = xstrdup(server_client_get_cwd(item->client, s));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	type = LAYOUT_TOPBOTTOM;
 | 
					 | 
				
			||||||
	if (args_has(args, 'h'))
 | 
						if (args_has(args, 'h'))
 | 
				
			||||||
		type = LAYOUT_LEFTRIGHT;
 | 
							type = LAYOUT_LEFTRIGHT;
 | 
				
			||||||
	before = args_has(args, 'b');
 | 
						else
 | 
				
			||||||
 | 
							type = LAYOUT_TOPBOTTOM;
 | 
				
			||||||
	size = -1;
 | 
					 | 
				
			||||||
	if (args_has(args, 'l')) {
 | 
						if (args_has(args, 'l')) {
 | 
				
			||||||
		size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
 | 
							size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
 | 
				
			||||||
		if (cause != NULL) {
 | 
							if (cause != NULL) {
 | 
				
			||||||
			xasprintf(&new_cause, "size %s", cause);
 | 
								cmdq_error(item, "create pane failed: -l %s", cause);
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
			cause = new_cause;
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
			goto error;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (args_has(args, 'p')) {
 | 
						} else if (args_has(args, 'p')) {
 | 
				
			||||||
		percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
 | 
							percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
 | 
				
			||||||
		if (cause != NULL) {
 | 
							if (cause != NULL) {
 | 
				
			||||||
			xasprintf(&new_cause, "percentage %s", cause);
 | 
								cmdq_error(item, "create pane failed: -p %s", cause);
 | 
				
			||||||
			free(cause);
 | 
								free(cause);
 | 
				
			||||||
			cause = new_cause;
 | 
								return (CMD_RETURN_ERROR);
 | 
				
			||||||
			goto error;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (type == LAYOUT_TOPBOTTOM)
 | 
							if (type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
			size = (wp->sy * percentage) / 100;
 | 
								size = (wp->sy * percentage) / 100;
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			size = (wp->sx * percentage) / 100;
 | 
								size = (wp->sx * percentage) / 100;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	hlimit = options_get_number(s->options, "history-limit");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	shell = options_get_string(s->options, "default-shell");
 | 
					 | 
				
			||||||
	if (*shell == '\0' || areshell(shell))
 | 
					 | 
				
			||||||
		shell = _PATH_BSHELL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	lc = layout_split_pane(wp, type, size, before, args_has(args, 'f'));
 | 
					 | 
				
			||||||
	if (lc == NULL) {
 | 
					 | 
				
			||||||
		cause = xstrdup("pane too small");
 | 
					 | 
				
			||||||
		goto error;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	new_wp = window_add_pane(w, wp, before, args_has(args, 'f'), hlimit);
 | 
					 | 
				
			||||||
	layout_make_leaf(lc, new_wp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	path = NULL;
 | 
					 | 
				
			||||||
	if (item->client != NULL && item->client->session == NULL)
 | 
					 | 
				
			||||||
		envent = environ_find(item->client->environ, "PATH");
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		envent = environ_find(s->environ, "PATH");
 | 
					 | 
				
			||||||
	if (envent != NULL)
 | 
					 | 
				
			||||||
		path = envent->value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	env = environ_for_session(s, 0);
 | 
					 | 
				
			||||||
	if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
 | 
					 | 
				
			||||||
	    s->tio, &cause) != 0) {
 | 
					 | 
				
			||||||
		environ_free(env);
 | 
					 | 
				
			||||||
		goto error;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	environ_free(env);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	layout_fix_panes(w);
 | 
					 | 
				
			||||||
	server_redraw_window(w);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!args_has(args, 'd')) {
 | 
					 | 
				
			||||||
		window_set_active_pane(w, new_wp);
 | 
					 | 
				
			||||||
		session_select(s, wl->idx);
 | 
					 | 
				
			||||||
		cmd_find_from_session(current, s, 0);
 | 
					 | 
				
			||||||
		server_redraw_session(s);
 | 
					 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		server_status_session(s);
 | 
							size = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						server_unzoom_window(wp->window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						flags = 0;
 | 
				
			||||||
 | 
						if (args_has(args, 'b'))
 | 
				
			||||||
 | 
							flags |= SPAWN_BEFORE;
 | 
				
			||||||
 | 
						if (args_has(args, 'f'))
 | 
				
			||||||
 | 
							flags |= SPAWN_FULLSIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lc = layout_split_pane(wp, type, size, flags);
 | 
				
			||||||
 | 
						if (lc == NULL) {
 | 
				
			||||||
 | 
							cmdq_error(item, "no space for new pane");
 | 
				
			||||||
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memset(&sc, 0, sizeof sc);
 | 
				
			||||||
 | 
						sc.item = item;
 | 
				
			||||||
 | 
						sc.s = s;
 | 
				
			||||||
 | 
						sc.wl = wl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.wp0 = wp;
 | 
				
			||||||
 | 
						sc.lc = lc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.name = NULL;
 | 
				
			||||||
 | 
						sc.argc = args->argc;
 | 
				
			||||||
 | 
						sc.argv = args->argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.idx = -1;
 | 
				
			||||||
 | 
						sc.cwd = args_get(args, 'c');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc.flags = flags;
 | 
				
			||||||
 | 
						if (args_has(args, 'd'))
 | 
				
			||||||
 | 
							sc.flags |= SPAWN_DETACHED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
 | 
				
			||||||
 | 
							cmdq_error(item, "create pane failed: %s", cause);
 | 
				
			||||||
 | 
							free(cause);
 | 
				
			||||||
 | 
							return (CMD_RETURN_ERROR);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!args_has(args, 'd'))
 | 
				
			||||||
 | 
							cmd_find_from_winlink_pane(current, wl, new_wp, 0);
 | 
				
			||||||
 | 
						server_redraw_window(wp->window);
 | 
				
			||||||
 | 
						server_status_session(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args_has(args, 'P')) {
 | 
						if (args_has(args, 'P')) {
 | 
				
			||||||
		if ((template = args_get(args, 'F')) == NULL)
 | 
							if ((template = args_get(args, 'F')) == NULL)
 | 
				
			||||||
@@ -166,22 +142,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
		cmdq_print(item, "%s", cp);
 | 
							cmdq_print(item, "%s", cp);
 | 
				
			||||||
		free(cp);
 | 
							free(cp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	notify_window("window-layout-changed", w);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
 | 
						cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
 | 
				
			||||||
	hooks_insert(s->hooks, item, &fs, "after-split-window");
 | 
						hooks_insert(s->hooks, item, &fs, "after-split-window");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
 | 
					 | 
				
			||||||
error:
 | 
					 | 
				
			||||||
	if (new_wp != NULL) {
 | 
					 | 
				
			||||||
		layout_close_pane(new_wp);
 | 
					 | 
				
			||||||
		window_remove_pane(w, new_wp);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cmdq_error(item, "create pane failed: %s", cause);
 | 
					 | 
				
			||||||
	free(cause);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(cwd);
 | 
					 | 
				
			||||||
	return (CMD_RETURN_ERROR);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,17 +101,17 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (!args_has(self->args, 'd')) {
 | 
						if (!args_has(self->args, 'd')) {
 | 
				
			||||||
		if (src_w != dst_w) {
 | 
							if (src_w != dst_w) {
 | 
				
			||||||
			window_set_active_pane(src_w, dst_wp);
 | 
								window_set_active_pane(src_w, dst_wp, 1);
 | 
				
			||||||
			window_set_active_pane(dst_w, src_wp);
 | 
								window_set_active_pane(dst_w, src_wp, 1);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			tmp_wp = dst_wp;
 | 
								tmp_wp = dst_wp;
 | 
				
			||||||
			window_set_active_pane(src_w, tmp_wp);
 | 
								window_set_active_pane(src_w, tmp_wp, 1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (src_w->active == src_wp)
 | 
							if (src_w->active == src_wp)
 | 
				
			||||||
			window_set_active_pane(src_w, dst_wp);
 | 
								window_set_active_pane(src_w, dst_wp, 1);
 | 
				
			||||||
		if (dst_w->active == dst_wp)
 | 
							if (dst_w->active == dst_wp)
 | 
				
			||||||
			window_set_active_pane(dst_w, src_wp);
 | 
								window_set_active_pane(dst_w, src_wp, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (src_w != dst_w) {
 | 
						if (src_w != dst_w) {
 | 
				
			||||||
		if (src_w->last == src_wp)
 | 
							if (src_w->last == src_wp)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
 | 
				
			|||||||
			server_unzoom_window(wl->window);
 | 
								server_unzoom_window(wl->window);
 | 
				
			||||||
			if (wp != NULL) {
 | 
								if (wp != NULL) {
 | 
				
			||||||
				window_redraw_active_switch(wp->window, wp);
 | 
									window_redraw_active_switch(wp->window, wp);
 | 
				
			||||||
				window_set_active_pane(wp->window, wp);
 | 
									window_set_active_pane(wp->window, wp, 1);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			session_set_current(s, wl);
 | 
								session_set_current(s, wl);
 | 
				
			||||||
			cmd_find_from_session(&item->shared->current, s, 0);
 | 
								cmd_find_from_session(&item->shared->current, s, 0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								layout.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								layout.c
									
									
									
									
									
								
							@@ -831,11 +831,12 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
struct layout_cell *
 | 
					struct layout_cell *
 | 
				
			||||||
layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
					layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			||||||
    int insert_before, int full_size)
 | 
					    int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct layout_cell     *lc, *lcparent, *lcnew, *lc1, *lc2;
 | 
						struct layout_cell     *lc, *lcparent, *lcnew, *lc1, *lc2;
 | 
				
			||||||
	u_int			sx, sy, xoff, yoff, size1, size2;
 | 
						u_int			sx, sy, xoff, yoff, size1, size2;
 | 
				
			||||||
	u_int			new_size, saved_size, resize_first = 0;
 | 
						u_int			new_size, saved_size, resize_first = 0;
 | 
				
			||||||
 | 
						int			full_size = (flags & SPAWN_FULLSIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If full_size is specified, add a new cell at the top of the window
 | 
						 * If full_size is specified, add a new cell at the top of the window
 | 
				
			||||||
@@ -876,7 +877,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			|||||||
		saved_size = sy;
 | 
							saved_size = sy;
 | 
				
			||||||
	if (size < 0)
 | 
						if (size < 0)
 | 
				
			||||||
		size2 = ((saved_size + 1) / 2) - 1;
 | 
							size2 = ((saved_size + 1) / 2) - 1;
 | 
				
			||||||
	else if (insert_before)
 | 
						else if (flags & SPAWN_BEFORE)
 | 
				
			||||||
		size2 = saved_size - size - 1;
 | 
							size2 = saved_size - size - 1;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		size2 = size;
 | 
							size2 = size;
 | 
				
			||||||
@@ -887,7 +888,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			|||||||
	size1 = saved_size - 1 - size2;
 | 
						size1 = saved_size - 1 - size2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Which size are we using? */
 | 
						/* Which size are we using? */
 | 
				
			||||||
	if (insert_before)
 | 
						if (flags & SPAWN_BEFORE)
 | 
				
			||||||
		new_size = size2;
 | 
							new_size = size2;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		new_size = size1;
 | 
							new_size = size1;
 | 
				
			||||||
@@ -903,7 +904,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			|||||||
		 */
 | 
							 */
 | 
				
			||||||
		lcparent = lc->parent;
 | 
							lcparent = lc->parent;
 | 
				
			||||||
		lcnew = layout_create_cell(lcparent);
 | 
							lcnew = layout_create_cell(lcparent);
 | 
				
			||||||
		if (insert_before)
 | 
							if (flags & SPAWN_BEFORE)
 | 
				
			||||||
			TAILQ_INSERT_BEFORE(lc, lcnew, entry);
 | 
								TAILQ_INSERT_BEFORE(lc, lcnew, entry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
 | 
								TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry);
 | 
				
			||||||
@@ -932,7 +933,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			|||||||
			layout_set_size(lcnew, size, sy, 0, 0);
 | 
								layout_set_size(lcnew, size, sy, 0, 0);
 | 
				
			||||||
		else if (lc->type == LAYOUT_TOPBOTTOM)
 | 
							else if (lc->type == LAYOUT_TOPBOTTOM)
 | 
				
			||||||
			layout_set_size(lcnew, sx, size, 0, 0);
 | 
								layout_set_size(lcnew, sx, size, 0, 0);
 | 
				
			||||||
		if (insert_before)
 | 
							if (flags & SPAWN_BEFORE)
 | 
				
			||||||
			TAILQ_INSERT_HEAD(&lc->cells, lcnew, entry);
 | 
								TAILQ_INSERT_HEAD(&lc->cells, lcnew, entry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
 | 
								TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
 | 
				
			||||||
@@ -956,12 +957,12 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		/* Create the new child cell. */
 | 
							/* Create the new child cell. */
 | 
				
			||||||
		lcnew = layout_create_cell(lcparent);
 | 
							lcnew = layout_create_cell(lcparent);
 | 
				
			||||||
		if (insert_before)
 | 
							if (flags & SPAWN_BEFORE)
 | 
				
			||||||
			TAILQ_INSERT_HEAD(&lcparent->cells, lcnew, entry);
 | 
								TAILQ_INSERT_HEAD(&lcparent->cells, lcnew, entry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
 | 
								TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (insert_before) {
 | 
						if (flags & SPAWN_BEFORE) {
 | 
				
			||||||
		lc1 = lcnew;
 | 
							lc1 = lcnew;
 | 
				
			||||||
		lc2 = lc;
 | 
							lc2 = lc;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -368,7 +368,7 @@ server_destroy_session_group(struct session *s)
 | 
				
			|||||||
	else {
 | 
						else {
 | 
				
			||||||
		TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
 | 
							TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
 | 
				
			||||||
			server_destroy_session(s);
 | 
								server_destroy_session(s);
 | 
				
			||||||
			session_destroy(s, __func__);
 | 
								session_destroy(s, 1, __func__);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -435,7 +435,7 @@ server_check_unattached(void)
 | 
				
			|||||||
		if (s->attached != 0)
 | 
							if (s->attached != 0)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		if (options_get_number (s->options, "destroy-unattached"))
 | 
							if (options_get_number (s->options, "destroy-unattached"))
 | 
				
			||||||
			session_destroy(s, __func__);
 | 
								session_destroy(s, 1, __func__);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								server.c
									
									
									
									
									
								
							@@ -297,7 +297,7 @@ server_send_exit(void)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RB_FOREACH_SAFE(s, sessions, &sessions, s1)
 | 
						RB_FOREACH_SAFE(s, sessions, &sessions, s1)
 | 
				
			||||||
		session_destroy(s, __func__);
 | 
							session_destroy(s, 1, __func__);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Update socket execute permissions based on whether sessions are attached. */
 | 
					/* Update socket execute permissions based on whether sessions are attached. */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										68
									
								
								session.c
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								session.c
									
									
									
									
									
								
							@@ -112,12 +112,10 @@ session_find_by_id(u_int id)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Create a new session. */
 | 
					/* Create a new session. */
 | 
				
			||||||
struct session *
 | 
					struct session *
 | 
				
			||||||
session_create(const char *prefix, const char *name, int argc, char **argv,
 | 
					session_create(const char *prefix, const char *name, const char *cwd,
 | 
				
			||||||
    const char *path, const char *cwd, struct environ *env, struct options *oo,
 | 
					    struct environ *env, struct options *oo, struct termios *tio)
 | 
				
			||||||
    struct termios *tio, int idx, char **cause)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session	*s;
 | 
						struct session	*s;
 | 
				
			||||||
	struct winlink	*wl;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = xcalloc(1, sizeof *s);
 | 
						s = xcalloc(1, sizeof *s);
 | 
				
			||||||
	s->references = 1;
 | 
						s->references = 1;
 | 
				
			||||||
@@ -129,10 +127,7 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
 | 
				
			|||||||
	TAILQ_INIT(&s->lastw);
 | 
						TAILQ_INIT(&s->lastw);
 | 
				
			||||||
	RB_INIT(&s->windows);
 | 
						RB_INIT(&s->windows);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->environ = environ_create();
 | 
						s->environ = env;
 | 
				
			||||||
	if (env != NULL)
 | 
					 | 
				
			||||||
		environ_copy(env, s->environ);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	s->options = oo;
 | 
						s->options = oo;
 | 
				
			||||||
	s->hooks = hooks_create(global_hooks);
 | 
						s->hooks = hooks_create(global_hooks);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -166,17 +161,6 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
 | 
				
			|||||||
		fatal("gettimeofday failed");
 | 
							fatal("gettimeofday failed");
 | 
				
			||||||
	session_update_activity(s, &s->creation_time);
 | 
						session_update_activity(s, &s->creation_time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argc >= 0) {
 | 
					 | 
				
			||||||
		wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
 | 
					 | 
				
			||||||
		if (wl == NULL) {
 | 
					 | 
				
			||||||
			session_destroy(s, __func__);
 | 
					 | 
				
			||||||
			return (NULL);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		session_select(s, RB_ROOT(&s->windows)->idx);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	log_debug("session %s created", s->name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (s);
 | 
						return (s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -220,7 +204,7 @@ session_free(__unused int fd, __unused short events, void *arg)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Destroy a session. */
 | 
					/* Destroy a session. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
session_destroy(struct session *s, const char *from)
 | 
					session_destroy(struct session *s, int notify, const char *from)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct winlink	*wl;
 | 
						struct winlink	*wl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -228,7 +212,8 @@ session_destroy(struct session *s, const char *from)
 | 
				
			|||||||
	s->curw = NULL;
 | 
						s->curw = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RB_REMOVE(sessions, &sessions, s);
 | 
						RB_REMOVE(sessions, &sessions, s);
 | 
				
			||||||
	notify_session("session-closed", s);
 | 
						if (notify)
 | 
				
			||||||
 | 
							notify_session("session-closed", s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(s->tio);
 | 
						free(s->tio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -338,45 +323,6 @@ session_previous_session(struct session *s)
 | 
				
			|||||||
	return (s2);
 | 
						return (s2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Create a new window on a session. */
 | 
					 | 
				
			||||||
struct winlink *
 | 
					 | 
				
			||||||
session_new(struct session *s, const char *name, int argc, char **argv,
 | 
					 | 
				
			||||||
    const char *path, const char *cwd, int idx, char **cause)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct window	*w;
 | 
					 | 
				
			||||||
	struct winlink	*wl;
 | 
					 | 
				
			||||||
	struct environ	*env;
 | 
					 | 
				
			||||||
	const char	*shell;
 | 
					 | 
				
			||||||
	u_int		 hlimit, sx, sy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((wl = winlink_add(&s->windows, idx)) == NULL) {
 | 
					 | 
				
			||||||
		xasprintf(cause, "index in use: %d", idx);
 | 
					 | 
				
			||||||
		return (NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wl->session = s;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	shell = options_get_string(s->options, "default-shell");
 | 
					 | 
				
			||||||
	if (*shell == '\0' || areshell(shell))
 | 
					 | 
				
			||||||
		shell = _PATH_BSHELL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default_window_size(s, NULL, &sx, &sy, -1);
 | 
					 | 
				
			||||||
	hlimit = options_get_number(s->options, "history-limit");
 | 
					 | 
				
			||||||
	env = environ_for_session(s, 0);
 | 
					 | 
				
			||||||
	w = window_create_spawn(name, argc, argv, path, shell, cwd, env, s->tio,
 | 
					 | 
				
			||||||
	    sx, sy, hlimit, cause);
 | 
					 | 
				
			||||||
	if (w == NULL) {
 | 
					 | 
				
			||||||
		winlink_remove(&s->windows, wl);
 | 
					 | 
				
			||||||
		environ_free(env);
 | 
					 | 
				
			||||||
		return (NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	winlink_set_window(wl, w);
 | 
					 | 
				
			||||||
	environ_free(env);
 | 
					 | 
				
			||||||
	notify_session_window("window-linked", s, w);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	session_group_synchronize_from(s);
 | 
					 | 
				
			||||||
	return (wl);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Attach a window to a session. */
 | 
					/* Attach a window to a session. */
 | 
				
			||||||
struct winlink *
 | 
					struct winlink *
 | 
				
			||||||
session_attach(struct session *s, struct window *w, int idx, char **cause)
 | 
					session_attach(struct session *s, struct window *w, int idx, char **cause)
 | 
				
			||||||
@@ -412,7 +358,7 @@ session_detach(struct session *s, struct winlink *wl)
 | 
				
			|||||||
	session_group_synchronize_from(s);
 | 
						session_group_synchronize_from(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (RB_EMPTY(&s->windows)) {
 | 
						if (RB_EMPTY(&s->windows)) {
 | 
				
			||||||
		session_destroy(s, __func__);
 | 
							session_destroy(s, 1, __func__);
 | 
				
			||||||
		return (1);
 | 
							return (1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return (0);
 | 
						return (0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										434
									
								
								spawn.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								spawn.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
				
			|||||||
 | 
					/* $OpenBSD$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission to use, copy, modify, and distribute this software for any
 | 
				
			||||||
 | 
					 * purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 * copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
				
			||||||
 | 
					 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <paths.h>
 | 
				
			||||||
 | 
					#include <signal.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <util.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Set up the environment and create a new window and pane or a new pane.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * We need to set up the following items:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - history limit, comes from the session;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - base index, comes from the session;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - current working directory, may be specified - if it isn't it comes from
 | 
				
			||||||
 | 
					 *   either the client or the session;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - PATH variable, comes from the client if any, otherwise from the session
 | 
				
			||||||
 | 
					 *   environment;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - shell, comes from default-shell;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - termios, comes from the session;
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * - remaining environment, comes from the session.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					spawn_log(const char *from, struct spawn_context *sc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session		*s = sc->s;
 | 
				
			||||||
 | 
						struct winlink		*wl = sc->wl;
 | 
				
			||||||
 | 
						struct window_pane	*wp0 = sc->wp0;
 | 
				
			||||||
 | 
						char			 tmp[128];
 | 
				
			||||||
 | 
						const char		*name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log_debug("%s: %s, flags=%#x", from, sc->item->name, sc->flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wl != NULL && wp0 != NULL)
 | 
				
			||||||
 | 
							xsnprintf(tmp, sizeof tmp, "wl=%d wp0=%%%u", wl->idx, wp0->id);
 | 
				
			||||||
 | 
						else if (wl != NULL)
 | 
				
			||||||
 | 
							xsnprintf(tmp, sizeof tmp, "wl=%d wp0=none", wl->idx);
 | 
				
			||||||
 | 
						else if (wp0 != NULL)
 | 
				
			||||||
 | 
							xsnprintf(tmp, sizeof tmp, "wl=none wp0=%%%u", wp0->id);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							xsnprintf(tmp, sizeof tmp, "wl=none wp0=none");
 | 
				
			||||||
 | 
						log_debug("%s: s=$%u %s idx=%d", from, s->id, tmp, sc->idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						name = sc->name;
 | 
				
			||||||
 | 
						if (name == NULL)
 | 
				
			||||||
 | 
							name = "none";
 | 
				
			||||||
 | 
						log_debug("%s: name=%s", from, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct winlink *
 | 
				
			||||||
 | 
					spawn_window(struct spawn_context *sc, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct session		*s = sc->s;
 | 
				
			||||||
 | 
						struct window		*w;
 | 
				
			||||||
 | 
						struct window_pane	*wp;
 | 
				
			||||||
 | 
						struct winlink		*wl;
 | 
				
			||||||
 | 
						int			 idx = sc->idx;
 | 
				
			||||||
 | 
						u_int			 sx, sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spawn_log(__func__, sc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If the window already exists, we are respawning, so destroy all the
 | 
				
			||||||
 | 
						 * panes except one.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
							w = sc->wl->window;
 | 
				
			||||||
 | 
							if (~sc->flags & SPAWN_KILL) {
 | 
				
			||||||
 | 
								TAILQ_FOREACH(wp, &w->panes, entry) {
 | 
				
			||||||
 | 
									if (wp->fd != -1)
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (wp != NULL) {
 | 
				
			||||||
 | 
									xasprintf(cause, "window %s:%d still active",
 | 
				
			||||||
 | 
									    s->name, sc->wl->idx);
 | 
				
			||||||
 | 
									return (NULL);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sc->wp0 = TAILQ_FIRST(&w->panes);
 | 
				
			||||||
 | 
							TAILQ_REMOVE(&w->panes, sc->wp0, entry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							layout_free(w);
 | 
				
			||||||
 | 
							window_destroy_panes(w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							TAILQ_INSERT_HEAD(&w->panes, sc->wp0, entry);
 | 
				
			||||||
 | 
							window_pane_resize(sc->wp0, w->sx, w->sy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							layout_init(w, sc->wp0);
 | 
				
			||||||
 | 
							window_set_active_pane(w, sc->wp0, 0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Otherwise we have no window so we will need to create one. First
 | 
				
			||||||
 | 
						 * check if the given index already exists and destroy it if so.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if ((~sc->flags & SPAWN_RESPAWN) && idx != -1) {
 | 
				
			||||||
 | 
							wl = winlink_find_by_index(&s->windows, idx);
 | 
				
			||||||
 | 
							if (wl != NULL && (~sc->flags & SPAWN_KILL)) {
 | 
				
			||||||
 | 
								xasprintf(cause, "index %d in use", idx);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (wl != NULL) {
 | 
				
			||||||
 | 
								/*
 | 
				
			||||||
 | 
								 * Can't use session_detach as it will destroy session
 | 
				
			||||||
 | 
								 * if this makes it empty.
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								wl->flags &= ~WINLINK_ALERTFLAGS;
 | 
				
			||||||
 | 
								notify_session_window("window-unlinked", s, wl->window);
 | 
				
			||||||
 | 
								winlink_stack_remove(&s->lastw, wl);
 | 
				
			||||||
 | 
								winlink_remove(&s->windows, wl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (s->curw == wl) {
 | 
				
			||||||
 | 
									s->curw = NULL;
 | 
				
			||||||
 | 
									sc->flags &= ~SPAWN_DETACHED;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Then create a window if needed. */
 | 
				
			||||||
 | 
						if (~sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
							if (idx == -1)
 | 
				
			||||||
 | 
								idx = -1 - options_get_number(s->options, "base-index");
 | 
				
			||||||
 | 
							if ((sc->wl = winlink_add(&s->windows, idx)) == NULL) {
 | 
				
			||||||
 | 
								xasprintf(cause, "couldn't add window %d", idx);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							default_window_size(s, NULL, &sx, &sy, -1);
 | 
				
			||||||
 | 
							if ((w = window_create(sx, sy)) == NULL) {
 | 
				
			||||||
 | 
								winlink_remove(&s->windows, sc->wl);
 | 
				
			||||||
 | 
								xasprintf(cause, "couldn't create window %d", idx);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sc->wl->session = s;
 | 
				
			||||||
 | 
							winlink_set_window(sc->wl, w);
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							w = NULL;
 | 
				
			||||||
 | 
						sc->flags |= SPAWN_NONOTIFY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Spawn the pane. */
 | 
				
			||||||
 | 
						wp = spawn_pane(sc, cause);
 | 
				
			||||||
 | 
						if (wp == NULL) {
 | 
				
			||||||
 | 
							if (~sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
								window_destroy(w);
 | 
				
			||||||
 | 
								winlink_remove(&s->windows, sc->wl);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set the name of the new window. */
 | 
				
			||||||
 | 
						if (~sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
							if (sc->name != NULL) {
 | 
				
			||||||
 | 
								w->name = xstrdup(sc->name);
 | 
				
			||||||
 | 
								options_set_number(w->options, "automatic-rename", 0);
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								w->name = xstrdup(default_window_name(w));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Switch to the new window if required. */
 | 
				
			||||||
 | 
						if (~sc->flags & SPAWN_DETACHED)
 | 
				
			||||||
 | 
							session_select(s, sc->wl->idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fire notification if new window. */
 | 
				
			||||||
 | 
						if (~sc->flags & SPAWN_RESPAWN)
 | 
				
			||||||
 | 
							notify_session_window("window-linked", s, w);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session_group_synchronize_from(s);
 | 
				
			||||||
 | 
						return (sc->wl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct window_pane *
 | 
				
			||||||
 | 
					spawn_pane(struct spawn_context *sc, char **cause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cmdq_item	 *item = sc->item;
 | 
				
			||||||
 | 
						struct client		 *c = item->client;
 | 
				
			||||||
 | 
						struct session		 *s = sc->s;
 | 
				
			||||||
 | 
						struct window		 *w = sc->wl->window;
 | 
				
			||||||
 | 
						struct window_pane	 *new_wp;
 | 
				
			||||||
 | 
						struct environ		 *child;
 | 
				
			||||||
 | 
						struct environ_entry	 *ee;
 | 
				
			||||||
 | 
						char			**argv, *cp, **argvp, *argv0, *cwd;
 | 
				
			||||||
 | 
						const char		 *cmd, *tmp;
 | 
				
			||||||
 | 
						int			  argc;
 | 
				
			||||||
 | 
						u_int			  idx;
 | 
				
			||||||
 | 
						struct termios		  now;
 | 
				
			||||||
 | 
						u_int			  hlimit;
 | 
				
			||||||
 | 
						struct winsize		  ws;
 | 
				
			||||||
 | 
						sigset_t		  set, oldset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spawn_log(__func__, sc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If we are respawning then get rid of the old process. Otherwise
 | 
				
			||||||
 | 
						 * either create a new cell or assign to the one we are given.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						hlimit = options_get_number(s->options, "history-limit");
 | 
				
			||||||
 | 
						if (sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
							if (sc->wp0->fd != -1 && (~sc->flags & SPAWN_KILL)) {
 | 
				
			||||||
 | 
								window_pane_index(sc->wp0, &idx);
 | 
				
			||||||
 | 
								xasprintf(cause, "pane %s:%d.%u still active",
 | 
				
			||||||
 | 
								    s->name, sc->wl->idx, idx);
 | 
				
			||||||
 | 
								return (NULL);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (sc->wp0->fd != -1) {
 | 
				
			||||||
 | 
								bufferevent_free(sc->wp0->event);
 | 
				
			||||||
 | 
								close(sc->wp0->fd);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							window_pane_reset_mode_all(sc->wp0);
 | 
				
			||||||
 | 
							screen_reinit(&sc->wp0->base);
 | 
				
			||||||
 | 
							input_init(sc->wp0);
 | 
				
			||||||
 | 
							new_wp = sc->wp0;
 | 
				
			||||||
 | 
							new_wp->flags &= ~(PANE_STATUSREADY|PANE_STATUSDRAWN);
 | 
				
			||||||
 | 
						} else if (sc->lc == NULL) {
 | 
				
			||||||
 | 
							new_wp = window_add_pane(w, NULL, hlimit, sc->flags);
 | 
				
			||||||
 | 
							layout_init(w, new_wp);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							new_wp = window_add_pane(w, sc->wp0, hlimit, sc->flags);
 | 
				
			||||||
 | 
							layout_assign_pane(sc->lc, new_wp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Now we have a pane with nothing running in it ready for the new
 | 
				
			||||||
 | 
						 * process. Work out the command and arguments.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (sc->argc == 0) {
 | 
				
			||||||
 | 
							cmd = options_get_string(s->options, "default-command");
 | 
				
			||||||
 | 
							if (cmd != NULL && *cmd != '\0') {
 | 
				
			||||||
 | 
								argc = 1;
 | 
				
			||||||
 | 
								argv = (char **)&cmd;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								argc = 0;
 | 
				
			||||||
 | 
								argv = NULL;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							argc = sc->argc;
 | 
				
			||||||
 | 
							argv = sc->argv;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Replace the stored arguments if there are new ones. If not, the
 | 
				
			||||||
 | 
						 * existing ones will be used (they will only exist for respawn).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (argc > 0) {
 | 
				
			||||||
 | 
							cmd_free_argv(new_wp->argc, new_wp->argv);
 | 
				
			||||||
 | 
							new_wp->argc = argc;
 | 
				
			||||||
 | 
							new_wp->argv = cmd_copy_argv(argc, argv);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Work out the current working directory. If respawning, use
 | 
				
			||||||
 | 
						 * the pane's stored one unless specified.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (sc->cwd != NULL)
 | 
				
			||||||
 | 
							cwd = format_single(item, sc->cwd, c, s, NULL, NULL);
 | 
				
			||||||
 | 
						else if (~sc->flags & SPAWN_RESPAWN)
 | 
				
			||||||
 | 
							cwd = xstrdup(server_client_get_cwd(c, s));
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							cwd = NULL;
 | 
				
			||||||
 | 
						if (cwd != NULL) {
 | 
				
			||||||
 | 
							free(new_wp->cwd);
 | 
				
			||||||
 | 
							new_wp->cwd = cwd;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create an environment for this pane. */
 | 
				
			||||||
 | 
						child = environ_for_session(s, 0);
 | 
				
			||||||
 | 
						environ_set(child, "TMUX_PANE", "%%%u", new_wp->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Then the PATH environment variable. The session one is replaced from
 | 
				
			||||||
 | 
						 * the client if there is one because otherwise running "tmux new
 | 
				
			||||||
 | 
						 * myprogram" wouldn't work if myprogram isn't in the session's path.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (c != NULL && c->session == NULL) { /* only unattached clients */
 | 
				
			||||||
 | 
							ee = environ_find(c->environ, "PATH");
 | 
				
			||||||
 | 
							if (ee != NULL)
 | 
				
			||||||
 | 
								environ_set(child, "PATH", "%s", ee->value);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (environ_find(child, "PATH") == NULL)
 | 
				
			||||||
 | 
							environ_set(child, "%s", _PATH_DEFPATH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Then the shell. If respawning, use the old one. */
 | 
				
			||||||
 | 
						if (~sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
							tmp = options_get_string(s->options, "default-shell");
 | 
				
			||||||
 | 
							if (*tmp == '\0' || areshell(tmp))
 | 
				
			||||||
 | 
								tmp = _PATH_BSHELL;
 | 
				
			||||||
 | 
							free(new_wp->shell);
 | 
				
			||||||
 | 
							new_wp->shell = xstrdup(tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						environ_set(child, "SHELL", "%s", new_wp->shell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Log the arguments we are going to use. */
 | 
				
			||||||
 | 
						log_debug("%s: shell=%s", __func__, new_wp->shell);
 | 
				
			||||||
 | 
						if (new_wp->argc != 0) {
 | 
				
			||||||
 | 
							cp = cmd_stringify_argv(new_wp->argc, new_wp->argv);
 | 
				
			||||||
 | 
							log_debug("%s: cmd=%s", __func__, cp);
 | 
				
			||||||
 | 
							free(cp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (cwd != NULL)
 | 
				
			||||||
 | 
							log_debug("%s: cwd=%s", __func__, cwd);
 | 
				
			||||||
 | 
						cmd_log_argv(new_wp->argc, new_wp->argv, __func__);
 | 
				
			||||||
 | 
						environ_log(child, "%s: environment ", __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Initialize the window size. */
 | 
				
			||||||
 | 
						memset(&ws, 0, sizeof ws);
 | 
				
			||||||
 | 
						ws.ws_col = screen_size_x(&new_wp->base);
 | 
				
			||||||
 | 
						ws.ws_row = screen_size_y(&new_wp->base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Block signals until fork has completed. */
 | 
				
			||||||
 | 
						sigfillset(&set);
 | 
				
			||||||
 | 
						sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Fork the new process. */
 | 
				
			||||||
 | 
						new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
 | 
				
			||||||
 | 
						if (new_wp->pid == -1) {
 | 
				
			||||||
 | 
							xasprintf(cause, "fork failed: %s", strerror(errno));
 | 
				
			||||||
 | 
							new_wp->fd = -1;
 | 
				
			||||||
 | 
							if (~sc->flags & SPAWN_RESPAWN) {
 | 
				
			||||||
 | 
								layout_close_pane(new_wp);
 | 
				
			||||||
 | 
								window_remove_pane(w, new_wp);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
 | 
							return (NULL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* In the parent process, everything is done now. */
 | 
				
			||||||
 | 
						if (new_wp->pid != 0) {
 | 
				
			||||||
 | 
							new_wp->pipe_off = 0;
 | 
				
			||||||
 | 
							new_wp->flags &= ~PANE_EXITED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
 | 
							window_pane_set_event(new_wp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (sc->flags & SPAWN_RESPAWN)
 | 
				
			||||||
 | 
								return (new_wp);
 | 
				
			||||||
 | 
							if ((~sc->flags & SPAWN_DETACHED) || w->active == NULL) {
 | 
				
			||||||
 | 
								if (sc->flags & SPAWN_NONOTIFY)
 | 
				
			||||||
 | 
									window_set_active_pane(w, new_wp, 0);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									window_set_active_pane(w, new_wp, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (~sc->flags & SPAWN_NONOTIFY)
 | 
				
			||||||
 | 
								notify_window("window-layout-changed", w);
 | 
				
			||||||
 | 
							return (new_wp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Child process. Change to the working directory or home if that
 | 
				
			||||||
 | 
						 * fails.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (chdir(new_wp->cwd) != 0) {
 | 
				
			||||||
 | 
							if ((tmp = find_home()) == NULL || chdir(tmp) != 0)
 | 
				
			||||||
 | 
								chdir("/");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Update terminal escape characters from the session if available and
 | 
				
			||||||
 | 
						 * force VERASE to tmux's \177.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (tcgetattr(STDIN_FILENO, &now) != 0)
 | 
				
			||||||
 | 
							_exit(1);
 | 
				
			||||||
 | 
						if (s->tio != NULL)
 | 
				
			||||||
 | 
							memcpy(now.c_cc, s->tio->c_cc, sizeof now.c_cc);
 | 
				
			||||||
 | 
						now.c_cc[VERASE] = '\177';
 | 
				
			||||||
 | 
						if (tcsetattr(STDIN_FILENO, TCSANOW, &now) != 0)
 | 
				
			||||||
 | 
							_exit(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Clean up file descriptors and signals and update the environment. */
 | 
				
			||||||
 | 
						closefrom(STDERR_FILENO + 1);
 | 
				
			||||||
 | 
						proc_clear_signals(server_proc, 1);
 | 
				
			||||||
 | 
						sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
				
			||||||
 | 
						log_close();
 | 
				
			||||||
 | 
						environ_push(child);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If given multiple arguments, use execvp(). Copy the arguments to
 | 
				
			||||||
 | 
						 * ensure they end in a NULL.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (new_wp->argc != 0 && new_wp->argc != 1) {
 | 
				
			||||||
 | 
							argvp = cmd_copy_argv(new_wp->argc, new_wp->argv);
 | 
				
			||||||
 | 
							execvp(argvp[0], argvp);
 | 
				
			||||||
 | 
							_exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If one argument, pass it to $SHELL -c. Otherwise create a login
 | 
				
			||||||
 | 
						 * shell.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						cp = strrchr(new_wp->shell, '/');
 | 
				
			||||||
 | 
						if (new_wp->argc == 1) {
 | 
				
			||||||
 | 
							tmp = new_wp->argv[0];
 | 
				
			||||||
 | 
							if (cp != NULL && cp[1] != '\0')
 | 
				
			||||||
 | 
								xasprintf(&argv0, "%s", cp + 1);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								xasprintf(&argv0, "%s", new_wp->shell);
 | 
				
			||||||
 | 
							execl(new_wp->shell, argv0, "-c", tmp, (char *)NULL);
 | 
				
			||||||
 | 
							_exit(1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (cp != NULL && cp[1] != '\0')
 | 
				
			||||||
 | 
							xasprintf(&argv0, "-%s", cp + 1);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							xasprintf(&argv0, "-%s", new_wp->shell);
 | 
				
			||||||
 | 
						execl(new_wp->shell, argv0, (char *)NULL);
 | 
				
			||||||
 | 
						_exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								tmux.h
									
									
									
									
									
								
							@@ -233,8 +233,8 @@ enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Termcap codes. */
 | 
					/* Termcap codes. */
 | 
				
			||||||
enum tty_code_code {
 | 
					enum tty_code_code {
 | 
				
			||||||
	TTYC_AX = 0,
 | 
					 | 
				
			||||||
	TTYC_ACSC,
 | 
						TTYC_ACSC,
 | 
				
			||||||
 | 
						TTYC_AX,
 | 
				
			||||||
	TTYC_BCE,
 | 
						TTYC_BCE,
 | 
				
			||||||
	TTYC_BEL,
 | 
						TTYC_BEL,
 | 
				
			||||||
	TTYC_BLINK,
 | 
						TTYC_BLINK,
 | 
				
			||||||
@@ -814,7 +814,7 @@ struct window_pane {
 | 
				
			|||||||
	int		 argc;
 | 
						int		 argc;
 | 
				
			||||||
	char	       **argv;
 | 
						char	       **argv;
 | 
				
			||||||
	char		*shell;
 | 
						char		*shell;
 | 
				
			||||||
	const char	*cwd;
 | 
						char		*cwd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pid_t		 pid;
 | 
						pid_t		 pid;
 | 
				
			||||||
	char		 tty[TTY_NAME_MAX];
 | 
						char		 tty[TTY_NAME_MAX];
 | 
				
			||||||
@@ -1561,6 +1561,32 @@ struct options_table_entry {
 | 
				
			|||||||
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
 | 
					#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
 | 
				
			||||||
#define CMD_BUFFER_USAGE "[-b buffer-name]"
 | 
					#define CMD_BUFFER_USAGE "[-b buffer-name]"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Spawn common context. */
 | 
				
			||||||
 | 
					struct spawn_context {
 | 
				
			||||||
 | 
						struct cmdq_item	 *item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct session		 *s;
 | 
				
			||||||
 | 
						struct winlink		 *wl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct window_pane	 *wp0;
 | 
				
			||||||
 | 
						struct layout_cell	 *lc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char		 *name;
 | 
				
			||||||
 | 
						char			**argv;
 | 
				
			||||||
 | 
						int			  argc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			  idx;
 | 
				
			||||||
 | 
						const char		 *cwd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int			  flags;
 | 
				
			||||||
 | 
					#define SPAWN_KILL 0x1
 | 
				
			||||||
 | 
					#define SPAWN_DETACHED 0x2
 | 
				
			||||||
 | 
					#define SPAWN_RESPAWN 0x4
 | 
				
			||||||
 | 
					#define SPAWN_BEFORE 0x8
 | 
				
			||||||
 | 
					#define SPAWN_NONOTIFY 0x10
 | 
				
			||||||
 | 
					#define SPAWN_FULLSIZE 0x20
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* tmux.c */
 | 
					/* tmux.c */
 | 
				
			||||||
extern struct hooks	*global_hooks;
 | 
					extern struct hooks	*global_hooks;
 | 
				
			||||||
extern struct options	*global_options;
 | 
					extern struct options	*global_options;
 | 
				
			||||||
@@ -2232,17 +2258,17 @@ struct window	*window_find_by_id_str(const char *);
 | 
				
			|||||||
struct window	*window_find_by_id(u_int);
 | 
					struct window	*window_find_by_id(u_int);
 | 
				
			||||||
void		 window_update_activity(struct window *);
 | 
					void		 window_update_activity(struct window *);
 | 
				
			||||||
struct window	*window_create(u_int, u_int);
 | 
					struct window	*window_create(u_int, u_int);
 | 
				
			||||||
struct window	*window_create_spawn(const char *, int, char **, const char *,
 | 
					void		 window_destroy(struct window *);
 | 
				
			||||||
		     const char *, const char *, struct environ *,
 | 
					void		 window_pane_set_event(struct window_pane *);
 | 
				
			||||||
		     struct termios *, u_int, u_int, u_int, char **);
 | 
					 | 
				
			||||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
 | 
					struct window_pane *window_get_active_at(struct window *, u_int, u_int);
 | 
				
			||||||
struct window_pane *window_find_string(struct window *, const char *);
 | 
					struct window_pane *window_find_string(struct window *, const char *);
 | 
				
			||||||
int		 window_has_pane(struct window *, struct window_pane *);
 | 
					int		 window_has_pane(struct window *, struct window_pane *);
 | 
				
			||||||
int		 window_set_active_pane(struct window *, struct window_pane *);
 | 
					int		 window_set_active_pane(struct window *, struct window_pane *,
 | 
				
			||||||
 | 
							     int);
 | 
				
			||||||
void		 window_redraw_active_switch(struct window *,
 | 
					void		 window_redraw_active_switch(struct window *,
 | 
				
			||||||
		     struct window_pane *);
 | 
							     struct window_pane *);
 | 
				
			||||||
struct window_pane *window_add_pane(struct window *, struct window_pane *, int,
 | 
					struct window_pane *window_add_pane(struct window *, struct window_pane *,
 | 
				
			||||||
		     int, u_int);
 | 
							     u_int, int);
 | 
				
			||||||
void		 window_resize(struct window *, u_int, u_int);
 | 
					void		 window_resize(struct window *, u_int, u_int);
 | 
				
			||||||
int		 window_zoom(struct window_pane *);
 | 
					int		 window_zoom(struct window_pane *);
 | 
				
			||||||
int		 window_unzoom(struct window *);
 | 
					int		 window_unzoom(struct window *);
 | 
				
			||||||
@@ -2259,9 +2285,6 @@ void		 window_destroy_panes(struct window *);
 | 
				
			|||||||
struct window_pane *window_pane_find_by_id_str(const char *);
 | 
					struct window_pane *window_pane_find_by_id_str(const char *);
 | 
				
			||||||
struct window_pane *window_pane_find_by_id(u_int);
 | 
					struct window_pane *window_pane_find_by_id(u_int);
 | 
				
			||||||
int		 window_pane_destroy_ready(struct window_pane *);
 | 
					int		 window_pane_destroy_ready(struct window_pane *);
 | 
				
			||||||
int		 window_pane_spawn(struct window_pane *, int, char **,
 | 
					 | 
				
			||||||
		     const char *, const char *, const char *, struct environ *,
 | 
					 | 
				
			||||||
		     struct termios *, char **);
 | 
					 | 
				
			||||||
void		 window_pane_resize(struct window_pane *, u_int, u_int);
 | 
					void		 window_pane_resize(struct window_pane *, u_int, u_int);
 | 
				
			||||||
void		 window_pane_alternate_on(struct window_pane *,
 | 
					void		 window_pane_alternate_on(struct window_pane *,
 | 
				
			||||||
		     struct grid_cell *, int);
 | 
							     struct grid_cell *, int);
 | 
				
			||||||
@@ -2319,7 +2342,7 @@ void		 layout_resize_pane_to(struct window_pane *, enum layout_type,
 | 
				
			|||||||
		     u_int);
 | 
							     u_int);
 | 
				
			||||||
void		 layout_assign_pane(struct layout_cell *, struct window_pane *);
 | 
					void		 layout_assign_pane(struct layout_cell *, struct window_pane *);
 | 
				
			||||||
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
 | 
					struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
 | 
				
			||||||
		     int, int, int);
 | 
							     int, int);
 | 
				
			||||||
void		 layout_close_pane(struct window_pane *);
 | 
					void		 layout_close_pane(struct window_pane *);
 | 
				
			||||||
int		 layout_spread_cell(struct window *, struct layout_cell *);
 | 
					int		 layout_spread_cell(struct window *, struct layout_cell *);
 | 
				
			||||||
void		 layout_spread_out(struct window_pane *);
 | 
					void		 layout_spread_out(struct window_pane *);
 | 
				
			||||||
@@ -2418,10 +2441,9 @@ int		 session_alive(struct session *);
 | 
				
			|||||||
struct session	*session_find(const char *);
 | 
					struct session	*session_find(const char *);
 | 
				
			||||||
struct session	*session_find_by_id_str(const char *);
 | 
					struct session	*session_find_by_id_str(const char *);
 | 
				
			||||||
struct session	*session_find_by_id(u_int);
 | 
					struct session	*session_find_by_id(u_int);
 | 
				
			||||||
struct session	*session_create(const char *, const char *, int, char **,
 | 
					struct session	*session_create(const char *, const char *, const char *,
 | 
				
			||||||
		     const char *, const char *, struct environ *,
 | 
							     struct environ *, struct options *, struct termios *);
 | 
				
			||||||
		     struct options *, struct termios *, int, char **);
 | 
					void		 session_destroy(struct session *, int,  const char *);
 | 
				
			||||||
void		 session_destroy(struct session *, const char *);
 | 
					 | 
				
			||||||
void		 session_add_ref(struct session *, const char *);
 | 
					void		 session_add_ref(struct session *, const char *);
 | 
				
			||||||
void		 session_remove_ref(struct session *, const char *);
 | 
					void		 session_remove_ref(struct session *, const char *);
 | 
				
			||||||
int		 session_check_name(const char *);
 | 
					int		 session_check_name(const char *);
 | 
				
			||||||
@@ -2493,4 +2515,8 @@ void		 style_set(struct style *, const struct grid_cell *);
 | 
				
			|||||||
void		 style_copy(struct style *, struct style *);
 | 
					void		 style_copy(struct style *, struct style *);
 | 
				
			||||||
int		 style_is_default(struct style *);
 | 
					int		 style_is_default(struct style *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* spawn.c */
 | 
				
			||||||
 | 
					struct winlink	*spawn_window(struct spawn_context *, char **);
 | 
				
			||||||
 | 
					struct window_pane *spawn_pane(struct spawn_context *, char **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* TMUX_H */
 | 
					#endif /* TMUX_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1006,7 +1006,7 @@ window_tree_kill_each(__unused void* modedata, void* itemdata,
 | 
				
			|||||||
	case WINDOW_TREE_SESSION:
 | 
						case WINDOW_TREE_SESSION:
 | 
				
			||||||
		if (s != NULL) {
 | 
							if (s != NULL) {
 | 
				
			||||||
			server_destroy_session(s);
 | 
								server_destroy_session(s);
 | 
				
			||||||
			session_destroy(s, __func__);
 | 
								session_destroy(s, 1, __func__);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case WINDOW_TREE_WINDOW:
 | 
						case WINDOW_TREE_WINDOW:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										215
									
								
								window.c
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								window.c
									
									
									
									
									
								
							@@ -26,7 +26,6 @@
 | 
				
			|||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <termios.h>
 | 
					 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <util.h>
 | 
					#include <util.h>
 | 
				
			||||||
@@ -73,20 +72,10 @@ const struct window_mode *all_window_modes[] = {
 | 
				
			|||||||
	NULL
 | 
						NULL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void	window_destroy(struct window *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
 | 
					static struct window_pane *window_pane_create(struct window *, u_int, u_int,
 | 
				
			||||||
		    u_int);
 | 
							    u_int);
 | 
				
			||||||
static void	window_pane_destroy(struct window_pane *);
 | 
					static void	window_pane_destroy(struct window_pane *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void	window_pane_read_callback(struct bufferevent *, void *);
 | 
					 | 
				
			||||||
static void	window_pane_error_callback(struct bufferevent *, short, void *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int	winlink_next_index(struct winlinks *, int);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct window_pane *window_pane_choose_best(struct window_pane **,
 | 
					 | 
				
			||||||
		    u_int);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
RB_GENERATE(windows, window, entry, window_cmp);
 | 
					RB_GENERATE(windows, window, entry, window_cmp);
 | 
				
			||||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
 | 
					RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
 | 
				
			||||||
RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
 | 
					RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
 | 
				
			||||||
@@ -342,37 +331,7 @@ window_create(u_int sx, u_int sy)
 | 
				
			|||||||
	return (w);
 | 
						return (w);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct window *
 | 
					void
 | 
				
			||||||
window_create_spawn(const char *name, int argc, char **argv, const char *path,
 | 
					 | 
				
			||||||
    const char *shell, const char *cwd, struct environ *env,
 | 
					 | 
				
			||||||
    struct termios *tio, u_int sx, u_int sy, u_int hlimit, char **cause)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct window		*w;
 | 
					 | 
				
			||||||
	struct window_pane	*wp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	w = window_create(sx, sy);
 | 
					 | 
				
			||||||
	wp = window_add_pane(w, NULL, 0, 0, hlimit);
 | 
					 | 
				
			||||||
	layout_init(w, wp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (window_pane_spawn(wp, argc, argv, path, shell, cwd,
 | 
					 | 
				
			||||||
	    env, tio, cause) != 0) {
 | 
					 | 
				
			||||||
		window_destroy(w);
 | 
					 | 
				
			||||||
		return (NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	w->active = TAILQ_FIRST(&w->panes);
 | 
					 | 
				
			||||||
	if (name != NULL) {
 | 
					 | 
				
			||||||
		w->name = xstrdup(name);
 | 
					 | 
				
			||||||
		options_set_number(w->options, "automatic-rename", 0);
 | 
					 | 
				
			||||||
	} else
 | 
					 | 
				
			||||||
		w->name = default_window_name(w);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	notify_window("window-pane-changed", w);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (w);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
window_destroy(struct window *w)
 | 
					window_destroy(struct window *w)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	log_debug("window @%u destroyed (%d references)", w->id, w->references);
 | 
						log_debug("window @%u destroyed (%d references)", w->id, w->references);
 | 
				
			||||||
@@ -463,17 +422,22 @@ window_has_pane(struct window *w, struct window_pane *wp)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
window_set_active_pane(struct window *w, struct window_pane *wp)
 | 
					window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	log_debug("%s: pane %%%u (was %%%u)", __func__, wp->id, w->active->id);
 | 
						log_debug("%s: pane %%%u", __func__, wp->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wp == w->active)
 | 
						if (wp == w->active)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
	w->last = w->active;
 | 
						w->last = w->active;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w->active = wp;
 | 
						w->active = wp;
 | 
				
			||||||
	w->active->active_point = next_active_point++;
 | 
						w->active->active_point = next_active_point++;
 | 
				
			||||||
	w->active->flags |= PANE_CHANGED;
 | 
						w->active->flags |= PANE_CHANGED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tty_update_window_offset(w);
 | 
						tty_update_window_offset(w);
 | 
				
			||||||
	notify_window("window-pane-changed", w);
 | 
					
 | 
				
			||||||
 | 
						if (notify)
 | 
				
			||||||
 | 
							notify_window("window-pane-changed", w);
 | 
				
			||||||
	return (1);
 | 
						return (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -571,7 +535,7 @@ window_zoom(struct window_pane *wp)
 | 
				
			|||||||
		return (-1);
 | 
							return (-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (w->active != wp)
 | 
						if (w->active != wp)
 | 
				
			||||||
		window_set_active_pane(w, wp);
 | 
							window_set_active_pane(w, wp, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TAILQ_FOREACH(wp1, &w->panes, entry) {
 | 
						TAILQ_FOREACH(wp1, &w->panes, entry) {
 | 
				
			||||||
		wp1->saved_layout_cell = wp1->layout_cell;
 | 
							wp1->saved_layout_cell = wp1->layout_cell;
 | 
				
			||||||
@@ -610,8 +574,8 @@ window_unzoom(struct window *w)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct window_pane *
 | 
					struct window_pane *
 | 
				
			||||||
window_add_pane(struct window *w, struct window_pane *other, int before,
 | 
					window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
 | 
				
			||||||
    int full_size, u_int hlimit)
 | 
					    int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct window_pane	*wp;
 | 
						struct window_pane	*wp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -622,15 +586,15 @@ window_add_pane(struct window *w, struct window_pane *other, int before,
 | 
				
			|||||||
	if (TAILQ_EMPTY(&w->panes)) {
 | 
						if (TAILQ_EMPTY(&w->panes)) {
 | 
				
			||||||
		log_debug("%s: @%u at start", __func__, w->id);
 | 
							log_debug("%s: @%u at start", __func__, w->id);
 | 
				
			||||||
		TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
							TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
				
			||||||
	} else if (before) {
 | 
						} else if (flags & SPAWN_BEFORE) {
 | 
				
			||||||
		log_debug("%s: @%u before %%%u", __func__, w->id, wp->id);
 | 
							log_debug("%s: @%u before %%%u", __func__, w->id, wp->id);
 | 
				
			||||||
		if (full_size)
 | 
							if (flags & SPAWN_FULLSIZE)
 | 
				
			||||||
			TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
								TAILQ_INSERT_HEAD(&w->panes, wp, entry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			TAILQ_INSERT_BEFORE(other, wp, entry);
 | 
								TAILQ_INSERT_BEFORE(other, wp, entry);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
 | 
							log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
 | 
				
			||||||
		if (full_size)
 | 
							if (flags & SPAWN_FULLSIZE)
 | 
				
			||||||
			TAILQ_INSERT_TAIL(&w->panes, wp, entry);
 | 
								TAILQ_INSERT_TAIL(&w->panes, wp, entry);
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
 | 
								TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
 | 
				
			||||||
@@ -887,141 +851,6 @@ window_pane_destroy(struct window_pane *wp)
 | 
				
			|||||||
	free(wp);
 | 
						free(wp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					 | 
				
			||||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
 | 
					 | 
				
			||||||
    const char *path, const char *shell, const char *cwd, struct environ *env,
 | 
					 | 
				
			||||||
    struct termios *tio, char **cause)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct winsize	 ws;
 | 
					 | 
				
			||||||
	char		*argv0, *cmd, **argvp;
 | 
					 | 
				
			||||||
	const char	*ptr, *first, *home;
 | 
					 | 
				
			||||||
	struct termios	 tio2;
 | 
					 | 
				
			||||||
	sigset_t	 set, oldset;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (wp->fd != -1) {
 | 
					 | 
				
			||||||
		bufferevent_free(wp->event);
 | 
					 | 
				
			||||||
		close(wp->fd);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (argc > 0) {
 | 
					 | 
				
			||||||
		cmd_free_argv(wp->argc, wp->argv);
 | 
					 | 
				
			||||||
		wp->argc = argc;
 | 
					 | 
				
			||||||
		wp->argv = cmd_copy_argv(argc, argv);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (shell != NULL) {
 | 
					 | 
				
			||||||
		free(wp->shell);
 | 
					 | 
				
			||||||
		wp->shell = xstrdup(shell);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (cwd != NULL) {
 | 
					 | 
				
			||||||
		free((void *)wp->cwd);
 | 
					 | 
				
			||||||
		wp->cwd = xstrdup(cwd);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wp->flags &= ~(PANE_STATUSREADY|PANE_STATUSDRAWN);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd = cmd_stringify_argv(wp->argc, wp->argv);
 | 
					 | 
				
			||||||
	log_debug("%s: shell=%s", __func__, wp->shell);
 | 
					 | 
				
			||||||
	log_debug("%s: cmd=%s", __func__, cmd);
 | 
					 | 
				
			||||||
	log_debug("%s: cwd=%s", __func__, cwd);
 | 
					 | 
				
			||||||
	cmd_log_argv(wp->argc, wp->argv, __func__);
 | 
					 | 
				
			||||||
	environ_log(env, "%s: environment ", __func__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memset(&ws, 0, sizeof ws);
 | 
					 | 
				
			||||||
	ws.ws_col = screen_size_x(&wp->base);
 | 
					 | 
				
			||||||
	ws.ws_row = screen_size_y(&wp->base);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sigfillset(&set);
 | 
					 | 
				
			||||||
	sigprocmask(SIG_BLOCK, &set, &oldset);
 | 
					 | 
				
			||||||
	switch (wp->pid = fdforkpty(ptm_fd, &wp->fd, wp->tty, NULL, &ws)) {
 | 
					 | 
				
			||||||
	case -1:
 | 
					 | 
				
			||||||
		wp->event = NULL;
 | 
					 | 
				
			||||||
		wp->fd = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		xasprintf(cause, "%s: %s", cmd, strerror(errno));
 | 
					 | 
				
			||||||
		free(cmd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
					 | 
				
			||||||
		return (-1);
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
		proc_clear_signals(server_proc, 1);
 | 
					 | 
				
			||||||
		sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		cwd = NULL;
 | 
					 | 
				
			||||||
		if (chdir(wp->cwd) == 0)
 | 
					 | 
				
			||||||
			cwd = wp->cwd;
 | 
					 | 
				
			||||||
		else if ((home = find_home()) != NULL && chdir(home) == 0)
 | 
					 | 
				
			||||||
			cwd = home;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			chdir("/");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (tcgetattr(STDIN_FILENO, &tio2) != 0)
 | 
					 | 
				
			||||||
			fatal("tcgetattr failed");
 | 
					 | 
				
			||||||
		if (tio != NULL)
 | 
					 | 
				
			||||||
			memcpy(tio2.c_cc, tio->c_cc, sizeof tio2.c_cc);
 | 
					 | 
				
			||||||
		tio2.c_cc[VERASE] = '\177';
 | 
					 | 
				
			||||||
		if (tcsetattr(STDIN_FILENO, TCSANOW, &tio2) != 0)
 | 
					 | 
				
			||||||
			fatal("tcgetattr failed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		log_close();
 | 
					 | 
				
			||||||
		closefrom(STDERR_FILENO + 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (path != NULL)
 | 
					 | 
				
			||||||
			environ_set(env, "PATH", "%s", path);
 | 
					 | 
				
			||||||
		if (cwd != NULL)
 | 
					 | 
				
			||||||
			environ_set(env, "PWD", "%s", cwd);
 | 
					 | 
				
			||||||
		environ_set(env, "TMUX_PANE", "%%%u", wp->id);
 | 
					 | 
				
			||||||
		environ_push(env);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		setenv("SHELL", wp->shell, 1);
 | 
					 | 
				
			||||||
		ptr = strrchr(wp->shell, '/');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * If given one argument, assume it should be passed to sh -c;
 | 
					 | 
				
			||||||
		 * with more than one argument, use execvp(). If there is no
 | 
					 | 
				
			||||||
		 * arguments, create a login shell.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		if (wp->argc > 0) {
 | 
					 | 
				
			||||||
			if (wp->argc != 1) {
 | 
					 | 
				
			||||||
				/* Copy to ensure argv ends in NULL. */
 | 
					 | 
				
			||||||
				argvp = cmd_copy_argv(wp->argc, wp->argv);
 | 
					 | 
				
			||||||
				execvp(argvp[0], argvp);
 | 
					 | 
				
			||||||
				fatal("execvp failed");
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			first = wp->argv[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (ptr != NULL && *(ptr + 1) != '\0')
 | 
					 | 
				
			||||||
				xasprintf(&argv0, "%s", ptr + 1);
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				xasprintf(&argv0, "%s", wp->shell);
 | 
					 | 
				
			||||||
			execl(wp->shell, argv0, "-c", first, (char *)NULL);
 | 
					 | 
				
			||||||
			fatal("execl failed");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (ptr != NULL && *(ptr + 1) != '\0')
 | 
					 | 
				
			||||||
			xasprintf(&argv0, "-%s", ptr + 1);
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			xasprintf(&argv0, "-%s", wp->shell);
 | 
					 | 
				
			||||||
		execl(wp->shell, argv0, (char *)NULL);
 | 
					 | 
				
			||||||
		fatal("execl failed");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	log_debug("%s: master=%s", __func__, ttyname(wp->fd));
 | 
					 | 
				
			||||||
	log_debug("%s: slave=%s", __func__, wp->tty);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sigprocmask(SIG_SETMASK, &oldset, NULL);
 | 
					 | 
				
			||||||
	setblocking(wp->fd, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
 | 
					 | 
				
			||||||
	    window_pane_error_callback, wp);
 | 
					 | 
				
			||||||
	if (wp->event == NULL)
 | 
					 | 
				
			||||||
		fatalx("out of memory");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wp->pipe_off = 0;
 | 
					 | 
				
			||||||
	wp->flags &= ~PANE_EXITED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
 | 
					 | 
				
			||||||
	bufferevent_enable(wp->event, EV_READ|EV_WRITE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free(cmd);
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
 | 
					window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -1056,6 +885,18 @@ window_pane_error_callback(__unused struct bufferevent *bufev,
 | 
				
			|||||||
		server_destroy_pane(wp, 1);
 | 
							server_destroy_pane(wp, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					window_pane_set_event(struct window_pane *wp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						setblocking(wp->fd, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wp->event = bufferevent_new(wp->fd, window_pane_read_callback,
 | 
				
			||||||
 | 
						    NULL, window_pane_error_callback, wp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
 | 
				
			||||||
 | 
						bufferevent_enable(wp->event, EV_READ|EV_WRITE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
 | 
					window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -1604,6 +1445,8 @@ winlink_shuffle_up(struct session *s, struct winlink *wl)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	int	 idx, last;
 | 
						int	 idx, last;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wl == NULL)
 | 
				
			||||||
 | 
							return (-1);
 | 
				
			||||||
	idx = wl->idx + 1;
 | 
						idx = wl->idx + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Find the next free index. */
 | 
						/* Find the next free index. */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user