Example #1
0
void fe_common_core_finish_init(void)
{
	WINDOW_REC *window;

	signal(SIGPIPE, SIG_IGN);

	if (settings_get_bool("use_status_window")) {
		window = window_create(NULL, TRUE);
		window_set_name(window, "(status)");
		window_set_level(window, MSGLEVEL_ALL ^
				 (settings_get_bool("use_msgs_window") ?
				  (MSGLEVEL_MSGS|MSGLEVEL_ACTIONS) : 0));
	}

	if (settings_get_bool("use_msgs_window")) {
		window = window_create(NULL, TRUE);
		window_set_name(window, "(msgs)");
		window_set_level(window, MSGLEVEL_MSGS|MSGLEVEL_ACTIONS);
	}

	if (windows == NULL) {
		/* we have to have at least one window.. */
                window = window_create(NULL, TRUE);
	}
}
Example #2
0
static void create_windows(void)
{
	WINDOW_REC *window;

	windows_layout_restore();
	if (windows != NULL)
		return;

	if (settings_get_bool("use_status_window")) {
		window = window_create(NULL, TRUE);
		window_set_name(window, "(status)");
		window_set_level(window, MSGLEVEL_ALL ^
				 (settings_get_bool("use_msgs_window") ?
				  (MSGLEVEL_MSGS|MSGLEVEL_DCCMSGS) : 0));
	}

	if (settings_get_bool("use_msgs_window")) {
		window = window_create(NULL, TRUE);
		window_set_name(window, "(msgs)");
		window_set_level(window, MSGLEVEL_MSGS|MSGLEVEL_DCCMSGS);
	}

	if (windows == NULL) {
		/* we have to have at least one window.. */
                window = window_create(NULL, TRUE);
	}
}
Example #3
0
void windows_layout_restore(void)
{
	WINDOW_REC *window;
	CONFIG_NODE *node;
	GSList *tmp;

	node = iconfig_node_traverse("windows", FALSE);
	if (node == NULL) return;

	for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
		CONFIG_NODE *node = tmp->data;

		window = window_create(NULL, TRUE);
		window_set_refnum(window, atoi(node->key));
                window->sticky_refnum = config_node_get_bool(node, "sticky_refnum", FALSE);
		window_set_name(window, config_node_get_str(node, "name", NULL));
		window_set_level(window, level2bits(config_node_get_str(node, "level", "")));

		window->servertag = g_strdup(config_node_get_str(node, "servertag", NULL));
		window->theme_name = g_strdup(config_node_get_str(node, "theme", NULL));
		if (window->theme_name != NULL)
			window->theme = theme_load(window->theme_name);

		window_add_items(window, config_node_section(node, "items", -1));
		signal_emit("window restore", 2, window, node);
	}

	signal_emit("windows restored", 0);
}
Example #4
0
static void sig_layout_restore(void)
{
	WINDOW_REC *window;
	CONFIG_NODE *node;
	GSList *tmp;

	node = iconfig_node_traverse("windows", FALSE);
	if (node == NULL) return;

	tmp = config_node_first(node->value);
	for (; tmp != NULL; tmp = config_node_next(tmp)) {
		CONFIG_NODE *node = tmp->data;

		window = window_find_refnum(atoi(node->key));
		if (window == NULL)
			window = window_create(NULL, TRUE);

		window_set_refnum(window, atoi(node->key));
                window->sticky_refnum = config_node_get_bool(node, "sticky_refnum", FALSE);
                window->immortal = config_node_get_bool(node, "immortal", FALSE);
		window_set_name(window, config_node_get_str(node, "name", NULL));
		window_set_history(window, config_node_get_str(node, "history_name", NULL));
		window_set_level(window, level2bits(config_node_get_str(node, "level", "")));

		window->servertag = g_strdup(config_node_get_str(node, "servertag", NULL));
		window->theme_name = g_strdup(config_node_get_str(node, "theme", NULL));
		if (window->theme_name != NULL)
			window->theme = theme_load(window->theme_name);

		window_add_items(window, config_node_section(node, "items", -1));
		signal_emit("layout restore window", 2, window, node);
	}
}
Example #5
0
int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
    struct args		*args = self->args;
    struct winlink		*wl;
    struct session		*s;
    struct window_pane	*wp;
    struct window		*w;
    char			*name;
    char			*cause;
    int			 base_idx;
    struct client		*c;

    if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
        return (-1);

    if (window_count_panes(wl->window) == 1) {
        ctx->error(ctx, "can't break with only one pane");
        return (-1);
    }

    w = wl->window;
    TAILQ_REMOVE(&w->panes, wp, entry);
    if (wp == w->active) {
        w->active = w->last;
        w->last = NULL;
        if (w->active == NULL) {
            w->active = TAILQ_PREV(wp, window_panes, entry);
            if (w->active == NULL)
                w->active = TAILQ_NEXT(wp, entry);
        }
    } else if (wp == w->last)
        w->last = NULL;
    layout_close_pane(wp);

    w = wp->window = window_create1(s->sx, s->sy);
    TAILQ_INSERT_HEAD(&w->panes, wp, entry);
    w->active = wp;
    name = default_window_name(w);
    window_set_name(w, name);
    xfree(name);
    layout_init(w);

    base_idx = options_get_number(&s->options, "base-index");
    wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
    if (!args_has(self->args, 'd'))
        session_select(s, wl->idx);

    server_redraw_session(s);
    server_status_session_group(s);

    /* Output the window ID for control clients. */
    c = cmd_find_client(ctx, NULL);
    if (c->flags & CLIENT_CONTROL) {
        ctx->print(ctx, "%d", w->id);
    }

    return (0);
}
Example #6
0
static void create_windows(void)
{
	WINDOW_REC *window;
	int have_status = settings_get_bool("use_status_window");

	window = window_find_name("(status)");
	if (have_status) {
		if (window == NULL) {
			window = window_create(NULL, TRUE);
			window_set_refnum(window, 1);
			window_set_name(window, "(status)");
			window_set_level(window, MSGLEVEL_ALL ^
					 (settings_get_bool("use_msgs_window") ?
					  MSGS_WINDOW_LEVELS : 0));
			window_set_immortal(window, TRUE);
		}
	} else {
		if (window != NULL) {
			window_set_name(window, NULL);
			window_set_level(window, 0);
			window_set_immortal(window, FALSE);
		}
	}

	window = window_find_name("(msgs)");
	if (settings_get_bool("use_msgs_window")) {
		if (window == NULL) {
			window = window_create(NULL, TRUE);
			window_set_refnum(window, have_status ? 2 : 1);
			window_set_name(window, "(msgs)");
			window_set_level(window, MSGS_WINDOW_LEVELS);
			window_set_immortal(window, TRUE);
		}
	} else {
		if (window != NULL) {
			window_set_name(window, NULL);
			window_set_level(window, 0);
			window_set_immortal(window, FALSE);
		}
	}

	if (windows == NULL) {
		/* we have to have at least one window.. */
                window = window_create(NULL, TRUE);
	}
}
Example #7
0
enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE_SLAVE
    return (CMD_RETURN_ERROR);
