GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/cmd-attach-session.c Lines: 0 72 0.0 %
Date: 2016-12-06 Branches: 0 36 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: cmd-attach-session.c,v 1.61 2016/01/19 15:59:12 nicm Exp $ */
2
3
/*
4
 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
21
#include <errno.h>
22
#include <fcntl.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <unistd.h>
26
27
#include "tmux.h"
28
29
/*
30
 * Attach existing session to the current terminal.
31
 */
32
33
enum cmd_retval	cmd_attach_session_exec(struct cmd *, struct cmd_q *);
34
35
const struct cmd_entry cmd_attach_session_entry = {
36
	.name = "attach-session",
37
	.alias = "attach",
38
39
	.args = { "c:dErt:", 0, 0 },
40
	.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
41
42
	.tflag = CMD_SESSION_WITHPANE,
43
44
	.flags = CMD_STARTSERVER,
45
	.exec = cmd_attach_session_exec
46
};
47
48
enum cmd_retval
49
cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
50
    int Eflag)
51
{
52
	struct session		*s = cmdq->state.tflag.s;
53
	struct client		*c = cmdq->client, *c_loop;
54
	struct winlink		*wl = cmdq->state.tflag.wl;
55
	struct window_pane	*wp = cmdq->state.tflag.wp;
56
	const char		*update;
57
	char			*cause, *cwd;
58
	struct format_tree	*ft;
59
60
	if (RB_EMPTY(&sessions)) {
61
		cmdq_error(cmdq, "no sessions");
62
		return (CMD_RETURN_ERROR);
63
	}
64
65
	if (c == NULL)
66
		return (CMD_RETURN_NORMAL);
67
	if (server_client_check_nested(c)) {
68
		cmdq_error(cmdq, "sessions should be nested with care, "
69
		    "unset $TMUX to force");
70
		return (CMD_RETURN_ERROR);
71
	}
72
73
	if (wl != NULL) {
74
		if (wp != NULL)
75
			window_set_active_pane(wp->window, wp);
76
		session_set_current(s, wl);
77
	}
78
79
	if (cflag != NULL) {
80
		ft = format_create(cmdq, 0);
81
		format_defaults(ft, c, s, wl, wp);
82
		cwd = format_expand(ft, cflag);
83
		format_free(ft);
84
85
		free((void *)s->cwd);
86
		s->cwd = cwd;
87
	}
88
89
	if (c->session != NULL) {
90
		if (dflag) {
91
			TAILQ_FOREACH(c_loop, &clients, entry) {
92
				if (c_loop->session != s || c == c_loop)
93
					continue;
94
				server_client_detach(c_loop, MSG_DETACH);
95
			}
96
		}
97
98
		if (!Eflag) {
99
			update = options_get_string(s->options,
100
			    "update-environment");
101
			environ_update(update, c->environ, s->environ);
102
		}
103
104
		c->session = s;
105
		server_client_set_key_table(c, NULL);
106
		status_timer_start(c);
107
		notify_attached_session_changed(c);
108
		session_update_activity(s, NULL);
109
		gettimeofday(&s->last_attached_time, NULL);
110
		server_redraw_client(c);
111
		s->curw->flags &= ~WINLINK_ALERTFLAGS;
112
	} else {
113
		if (server_client_open(c, &cause) != 0) {
114
			cmdq_error(cmdq, "open terminal failed: %s", cause);
115
			free(cause);
116
			return (CMD_RETURN_ERROR);
117
		}
118
119
		if (rflag)
120
			c->flags |= CLIENT_READONLY;
121
122
		if (dflag) {
123
			TAILQ_FOREACH(c_loop, &clients, entry) {
124
				if (c_loop->session != s || c == c_loop)
125
					continue;
126
				server_client_detach(c_loop, MSG_DETACH);
127
			}
128
		}
129
130
		if (!Eflag) {
131
			update = options_get_string(s->options,
132
			    "update-environment");
133
			environ_update(update, c->environ, s->environ);
134
		}
135
136
		c->session = s;
137
		server_client_set_key_table(c, NULL);
138
		status_timer_start(c);
139
		notify_attached_session_changed(c);
140
		session_update_activity(s, NULL);
141
		gettimeofday(&s->last_attached_time, NULL);
142
		server_redraw_client(c);
143
		s->curw->flags &= ~WINLINK_ALERTFLAGS;
144
145
		if (~c->flags & CLIENT_CONTROL)
146
			proc_send(c->peer, MSG_READY, -1, NULL, 0);
147
		hooks_run(c->session->hooks, c, NULL, "client-attached");
148
		cmdq->client_exit = 0;
149
	}
150
	recalculate_sizes();
151
	alerts_check_session(s);
152
	server_update_socket();
153
154
	return (CMD_RETURN_NORMAL);
155
}
156
157
enum cmd_retval
158
cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
159
{
160
	struct args	*args = self->args;
161
162
	return (cmd_attach_session(cmdq, args_has(args, 'd'),
163
	    args_has(args, 'r'), args_get(args, 'c'), args_has(args, 'E')));
164
}