4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
30 * Attach existing session to the current terminal.
33 enum cmd_retval
cmd_attach_session_exec(struct cmd
*, struct cmd_q
*);
35 const struct cmd_entry cmd_attach_session_entry
= {
36 "attach-session", "attach",
38 "[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE
,
39 CMD_CANTNEST
|CMD_STARTSERVER
,
41 cmd_attach_session_exec
45 cmd_attach_session(struct cmd_q
*cmdq
, const char *tflag
, int dflag
, int rflag
,
50 struct winlink
*wl
= NULL
;
51 struct window
*w
= NULL
;
52 struct window_pane
*wp
= NULL
;
57 struct format_tree
*ft
;
60 if (RB_EMPTY(&sessions
)) {
61 cmdq_error(cmdq
, "no sessions");
62 return (CMD_RETURN_ERROR
);
66 if ((s
= cmd_find_session(cmdq
, tflag
, 1)) == NULL
)
67 return (CMD_RETURN_ERROR
);
68 } else if (tflag
[strcspn(tflag
, ":.")] != '\0') {
69 if ((wl
= cmd_find_pane(cmdq
, tflag
, &s
, &wp
)) == NULL
)
70 return (CMD_RETURN_ERROR
);
72 if ((s
= cmd_find_session(cmdq
, tflag
, 1)) == NULL
)
73 return (CMD_RETURN_ERROR
);
74 w
= cmd_lookup_windowid(tflag
);
75 if (w
== NULL
&& (wp
= cmd_lookup_paneid(tflag
)) != NULL
)
78 wl
= winlink_find_by_window(&s
->windows
, w
);
81 if (cmdq
->client
== NULL
)
82 return (CMD_RETURN_NORMAL
);
86 window_set_active_pane(wp
->window
, wp
);
87 session_set_current(s
, wl
);
90 if (cmdq
->client
->session
!= NULL
) {
93 * Can't use server_write_session in case attaching to
94 * the same session as currently attached to.
96 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
97 c
= ARRAY_ITEM(&clients
, i
);
98 if (c
== NULL
|| c
->session
!= s
)
100 if (c
== cmdq
->client
)
102 server_write_client(c
, MSG_DETACH
,
104 strlen(c
->session
->name
) + 1);
109 ft
= format_create();
110 if ((c
= cmd_find_client(cmdq
, NULL
, 1)) != NULL
)
111 format_client(ft
, c
);
112 format_session(ft
, s
);
113 format_winlink(ft
, s
, s
->curw
);
114 format_window_pane(ft
, s
->curw
->window
->active
);
115 cp
= format_expand(ft
, cflag
);
118 fd
= open(cp
, O_RDONLY
|O_DIRECTORY
);
121 cmdq_error(cmdq
, "bad working directory: %s",
123 return (CMD_RETURN_ERROR
);
129 cmdq
->client
->session
= s
;
130 notify_attached_session_changed(cmdq
->client
);
131 session_update_activity(s
);
132 server_redraw_client(cmdq
->client
);
133 s
->curw
->flags
&= ~WINLINK_ALERTFLAGS
;
135 if (server_client_open(cmdq
->client
, s
, &cause
) != 0) {
136 cmdq_error(cmdq
, "open terminal failed: %s", cause
);
138 return (CMD_RETURN_ERROR
);
142 ft
= format_create();
143 if ((c
= cmd_find_client(cmdq
, NULL
, 1)) != NULL
)
144 format_client(ft
, c
);
145 format_session(ft
, s
);
146 format_winlink(ft
, s
, s
->curw
);
147 format_window_pane(ft
, s
->curw
->window
->active
);
148 cp
= format_expand(ft
, cflag
);
151 fd
= open(cp
, O_RDONLY
|O_DIRECTORY
);
154 cmdq_error(cmdq
, "bad working directory: %s",
156 return (CMD_RETURN_ERROR
);
163 cmdq
->client
->flags
|= CLIENT_READONLY
;
166 server_write_session(s
, MSG_DETACH
, s
->name
,
167 strlen(s
->name
) + 1);
170 update
= options_get_string(&s
->options
, "update-environment");
171 environ_update(update
, &cmdq
->client
->environ
, &s
->environ
);
173 cmdq
->client
->session
= s
;
174 notify_attached_session_changed(cmdq
->client
);
175 session_update_activity(s
);
176 server_redraw_client(cmdq
->client
);
177 s
->curw
->flags
&= ~WINLINK_ALERTFLAGS
;
179 server_write_ready(cmdq
->client
);
180 cmdq
->client_exit
= 0;
183 server_update_socket();
185 return (CMD_RETURN_NORMAL
);
189 cmd_attach_session_exec(struct cmd
*self
, struct cmd_q
*cmdq
)
191 struct args
*args
= self
->args
;
193 return (cmd_attach_session(cmdq
, args_get(args
, 't'),
194 args_has(args
, 'd'), args_has(args
, 'r'), args_get(args
, 'c')));