#else
    struct args		*args = self->args;
    struct winlink		*wl = cmdq->state.sflag.wl;
    struct session		*src_s = cmdq->state.sflag.s;
    struct session		*dst_s = cmdq->state.tflag.s;
    struct window_pane	*wp = cmdq->state.sflag.wp;
    struct window		*w = wl->window;
    char			*name;
    char			*cause;
    int			 idx = cmdq->state.tflag.idx;
    struct format_tree	*ft;
    const char		*template;
    char			*cp;

    if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
        cmdq_error(cmdq, "index %d already in use", idx);
        return (CMD_RETURN_ERROR);
    }

    if (window_count_panes(w) == 1) {
        cmdq_error(cmdq, "can't break with only one pane");
        return (CMD_RETURN_ERROR);
    }
    server_unzoom_window(w);

    TAILQ_REMOVE(&w->panes, wp, entry);
    window_lost_pane(w, wp);
    layout_close_pane(wp);

    w = wp->window = window_create1(dst_s->sx, dst_s->sy);
    TAILQ_INSERT_HEAD(&w->panes, wp, entry);
    w->active = wp;
    name = default_window_name(w);
    window_set_name(w, name);
    free(name);
    layout_init(w, wp);
    wp->flags |= PANE_CHANGED;

    if (idx == -1)
        idx = -1 - options_get_number(dst_s->options, "base-index");
    wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
    if (!args_has(self->args, 'd'))
        session_select(dst_s, wl->idx);

    server_redraw_session(src_s);
    if (src_s != dst_s)
        server_redraw_session(dst_s);
    server_status_session_group(src_s);
    if (src_s != dst_s)
        server_status_session_group(dst_s);

    if (args_has(args, 'P')) {
        if ((template = args_get(args, 'F')) == NULL)
Example #8
0
enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args		*args = self->args;
	struct winlink		*wl;
	struct session		*s;
	struct window_pane	*wp;
	struct window		*w;
	char			*name;
	char			*cause;
	int			 base_idx;
	struct client		*c;
	struct format_tree	*ft;
	const char		*template;
	char			*cp;

	if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
		return (CMD_RETURN_ERROR);

	if (window_count_panes(wl->window) == 1) {
		cmdq_error(cmdq, "can't break with only one pane");
		return (CMD_RETURN_ERROR);
	}

	w = wl->window;
	server_unzoom_window(w);

	TAILQ_REMOVE(&w->panes, wp, entry);
	if (wp == w->active) {
		w->active = w->last;
		w->last = NULL;
		if (w->active == NULL) {
			w->active = TAILQ_PREV(wp, window_panes, entry);
			if (w->active == NULL)
				w->active = TAILQ_NEXT(wp, entry);
		}
	} else if (wp == w->last)
		w->last = NULL;
	layout_close_pane(wp);

	w = wp->window = window_create1(s->sx, s->sy);
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
	w->active = wp;
	name = default_window_name(w);
	window_set_name(w, name);
	free(name);
	layout_init(w, wp);

	base_idx = options_get_number(&s->options, "base-index");
	wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
	if (!args_has(self->args, 'd'))
		session_select(s, wl->idx);

	server_redraw_session(s);
	server_status_session_group(s);

	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)
