Esempio n. 1
0
int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data	*data = self->data;
	struct winlink		*wl;
	struct window_pane	*wp;

	if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
		return (-1);

	if (!window_pane_visible(wp)) {
		ctx->error(ctx, "pane not visible: %s", data->target);
		return (-1);
	}

	if (cmd_check_flag(data->chflags, 'L'))
		wp = window_pane_find_left(wp);
	else if (cmd_check_flag(data->chflags, 'R'))
		wp = window_pane_find_right(wp);
	else if (cmd_check_flag(data->chflags, 'U'))
		wp = window_pane_find_up(wp);
	else if (cmd_check_flag(data->chflags, 'D'))
		wp = window_pane_find_down(wp);
	if (wp == NULL) {
		ctx->error(ctx, "pane not found");
		return (-1);
	}

	window_set_active_pane(wl->window, wp);
	server_status_window(wl->window);
	server_redraw_window_borders(wl->window);

	return (0);
}
Esempio n. 2
0
int
cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_srcdst_data	*data = self->data;
	struct session		*src, *dst;
	struct winlink		*wl;
	char			*cause;
	int			 idx, kflag, dflag;

	if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL)
		return (-1);
	if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2)
		return (-1);

	kflag = cmd_check_flag(data->chflags, 'k');
	dflag = cmd_check_flag(data->chflags, 'd');
	if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
		ctx->error(ctx, "can't move window: %s", cause);
		xfree(cause);
		return (-1);
	}
	server_unlink_window(src, wl);
	recalculate_sizes();

	return (0);
}
Esempio n. 3
0
// cmd_select_pane_exec
int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct	window			*w;
	struct	winlink			*wl;
	struct	window_pane		*wp;
	struct	window_pane		*tar_wp;
	struct	cmd_target_data	*data = self->data;
	int		dir;
	bool	(*filt)(struct window_pane *our, struct window_pane *their);
	int		(*sort)(const void *a, const void *b);

	if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
		return (-1);
	w = wl->window;

	if (!window_pane_visible(wp)) {
		ctx->error(ctx, "pane not visible: %s", data->target);
		return (-1);
	}

	if (!data->chflags) {
		window_set_active_pane(wl->window, wp);
		return (0);
	}

	// directions
	if (cmd_check_flag(data->chflags, 'L')) {
		filt	= wp_next_l_filt;
		sort	= wp_next_l_sort;
		dir		= WP_L;
	}
	if (cmd_check_flag(data->chflags, 'R')) {
		filt	= wp_next_r_filt;
		sort	= wp_next_r_sort;
		dir=	WP_R;
	}
	if (cmd_check_flag(data->chflags, 'U')) {
		filt	= wp_next_u_filt;
		sort	= wp_next_u_sort;
		dir		= WP_U;
	}
	if (cmd_check_flag(data->chflags, 'D')) {
		filt	= wp_next_d_filt;
		sort	= wp_next_d_sort;
		dir		= WP_D;
	}

	if (filt && sort)
		if ((tar_wp = wp_next(wp, dir, filt, sort)) != NULL) {
			window_set_active_pane(wl->window, tar_wp);
			server_status_window(wl->window);
		}

	return (0);
}
Esempio n. 4
0
int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data	*data = self->data;
	struct winlink		*wl;
	struct window_pane	*loopwp, *nextwp, *wp;

	if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
		return (-1);

	if (window_count_panes(wl->window) == 1) {
		/* Only one pane, kill the window. */
		server_kill_window(wl->window);
		recalculate_sizes();
		return (0);
	}

	if (cmd_check_flag(data->chflags, 'a')) {
		loopwp = TAILQ_FIRST(&wl->window->panes);
		while (loopwp != NULL) {
			nextwp = TAILQ_NEXT(loopwp, entry);
			if (loopwp != wp) {
				layout_close_pane(loopwp);
				window_remove_pane(wl->window, loopwp);
			}
			loopwp = nextwp;
		}
	} else {
		layout_close_pane(wp);
		window_remove_pane(wl->window, wp);
	}
	server_redraw_window(wl->window);

	return (0);
}
Esempio n. 5
0
/* Print the flags present in chflags. */
size_t
cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
{
	u_char	ch;
	size_t	boff = off;

	if (chflags == 0)
		return (0);
	off += xsnprintf(buf + off, len - off, " -");

	for (ch = 0; ch < 26; ch++) {
		if (cmd_check_flag(chflags, 'a' + ch))
			off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
		if (cmd_check_flag(chflags, 'A' + ch))
			off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
	}
	return (off - boff);
}
Esempio n. 6
0
int
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_buffer_data	*data = self->data;
	struct winlink		*wl;
	struct window_pane	*wp;
	struct session		*s;
	struct paste_buffer	*pb;

	if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
		return (-1);
	wp = wl->window->active;

	if (data->buffer == -1)
		pb = paste_get_top(&s->buffers);
	else {
		if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
			ctx->error(ctx, "no buffer %d", data->buffer);
			return (-1);
		}
	}

	if (pb != NULL) {
		/* -r means raw data without LF->CR conversion. */
		if (cmd_check_flag(data->chflags, 'r'))
			bufferevent_write(wp->event, pb->data, pb->size);
		else
			cmd_paste_buffer_lf2cr(wp, pb->data, pb->size);
	}

	/* Delete the buffer if -d. */
	if (cmd_check_flag(data->chflags, 'd')) {
		if (data->buffer == -1)
			paste_free_top(&s->buffers);
		else
			paste_free_index(&s->buffers, data->buffer);
	}

	return (0);
}
Esempio n. 7
0
int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data	*data = self->data;
	struct window_pane	*wp;

	if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL)
		return (-1);

	window_pane_set_mode(wp, &window_copy_mode);
	if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u'))
		window_copy_pageup(wp);

	return (0);
}
Esempio n. 8
0
int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_buffer_data	*data = self->data;
	struct session		*s;
	struct paste_buffer	*pb;
	mode_t			mask;
	FILE			*f;

	if ((s = cmd_find_session(ctx, data->target)) == NULL)
		return (-1);

	if (data->buffer == -1) {
		if ((pb = paste_get_top(&s->buffers)) == NULL) {
			ctx->error(ctx, "no buffers");
			return (-1);
		}
	} else {
		if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
			ctx->error(ctx, "no buffer %d", data->buffer);
			return (-1);
		}
	}

	mask = umask(S_IRWXG | S_IRWXO);
	if (cmd_check_flag(data->chflags, 'a'))
		f = fopen(data->arg, "ab");
	else
		f = fopen(data->arg, "wb");
	umask(mask);
	if (f == NULL) {
		ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
		return (-1);
	}

	if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
	    	ctx->error(ctx, "%s: fwrite error", data->arg);
	    	fclose(f);
	    	return (-1);
	}

	fclose(f);

	return (0);
}
Esempio n. 9
0
int
cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_srcdst_data	*data = self->data;
	struct session		*src, *dst;
	struct session_group	*sg_src, *sg_dst;
	struct winlink		*wl_src, *wl_dst;
	struct window		*w;

	if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL)
		return (-1);
	if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL)
		return (-1);

	sg_src = session_group_find(src);
	sg_dst = session_group_find(dst);
	if (src != dst &&
	    sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) {
		ctx->error(ctx, "can't move window, sessions are grouped");
		return (-1);
	}

	if (wl_dst->window == wl_src->window)
		return (0);

	w = wl_dst->window;
	wl_dst->window = wl_src->window;
	wl_src->window = w;

	if (!cmd_check_flag(data->chflags, 'd')) {
		session_select(dst, wl_dst->idx);
		if (src != dst)
			session_select(src, wl_src->idx);
	}
	session_group_synchronize_from(src);
	server_redraw_session_group(src);
	if (src != dst) {
		session_group_synchronize_from(dst);
		server_redraw_session_group(dst);
	}
	recalculate_sizes();

	return (0);
}
Esempio n. 10
0
/* Unset an option. */
int
cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx,
    const struct options_table_entry *oe, struct options *oo)
{
	struct cmd_target_data	*data = self->data;

	if (cmd_check_flag(data->chflags, 'g')) {
		ctx->error(ctx, "can't unset global option: %s", oe->name);
		return (-1);
	}
	if (data->arg2 != NULL) {
		ctx->error(ctx, "value passed to unset option: %s", oe->name);
		return (-1);
	}

	options_remove(oo, oe->name);
	ctx->info(ctx, "unset option: %s", oe->name);
	return (0);
}
Esempio n. 11
0
/* Set a string option. */
struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
    const struct options_table_entry *oe, struct options *oo)
{
	struct cmd_target_data	*data = self->data;
	struct options_entry	*o;
	char			*oldval, *newval;

	if (cmd_check_flag(data->chflags, 'a')) {
		oldval = options_get_string(oo, oe->name);
		xasprintf(&newval, "%s%s", oldval, data->arg2);
	} else
		newval = data->arg2;

	o = options_set_string(oo, oe->name, "%s", newval);

	if (newval != data->arg2)
		xfree(newval);
	return (o);
}
int
cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data	*data = self->data;
	struct session		*s;
	int			 activity;

	if ((s = cmd_find_session(ctx, data->target)) == NULL)
		return (-1);

	activity = 0;
	if (cmd_check_flag(data->chflags, 'a'))
		activity = 1;

	if (session_previous(s, activity) == 0)
		server_redraw_session(s);
	else {
		ctx->error(ctx, "no previous window");
		return (-1);
	}
	recalculate_sizes();

	return (0);
}
Esempio n. 13
0
int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data		*data = self->data;
	const struct set_option_entry	*table;
	struct session			*s;
	struct winlink			*wl;
	struct client			*c;
	struct options			*oo;
	const struct set_option_entry   *entry, *opt;
	struct jobs			*jobs;
	struct job			*job, *nextjob;
	u_int				 i;
	int				 try_again;

	if (cmd_check_flag(data->chflags, 's')) {
		oo = &global_options;
		table = set_option_table;
	} else if (cmd_check_flag(data->chflags, 'w')) {
		table = set_window_option_table;
		if (cmd_check_flag(data->chflags, 'g'))
			oo = &global_w_options;
		else {
			wl = cmd_find_window(ctx, data->target, NULL);
			if (wl == NULL)
				return (-1);
			oo = &wl->window->options;
		}
	} else {
		table = set_session_option_table;
		if (cmd_check_flag(data->chflags, 'g'))
			oo = &global_s_options;
		else {
			s = cmd_find_session(ctx, data->target);
			if (s == NULL)
				return (-1);
			oo = &s->options;
		}
	}

	if (*data->arg == '\0') {
		ctx->error(ctx, "invalid option");
		return (-1);
	}

	entry = NULL;
	for (opt = table; opt->name != NULL; opt++) {
		if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
			continue;
		if (entry != NULL) {
			ctx->error(ctx, "ambiguous option: %s", data->arg);
			return (-1);
		}
		entry = opt;

		/* Bail now if an exact match. */
		if (strcmp(entry->name, data->arg) == 0)
			break;
	}
	if (entry == NULL) {
		ctx->error(ctx, "unknown option: %s", data->arg);
		return (-1);
	}

	if (cmd_check_flag(data->chflags, 'u')) {
		if (cmd_check_flag(data->chflags, 'g')) {
			ctx->error(ctx,
			    "can't unset global option: %s", entry->name);
			return (-1);
		}
		if (data->arg2 != NULL) {
			ctx->error(ctx,
			    "value passed to unset option: %s", entry->name);
			return (-1);
		}

		options_remove(oo, entry->name);
		ctx->info(ctx, "unset option: %s", entry->name);
	} else {
		switch (entry->type) {
		case SET_OPTION_STRING:
			cmd_set_option_string(ctx, oo, entry,
			    data->arg2, cmd_check_flag(data->chflags, 'a'));
			break;
		case SET_OPTION_NUMBER:
			cmd_set_option_number(ctx, oo, entry, data->arg2);
			break;
		case SET_OPTION_KEYS:
			cmd_set_option_keys(ctx, oo, entry, data->arg2);
			break;
		case SET_OPTION_COLOUR:
			cmd_set_option_colour(ctx, oo, entry, data->arg2);
			break;
		case SET_OPTION_ATTRIBUTES:
			cmd_set_option_attributes(ctx, oo, entry, data->arg2);
			break;
		case SET_OPTION_FLAG:
			cmd_set_option_flag(ctx, oo, entry, data->arg2);
			break;
		case SET_OPTION_CHOICE:
			cmd_set_option_choice(ctx, oo, entry, data->arg2);
			break;
		}
	}

	recalculate_sizes();
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
		c = ARRAY_ITEM(&clients, i);
		if (c != NULL && c->session != NULL)
			server_redraw_client(c);
	}

	/*
	 * Special-case: kill all persistent jobs if status-left, status-right
	 * or set-titles-string have changed. Persistent jobs are only used by
	 * the status line at the moment so this works XXX.
	 */
	if (strcmp(entry->name, "status-left") == 0 ||
	    strcmp(entry->name, "status-right") == 0 ||
	    strcmp(entry->name, "status") == 0 ||
	    strcmp(entry->name, "set-titles-string") == 0 ||
	    strcmp(entry->name, "window-status-format") == 0) {
		for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
			c = ARRAY_ITEM(&clients, i);
			if (c == NULL || c->session == NULL)
				continue;

			jobs = &c->status_jobs;
			do {
				try_again = 0;
				job = RB_ROOT(jobs);
				while (job != NULL) {
					nextjob = RB_NEXT(jobs, jobs, job);
					if (job->flags & JOB_PERSIST) {
						job_remove(jobs, job);
						try_again = 1;
						break;
					}
					job = nextjob;
				}
			} while (try_again);
			server_redraw_client(c);
		}
	}

	return (0);
}
Esempio n. 14
0
int
cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data	*data = self->data;
	struct session		*s;
	struct client		*c;
	const char		*update;
	char			*overrides, *cause;
	u_int			 i;

	if (ARRAY_LENGTH(&sessions) == 0) {
		ctx->error(ctx, "no sessions");
		return (-1);
	}
	if ((s = cmd_find_session(ctx, data->target)) == NULL)
		return (-1);

	if (ctx->cmdclient == NULL && ctx->curclient == NULL)
		return (0);

	if (ctx->cmdclient == NULL) {
		if (cmd_check_flag(data->chflags, 'd')) {
			/*
			 * Can't use server_write_session in case attaching to
			 * the same session as currently attached to.
			 */
			for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
				c = ARRAY_ITEM(&clients, i);
				if (c == NULL || c->session != s)
					continue;
				if (c == ctx->curclient)
					continue;
				server_write_client(c, MSG_DETACH, NULL, 0);
			}
		}

		ctx->curclient->session = s;
		server_redraw_client(ctx->curclient);
	} else {
		if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
			ctx->error(ctx, "not a terminal");
			return (-1);
		}

		overrides =
		    options_get_string(&s->options, "terminal-overrides");
		if (tty_open(&ctx->cmdclient->tty, overrides, &cause) != 0) {
			ctx->error(ctx, "terminal open failed: %s", cause);
			xfree(cause);
			return (-1);
		}

		if (cmd_check_flag(data->chflags, 'r'))
			ctx->cmdclient->flags |= CLIENT_READONLY;

		if (cmd_check_flag(data->chflags, 'd'))
			server_write_session(s, MSG_DETACH, NULL, 0);

		ctx->cmdclient->session = s;
		server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);

		update = options_get_string(&s->options, "update-environment");
		environ_update(update, &ctx->cmdclient->environ, &s->environ);

		server_redraw_client(ctx->cmdclient);
	}
	recalculate_sizes();
	server_update_socket();

	return (1);	/* 1 means don't tell command client to exit */
}
Esempio n. 15
0
int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data			*data = self->data;
	const struct options_table_entry	*table, *oe, *oe_loop;
	struct session				*s;
	struct winlink				*wl;
	struct client				*c;
	struct options				*oo;
	struct jobs				*jobs;
	struct job				*job, *nextjob;
	u_int					 i;
	int					 try_again;

	/* Work out the options tree and table to use. */
	if (cmd_check_flag(data->chflags, 's')) {
		oo = &global_options;
		table = server_options_table;
	} else if (cmd_check_flag(data->chflags, 'w')) {
		table = window_options_table;
		if (cmd_check_flag(data->chflags, 'g'))
			oo = &global_w_options;
		else {
			wl = cmd_find_window(ctx, data->target, NULL);
			if (wl == NULL)
				return (-1);
			oo = &wl->window->options;
		}
	} else {
		table = session_options_table;
		if (cmd_check_flag(data->chflags, 'g'))
			oo = &global_s_options;
		else {
			s = cmd_find_session(ctx, data->target);
			if (s == NULL)
				return (-1);
			oo = &s->options;
		}
	}

	/* Find the option table entry. */
	oe = NULL;
	for (oe_loop = table; oe_loop->name != NULL; oe_loop++) {
		if (strncmp(oe_loop->name, data->arg, strlen(data->arg)) != 0)
			continue;
		if (oe != NULL) {
			ctx->error(ctx, "ambiguous option: %s", data->arg);
			return (-1);
		}
		oe = oe_loop;

		/* Bail now if an exact match. */
		if (strcmp(oe->name, data->arg) == 0)
			break;
	}
	if (oe == NULL) {
		ctx->error(ctx, "unknown option: %s", data->arg);
		return (-1);
	}

	/* Unset or set the option. */
	if (cmd_check_flag(data->chflags, 'u')) {
		if (cmd_set_option_unset(self, ctx, oe, oo) != 0)
			return (-1);
	} else {
		if (cmd_set_option_set(self, ctx, oe, oo) != 0)
			return (-1);
	}

	/* Update sizes and redraw. May not need it but meh. */
	recalculate_sizes();
	for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
		c = ARRAY_ITEM(&clients, i);
		if (c != NULL && c->session != NULL)
			server_redraw_client(c);
	}

	/*
	 * Special-case: kill all persistent jobs if status-left, status-right
	 * or set-titles-string have changed. Persistent jobs are only used by
	 * the status line at the moment so this works XXX.
	 */
	if (strcmp(oe->name, "status-left") == 0 ||
	    strcmp(oe->name, "status-right") == 0 ||
	    strcmp(oe->name, "status") == 0 ||
	    strcmp(oe->name, "set-titles-string") == 0 ||
	    strcmp(oe->name, "window-status-format") == 0) {
		for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
			c = ARRAY_ITEM(&clients, i);
			if (c == NULL || c->session == NULL)
				continue;

			jobs = &c->status_jobs;
			do {
				try_again = 0;
				job = RB_ROOT(jobs);
				while (job != NULL) {
					nextjob = RB_NEXT(jobs, jobs, job);
					if (job->flags & JOB_PERSIST) {
						job_remove(jobs, job);
						try_again = 1;
						break;
					}
					job = nextjob;
				}
			} while (try_again);
			server_redraw_client(c);
		}
	}

	return (0);
}