Example #9
0
    extern void wm_init_window(struct wm * wm,
                               struct window * w,
                               const char * name,
                               int x, int y, int width, int height,
                               unsigned options) {
        assert(wm);
        assert(w);
        assert(name);

        const bool is_double_buffered = false;//WINDOW_OPTION_DOUBLE_BUFFERED & options;
        XVisualInfo * vinfo = glXChooseVisual(wm->display, wm->default_screen, is_double_buffered ? VI_ATTR : VI_ATTR_SINGLE_BUFFERED);
        assert(vinfo);

        Window root = XRootWindow(wm->display, vinfo->screen);
        assert(root);

        if(WINDOW_OPTION_FULLSCREEN & options) {
            const Screen * s = XScreenOfDisplay(wm->display, wm->default_screen);
            x = 0;
            y = 0;
            width = s->width;
            height = s->height;
        }

        Colormap cmap = XCreateColormap(wm->display, root, vinfo->visual, AllocNone);
        XSetWindowAttributes attr;
        attr.background_pixel = 0;
        attr.border_pixel = 0;
        attr.colormap = cmap;
        attr.event_mask = EVENT_MASK;

        ::Window window = XCreateWindow(
                wm->display,
                root,
                x, y, static_cast<unsigned>(width), static_cast<unsigned>(height),
                0,  /* no border */
                vinfo->depth,
                InputOutput,
                vinfo->visual,
                VALUE_MASK,
                &attr
        );
        assert(window);

        w->display = wm->display;
        w->w = window;
        w->colormap = cmap;
        w->vinfo = vinfo;

        if(WINDOW_OPTION_FULLSCREEN & options) _set_fullscreen(w);
        if(name) window_set_name(w, name);
        if(!(WINDOW_OPTION_HIDDEN & options)) XMapWindow(wm->display, window);

        XFlush(wm->display);
    }
Example #10
0
void
check_window_name(struct window *w)
{
	struct timeval	 tv, next;
	char		*name;
	int		 left;

	if (w->active == NULL)
		return;

	if (!options_get_number(w->options, "automatic-rename"))
		return;

	if (~w->active->flags & PANE_CHANGED) {
		log_debug("@%u active pane not changed", w->id);
		return;
	}
	log_debug("@%u active pane changed", w->id);

	gettimeofday(&tv, NULL);
	left = name_time_expired(w, &tv);
	if (left != 0) {
		if (!event_initialized(&w->name_event))
			evtimer_set(&w->name_event, name_time_callback, w);
		if (!evtimer_pending(&w->name_event, NULL)) {
			log_debug("@%u name timer queued (%d left)", w->id,
			    left);
			timerclear(&next);
			next.tv_usec = left;
			event_add(&w->name_event, &next);
		} else {
			log_debug("@%u name timer already queued (%d left)",
			    w->id, left);
		}
		return;
	}
	memcpy(&w->name_time, &tv, sizeof w->name_time);
	if (event_initialized(&w->name_event))
		evtimer_del(&w->name_event);

	w->active->flags &= ~PANE_CHANGED;

	name = format_window_name(w);
	if (strcmp(name, w->name) != 0) {
		log_debug("@%u new name %s (was %s)", w->id, name, w->name);
		window_set_name(w, name);
		server_status_window(w);
	} else
		log_debug("@%u name not changed (still %s)", w->id, w->name);

	free(name);
}
Example #11
0
enum cmd_retval
cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args	*args = self->args;
	struct winlink	*wl = cmdq->state.tflag.wl;

	window_set_name(wl->window, args->argv[0]);
	options_set_number(wl->window->options, "automatic-rename", 0);

	server_status_window(wl->window);

	return (CMD_RETURN_NORMAL);
}
Example #12
0
/* SYNTAX: WINDOW NAME <name> */
static void cmd_window_name(const char *data)
{
	WINDOW_REC *win;

	win = window_find_name(data);
	if (win == NULL || win == active_win)
		window_set_name(active_win, data);
	else if (active_win->name == NULL ||
		 strcmp(active_win->name, data) != 0) {
		printformat_window(active_win, MSGLEVEL_CLIENTERROR,
				   TXT_WINDOW_NAME_NOT_UNIQUE, data);
	}
}
Example #13
0
File: input.c Project: akracun/tmux
/* Rename terminator (ST) received. */
void
input_exit_rename(struct input_ctx *ictx)
{
	if (ictx->flags & INPUT_DISCARD)
		return;
	if (!options_get_number(&ictx->wp->window->options, "allow-rename"))
		return;
	log_debug("%s: \"%s\"", __func__, ictx->input_buf);

	window_set_name(ictx->wp->window, ictx->input_buf);
	options_set_number(&ictx->wp->window->options, "automatic-rename", 0);

	server_status_window(ictx->wp->window);
}
Example #14
0
void
window_name_callback(unused int fd, unused short events, void *data)
{
	struct window	*w = data;
	char		*name, *wname;

	if (w->active == NULL)
		return;

	if (!options_get_number(&w->options, "automatic-rename")) {
		if (event_initialized(&w->name_timer))
			event_del(&w->name_timer);
		return;
	}
	queue_window_name(w);

	if (w->active->screen != &w->active->base)
		name = NULL;
	else
		name = osdep_get_name(w->active->fd, w->active->tty);
	if (name == NULL)
		wname = default_window_name(w);
	else {
		/*
		 * If tmux is using the default command, it will be a login
		 * shell and argv[0] may have a - prefix. Remove this if it is
		 * present. Ick.
		 */
		if (w->active->cmd != NULL && *w->active->cmd == '\0' &&
		    name != NULL && name[0] == '-' && name[1] != '\0')
			wname = parse_window_name(name + 1);
		else
			wname = parse_window_name(name);
		free(name);
	}

	if (w->active->fd == -1) {
		xasprintf(&name, "%s[dead]", wname);
		free(wname);
		wname = name;
	}

	if (strcmp(wname, w->name)) {
		window_set_name(w, wname);
		server_status_window(w);
	}
	free(wname);
}
Example #15
0
WINDOW_REC *
fe_xmpp_status_get_window(XMPP_SERVER_REC *server)
{
	WINDOW_REC *window;
	char *name;

	g_return_val_if_fail(IS_XMPP_SERVER(server), NULL);
	name = get_window_name(server);
	if ((window = window_find_name(name)) == NULL) {
		window = window_create(NULL, TRUE);
		window_set_name(window, name);
		window_change_server(window, server);
	}
	g_free(name);
	return window;
}
Example #16
0
enum cmd_retval
cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args	*args = self->args;
	struct session	*s;
	struct winlink	*wl;

	if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
		return (CMD_RETURN_ERROR);

	window_set_name(wl->window, args->argv[0]);
	options_set_number(&wl->window->options, "automatic-rename", 0);

	server_status_window(wl->window);

	return (CMD_RETURN_NORMAL);
}
Example #17
0
static enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
{
	struct args		*args = self->args;
	struct client		*c = item->client;
	struct session		*s, *as;
	struct session		*groupwith = item->state.tflag.s;
	struct window		*w;
	struct environ		*env;
	struct termios		 tio, *tiop;
	const char		*newname, *target, *update, *errstr, *template;
	const char		*path, *cwd, *to_free = NULL;
	char		       **argv, *cmd, *cause, *cp;
	int			 detached, already_attached, idx, argc;
	u_int			 sx, sy;
	struct format_tree	*ft;
	struct environ_entry	*envent;
	struct cmd_find_state	 fs;

	if (self->entry == &cmd_has_session_entry) {
		/*
		 * cmd_prepare() will fail if the session cannot be found,
		 * hence always return success here.
		 */
		return (CMD_RETURN_NORMAL);
	}

	if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
		cmdq_error(item, "command or window name given with target");
		return (CMD_RETURN_ERROR);
	}

	newname = args_get(args, 's');
	if (newname != NULL) {
		if (!session_check_name(newname)) {
			cmdq_error(item, "bad session name: %s", newname);
			return (CMD_RETURN_ERROR);
		}
		if ((as = session_find(newname)) != NULL) {
			if (args_has(args, 'A')) {
				/*
				 * This item is now destined for
				 * attach-session. Because attach-session will
				 * have already been prepared, copy this
				 * session into its tflag so it can be used.
				 */
				cmd_find_from_session(&item->state.tflag, as);
				return (cmd_attach_session(item,
				    args_has(args, 'D'), 0, NULL,
				    args_has(args, 'E')));
			}
			cmdq_error(item, "duplicate session: %s", newname);
			return (CMD_RETURN_ERROR);
		}
	}

	if ((target = args_get(args, 't')) != NULL) {
		if (groupwith == NULL) {
			cmdq_error(item, "no such session: %s", target);
			goto error;
		}
	} else
		groupwith = NULL;

	/* Set -d if no client. */
	detached = args_has(args, 'd');
	if (c == NULL)
		detached = 1;

	/* Is this client already attached? */
	already_attached = 0;
	if (c != NULL && c->session != NULL)
		already_attached = 1;

	/* Get the new session working directory. */
	if (args_has(args, 'c')) {
		ft = format_create(item, 0);
		format_defaults(ft, c, NULL, NULL, NULL);
		to_free = cwd = format_expand(ft, args_get(args, 'c'));
		format_free(ft);
	} else if (c != NULL && c->session == NULL && c->cwd != NULL)
		cwd = c->cwd;
	else
		cwd = ".";

	/*
	 * If this is a new client, check for nesting and save the termios
	 * settings (part of which is used for new windows in this session).
	 *
	 * tcgetattr() is used rather than using tty.tio since if the client is
	 * detached, tty_open won't be called. It must be done before opening
	 * the terminal as that calls tcsetattr() to prepare for tmux taking
	 * over.
	 */
	if (!detached && !already_attached && c->tty.fd != -1) {
		if (server_client_check_nested(item->client)) {
			cmdq_error(item, "sessions should be nested with care, "
			    "unset $TMUX to force");
			return (CMD_RETURN_ERROR);
		}
		if (tcgetattr(c->tty.fd, &tio) != 0)
			fatal("tcgetattr failed");
		tiop = &tio;
	} else
		tiop = NULL;

	/* Open the terminal if necessary. */
	if (!detached && !already_attached) {
		if (server_client_open(c, &cause) != 0) {
			cmdq_error(item, "open terminal failed: %s", cause);
			free(cause);
			goto error;
		}
	}

	/* Find new session size. */
	if (c != NULL) {
		sx = c->tty.sx;
		sy = c->tty.sy;
	} else {
		sx = 80;
		sy = 24;
	}
	if (detached && args_has(args, 'x')) {
		sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
		if (errstr != NULL) {
			cmdq_error(item, "width %s", errstr);
			goto error;
		}
	}
	if (detached && args_has(args, 'y')) {
		sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
		if (errstr != NULL) {
			cmdq_error(item, "height %s", errstr);
			goto error;
		}
	}
	if (sy > 0 && options_get_number(global_s_options, "status"))
		sy--;
	if (sx == 0)
		sx = 1;
	if (sy == 0)
		sy = 1;

	/* Figure out the command for the new window. */
	argc = -1;
	argv = NULL;
	if (!args_has(args, 't') && args->argc != 0) {
		argc = args->argc;
		argv = args->argv;
	} else if (groupwith == NULL) {
		cmd = options_get_string(global_s_options, "default-command");
		if (cmd != NULL && *cmd != '\0') {
			argc = 1;
			argv = &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')) {
		update = options_get_string(global_s_options,
		    "update-environment");
		environ_update(update, c->environ, env);
	}

	/* Create the new session. */
	idx = -1 - options_get_number(global_s_options, "base-index");
	s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx,
	    sy, &cause);
	environ_free(env);
	if (s == NULL) {
		cmdq_error(item, "create session failed: %s", cause);
		free(cause);
		goto error;
	}

	/* Set the initial window name if one given. */
	if (argc >= 0 && args_has(args, 'n')) {
		w = s->curw->window;
		window_set_name(w, args_get(args, 'n'));
		options_set_number(w->options, "automatic-rename", 0);
	}

	/*
	 * If a target session is given, this is to be part of a session group,
	 * so add it to the group and synchronize.
	 */
	if (groupwith != NULL) {
		session_group_add(groupwith, s);
		session_group_synchronize_to(s);
		session_select(s, RB_MIN(winlinks, &s->windows)->idx);
	}
	notify_session("session-created", s);

	/*
	 * Set the client to the new session. If a command client exists, it is
	 * taking this session and needs to get MSG_READY and stay around.
	 */
	if (!detached) {
		if (!already_attached) {
			if (~c->flags & CLIENT_CONTROL)
				proc_send(c->peer, MSG_READY, -1, NULL, 0);
		} else if (c->session != NULL)
			c->last_session = c->session;
		c->session = s;
		server_client_set_key_table(c, NULL);
		status_timer_start(c);
		notify_client("client-session-changed", c);
		session_update_activity(s, NULL);
		gettimeofday(&s->last_attached_time, NULL);
		server_redraw_client(c);
	}
	recalculate_sizes();
	server_update_socket();

	/*
	 * If there are still configuration file errors to display, put the new
	 * session's current window into more mode and display them now.
	 */
	if (cfg_finished)
		cfg_show_causes(s);

	/* Print if requested. */
	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)
Example #18
0
enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
	struct args		*args = self->args;
	struct client		*c = cmdq->client, *c0;
	struct session		*s, *groupwith;
	struct window		*w;
	struct environ		 env;
	struct termios		 tio, *tiop;
	const char		*newname, *target, *update, *errstr, *template;
	const char		*path;
	char		       **argv, *cmd, *cause, *cp;
	int			 detached, already_attached, idx, cwd, fd = -1;
	int			 argc;
	u_int			 sx, sy;
	struct format_tree	*ft;
	struct environ_entry	*envent;

	if (self->entry == &cmd_has_session_entry) {
		if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
			return (CMD_RETURN_ERROR);
		return (CMD_RETURN_NORMAL);
	}

	if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
		cmdq_error(cmdq, "command or window name given with target");
		return (CMD_RETURN_ERROR);
	}

	newname = args_get(args, 's');
	if (newname != NULL) {
		if (!session_check_name(newname)) {
			cmdq_error(cmdq, "bad session name: %s", newname);
			return (CMD_RETURN_ERROR);
		}
		if (session_find(newname) != NULL) {
			if (args_has(args, 'A')) {
				return (cmd_attach_session(cmdq, newname,
				    args_has(args, 'D'), 0, NULL,
				    args_has(args, 'E')));
			}
			cmdq_error(cmdq, "duplicate session: %s", newname);
			return (CMD_RETURN_ERROR);
		}
	}

	target = args_get(args, 't');
	if (target != NULL) {
		groupwith = cmd_find_session(cmdq, target, 0);
		if (groupwith == NULL)
			return (CMD_RETURN_ERROR);
	} else
		groupwith = NULL;

	/* Set -d if no client. */
	detached = args_has(args, 'd');
	if (c == NULL)
		detached = 1;

	/* Is this client already attached? */
	already_attached = 0;
	if (c != NULL && c->session != NULL)
		already_attached = 1;

	/* Get the new session working directory. */
	if (args_has(args, 'c')) {
		ft = format_create();
		format_defaults(ft, cmd_find_client(cmdq, NULL, 1), NULL, NULL,
		    NULL);
		cp = format_expand(ft, args_get(args, 'c'));
		format_free(ft);

		if (cp != NULL && *cp != '\0') {
			fd = open(cp, O_RDONLY|O_DIRECTORY);
			free(cp);
			if (fd == -1) {
				cmdq_error(cmdq, "bad working directory: %s",
				    strerror(errno));
				return (CMD_RETURN_ERROR);
			}
		} else if (cp != NULL)
			free(cp);
		cwd = fd;
	} else if (c != NULL && c->session == NULL)
		cwd = c->cwd;
	else if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
		cwd = c0->session->cwd;
	else {
		fd = open(".", O_RDONLY);
		cwd = fd;
	}

	/*
	 * If this is a new client, check for nesting and save the termios
	 * settings (part of which is used for new windows in this session).
	 *
	 * tcgetattr() is used rather than using tty.tio since if the client is
	 * detached, tty_open won't be called. It must be done before opening
	 * the terminal as that calls tcsetattr() to prepare for tmux taking
	 * over.
	 */
	if (!detached && !already_attached && c->tty.fd != -1) {
		if (server_client_check_nested(cmdq->client)) {
			cmdq_error(cmdq, "sessions should be nested with care, "
			    "unset $TMUX to force");
			return (CMD_RETURN_ERROR);
		}
		if (tcgetattr(c->tty.fd, &tio) != 0)
			fatal("tcgetattr failed");
		tiop = &tio;
	} else
		tiop = NULL;

	/* Open the terminal if necessary. */
	if (!detached && !already_attached) {
		if (server_client_open(c, &cause) != 0) {
			cmdq_error(cmdq, "open terminal failed: %s", cause);
			free(cause);
			goto error;
		}
	}

	/* Find new session size. */
	if (c != NULL) {
		sx = c->tty.sx;
		sy = c->tty.sy;
	} else {
		sx = 80;
		sy = 24;
	}
	if (detached && args_has(args, 'x')) {
		sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
		if (errstr != NULL) {
			cmdq_error(cmdq, "width %s", errstr);
			goto error;
		}
	}
	if (detached && args_has(args, 'y')) {
		sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
		if (errstr != NULL) {
			cmdq_error(cmdq, "height %s", errstr);
			goto error;
		}
	}
	if (sy > 0 && options_get_number(&global_s_options, "status"))
		sy--;
	if (sx == 0)
		sx = 1;
	if (sy == 0)
		sy = 1;

	/* Figure out the command for the new window. */
	argc = -1;
	argv = NULL;
	if (target == NULL && args->argc != 0) {
		argc = args->argc;
		argv = args->argv;
	} else if (target == NULL) {
		cmd = options_get_string(&global_s_options, "default-command");
		if (cmd != NULL && *cmd != '\0') {
			argc = 1;
			argv = &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. */
	environ_init(&env);
	if (c != NULL && !args_has(args, 'E')) {
		update = options_get_string(&global_s_options,
		    "update-environment");
		environ_update(update, &c->environ, &env);
	}

	/* Create the new session. */
	idx = -1 - options_get_number(&global_s_options, "base-index");
	s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
	    sy, &cause);
	if (s == NULL) {
		cmdq_error(cmdq, "create session failed: %s", cause);
		free(cause);
		goto error;
	}
	environ_free(&env);

	/* Set the initial window name if one given. */
	if (argc >= 0 && args_has(args, 'n')) {
		w = s->curw->window;
		window_set_name(w, args_get(args, 'n'));
		options_set_number(&w->options, "automatic-rename", 0);
	}

	/*
	 * If a target session is given, this is to be part of a session group,
	 * so add it to the group and synchronize.
	 */
	if (groupwith != NULL) {
		session_group_add(groupwith, s);
		session_group_synchronize_to(s);
		session_select(s, RB_MIN(winlinks, &s->windows)->idx);
	}

	/*
	 * Set the client to the new session. If a command client exists, it is
	 * taking this session and needs to get MSG_READY and stay around.
	 */
	if (!detached) {
		if (!already_attached)
			server_write_ready(c);
		else if (c->session != NULL)
			c->last_session = c->session;
		c->session = s;
		status_timer_start(c);
		notify_attached_session_changed(c);
		session_update_activity(s);
		server_redraw_client(c);
	}
	recalculate_sizes();
	server_update_socket();

	/*
	 * If there are still configuration file errors to display, put the new
	 * session's current window into more mode and display them now.
	 */
	if (cfg_finished)
		cfg_show_causes(s);

	/* Print if requested. */
	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)
Example #19
0
int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct args		*args = self->args;
	struct session		*s, *old_s, *groupwith;
	struct window		*w;
	struct window_pane	*wp;
	struct environ		 env;
	struct termios		 tio, *tiop;
	struct passwd		*pw;
	const char		*newname, *target, *update, *cwd, *errstr;
	char			*cmd, *cause;
	int			 detached, idx;
	u_int			 sx, sy, i;

	newname = args_get(args, 's');
	if (newname != NULL) {
		if (!session_check_name(newname)) {
			ctx->error(ctx, "bad session name: %s", newname);
			return (-1);
		}
		if (session_find(newname) != NULL) {
			ctx->error(ctx, "duplicate session: %s", newname);
			return (-1);
		}
	}

	target = args_get(args, 't');
	if (target != NULL) {
		groupwith = cmd_find_session(ctx, target, 0);
		if (groupwith == NULL)
			return (-1);
	} else
		groupwith = NULL;

	/*
	 * There are three cases:
	 *
	 * 1. If cmdclient is non-NULL, new-session has been called from the
	 *    command-line - cmdclient is to become a new attached, interactive
	 *    client. Unless -d is given, the terminal must be opened and then
	 *    the client sent MSG_READY.
	 *
	 * 2. If cmdclient is NULL, new-session has been called from an
	 *    existing client (such as a key binding).
	 *
	 * 3. Both are NULL, the command was in the configuration file. Treat
	 *    this as if -d was given even if it was not.
	 *
	 * In all cases, a new additional session needs to be created and
	 * (unless -d) set as the current session for the client.
	 */

	/* Set -d if no client. */
	detached = args_has(args, 'd');
	if (ctx->cmdclient == NULL && ctx->curclient == NULL)
		detached = 1;

	/*
	 * Save the termios settings, part of which is used for new windows in
	 * this session.
	 *
	 * This is read again with tcgetattr() rather than using tty.tio as if
	 * detached, tty_open won't be called. Because of this, it must be done
	 * before opening the terminal as that calls tcsetattr() to prepare for
	 * tmux taking over.
	 */
	if (ctx->cmdclient != NULL && ctx->cmdclient->tty.fd != -1) {
		if (tcgetattr(ctx->cmdclient->tty.fd, &tio) != 0)
			fatal("tcgetattr failed");
		tiop = &tio;
	} else
		tiop = NULL;

	/* Open the terminal if necessary. */
	if (!detached && ctx->cmdclient != NULL) {
		if (server_client_open(ctx->cmdclient, NULL, &cause) != 0) {
			ctx->error(ctx, "open terminal failed: %s", cause);
			xfree(cause);
			return (-1);
		}
	}

	/* Get the new session working directory. */
	if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
		cwd = ctx->cmdclient->cwd;
	else {
		pw = getpwuid(getuid());
		if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
			cwd = pw->pw_dir;
		else
			cwd = "/";
	}

	/* Find new session size. */
	if (ctx->cmdclient != NULL) {
		sx = ctx->cmdclient->tty.sx;
		sy = ctx->cmdclient->tty.sy;
	} else if (ctx->curclient != NULL) {
		sx = ctx->curclient->tty.sx;
		sy = ctx->curclient->tty.sy;
	} else {
		sx = 80;
		sy = 24;
	}
	if (detached) {
		if (args_has(args, 'x')) {
			sx = strtonum(
			    args_get(args, 'x'), 1, USHRT_MAX, &errstr);
			if (errstr != NULL) {
				ctx->error(ctx, "width %s", errstr);
				return (-1);
			}
		}
		if (args_has(args, 'y')) {
			sy = strtonum(
			    args_get(args, 'y'), 1, USHRT_MAX, &errstr);
			if (errstr != NULL) {
				ctx->error(ctx, "height %s", errstr);
				return (-1);
			}
		}
	}
	if (sy > 0 && options_get_number(&global_s_options, "status"))
		sy--;
	if (sx == 0)
		sx = 1;
	if (sy == 0)
		sy = 1;

	/* Figure out the command for the new window. */
	if (target != NULL)
		cmd = NULL;
	else if (args->argc != 0)
		cmd = args->argv[0];
	else
		cmd = options_get_string(&global_s_options, "default-command");

	/* Construct the environment. */
	environ_init(&env);
	update = options_get_string(&global_s_options, "update-environment");
	if (ctx->cmdclient != NULL)
		environ_update(update, &ctx->cmdclient->environ, &env);

	/* Create the new session. */
	idx = -1 - options_get_number(&global_s_options, "base-index");
	s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
	if (s == NULL) {
		ctx->error(ctx, "create session failed: %s", cause);
		xfree(cause);
		return (-1);
	}
	environ_free(&env);

	/* Set the initial window name if one given. */
	if (cmd != NULL && args_has(args, 'n')) {
		w = s->curw->window;

		window_set_name(w, args_get(args, 'n'));

		options_set_number(&w->options, "automatic-rename", 0);
	}

	/*
	 * If a target session is given, this is to be part of a session group,
	 * so add it to the group and synchronize.
	 */
	if (groupwith != NULL) {
		session_group_add(groupwith, s);
		session_group_synchronize_to(s);
		session_select(s, RB_ROOT(&s->windows)->idx);
	}

	/*
	 * Set the client to the new session. If a command client exists, it is
	 * taking this session and needs to get MSG_READY and stay around.
	 */
	if (!detached) {
		if (ctx->cmdclient != NULL) {
			server_write_ready(ctx->cmdclient);

			old_s = ctx->cmdclient->session;
			if (old_s != NULL)
				ctx->cmdclient->last_session = old_s;
			ctx->cmdclient->session = s;
			notify_attached_session_changed(ctx->cmdclient);
			session_update_activity(s);
			server_redraw_client(ctx->cmdclient);
		} else {
			old_s = ctx->curclient->session;
			if (old_s != NULL)
				ctx->curclient->last_session = old_s;
			ctx->curclient->session = s;
			notify_attached_session_changed(ctx->curclient);
			session_update_activity(s);
			server_redraw_client(ctx->curclient);
		}
	}
	recalculate_sizes();
	server_update_socket();

	/*
	 * If there are still configuration file errors to display, put the new
	 * session's current window into more mode and display them now.
	 */
	if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
		wp = s->curw->window->active;
		window_pane_set_mode(wp, &window_copy_mode);
		window_copy_init_for_output(wp);
		for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
			cause = ARRAY_ITEM(&cfg_causes, i);
			window_copy_add(wp, "%s", cause);
			xfree(cause);
		}
		ARRAY_FREE(&cfg_causes);
	}

	return (!detached);	/* 1 means don't tell command client to exit */
}
Example #20
0
static enum cmd_retval
cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
{
	struct args		*args = self->args;
	struct cmd_find_state	*current = &item->shared->current;
	struct client		*c = cmd_find_client(item, NULL, 1);
	struct winlink		*wl = item->source.wl;
	struct session		*src_s = item->source.s;
	struct session		*dst_s = item->target.s;
	struct window_pane	*wp = item->source.wp;
	struct window		*w = wl->window;
	char			*name, *cause;
	int			 idx = item->target.idx;
	const char		*template;
	char			*cp;

	if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
		cmdq_error(item, "index %d already in use", idx);
		return (CMD_RETURN_ERROR);
	}

	if (window_count_panes(w) == 1) {
		cmdq_error(item, "can't break with only one pane");
		return (CMD_RETURN_ERROR);
	}
	server_unzoom_window(w);

	TAILQ_REMOVE(&w->panes, wp, entry);
	window_lost_pane(w, wp);
	layout_close_pane(wp);

	w = wp->window = window_create(w->sx, w->sy);
	TAILQ_INSERT_HEAD(&w->panes, wp, entry);
	w->active = wp;

	if (!args_has(args, 'n')) {
		name = default_window_name(w);
		window_set_name(w, name);
		free(name);
	} else {
		window_set_name(w, args_get(args, 'n'));
		options_set_number(w->options, "automatic-rename", 0);
	}

	layout_init(w, wp);
	wp->flags |= PANE_CHANGED;

	if (idx == -1)
		idx = -1 - options_get_number(dst_s->options, "base-index");
	wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
	if (!args_has(self->args, 'd')) {
		session_select(dst_s, wl->idx);
		cmd_find_from_session(current, dst_s, 0);
	}

	server_redraw_session(src_s);
	if (src_s != dst_s)
		server_redraw_session(dst_s);
	server_status_session_group(src_s);
	if (src_s != dst_s)
		server_status_session_group(dst_s);

	if (args_has(args, 'P')) {
		if ((template = args_get(args, 'F')) == NULL)
Example #21
0
/* SYNTAX: WINDOW NAME <name> */
static void cmd_window_name(const char *data)
{
        window_set_name(active_win, data);
}