1 /* $Id: server-fn.c,v 1.102 2010-01-25 17:13:43 tcunha Exp $ */
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>
27 void server_callback_identify(int, short, void *);
30 server_fill_environ(struct session
*s
, struct environ
*env
)
32 char tmuxvar
[MAXPATHLEN
], *term
;
35 if (session_index(s
, &idx
) != 0)
36 fatalx("session not found");
37 xsnprintf(tmuxvar
, sizeof tmuxvar
,
38 "%s,%ld,%u", socket_path
, (long) getpid(), idx
);
39 environ_set(env
, "TMUX", tmuxvar
);
41 term
= options_get_string(&s
->options
, "default-terminal");
42 environ_set(env
, "TERM", term
);
46 server_write_error(struct client
*c
, const char *msg
)
48 struct msg_print_data printdata
;
50 strlcpy(printdata
.msg
, msg
, sizeof printdata
.msg
);
51 server_write_client(c
, MSG_ERROR
, &printdata
, sizeof printdata
);
56 struct client
*c
, enum msgtype type
, const void *buf
, size_t len
)
58 struct imsgbuf
*ibuf
= &c
->ibuf
;
60 if (c
->flags
& CLIENT_BAD
)
62 log_debug("writing %d to client %d", type
, c
->ibuf
.fd
);
63 imsg_compose(ibuf
, type
, PROTOCOL_VERSION
, -1, -1, (void *) buf
, len
);
64 server_update_event(c
);
69 struct session
*s
, enum msgtype type
, const void *buf
, size_t len
)
74 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
75 c
= ARRAY_ITEM(&clients
, i
);
76 if (c
== NULL
|| c
->session
== NULL
)
79 server_write_client(c
, type
, buf
, len
);
84 server_redraw_client(struct client
*c
)
86 c
->flags
|= CLIENT_REDRAW
;
90 server_status_client(struct client
*c
)
92 c
->flags
|= CLIENT_STATUS
;
96 server_redraw_session(struct session
*s
)
101 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
102 c
= ARRAY_ITEM(&clients
, i
);
103 if (c
== NULL
|| c
->session
== NULL
)
106 server_redraw_client(c
);
111 server_redraw_session_group(struct session
*s
)
113 struct session_group
*sg
;
115 if ((sg
= session_group_find(s
)) == NULL
)
116 server_redraw_session(s
);
118 TAILQ_FOREACH(s
, &sg
->sessions
, gentry
)
119 server_redraw_session(s
);
124 server_status_session(struct session
*s
)
129 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
130 c
= ARRAY_ITEM(&clients
, i
);
131 if (c
== NULL
|| c
->session
== NULL
)
134 server_status_client(c
);
139 server_status_session_group(struct session
*s
)
141 struct session_group
*sg
;
143 if ((sg
= session_group_find(s
)) == NULL
)
144 server_status_session(s
);
146 TAILQ_FOREACH(s
, &sg
->sessions
, gentry
)
147 server_status_session(s
);
152 server_redraw_window(struct window
*w
)
157 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
158 c
= ARRAY_ITEM(&clients
, i
);
159 if (c
== NULL
|| c
->session
== NULL
)
161 if (c
->session
->curw
->window
== w
)
162 server_redraw_client(c
);
164 w
->flags
|= WINDOW_REDRAW
;
168 server_redraw_window_borders(struct window
*w
)
173 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
174 c
= ARRAY_ITEM(&clients
, i
);
175 if (c
== NULL
|| c
->session
== NULL
)
177 if (c
->session
->curw
->window
== w
)
178 c
->flags
|= CLIENT_BORDERS
;
183 server_status_window(struct window
*w
)
189 * This is slightly different. We want to redraw the status line of any
190 * clients containing this window rather than any where it is the
194 for (i
= 0; i
< ARRAY_LENGTH(&sessions
); i
++) {
195 s
= ARRAY_ITEM(&sessions
, i
);
196 if (s
!= NULL
&& session_has(s
, w
))
197 server_status_session(s
);
207 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
208 c
= ARRAY_ITEM(&clients
, i
);
209 if (c
== NULL
|| c
->session
== NULL
)
211 server_lock_client(c
);
216 server_lock_session(struct session
*s
)
221 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
222 c
= ARRAY_ITEM(&clients
, i
);
223 if (c
== NULL
|| c
->session
== NULL
|| c
->session
!= s
)
225 server_lock_client(c
);
230 server_lock_client(struct client
*c
)
234 struct msg_lock_data lockdata
;
236 if (c
->flags
& CLIENT_SUSPENDED
)
239 cmd
= options_get_string(&c
->session
->options
, "lock-command");
240 cmdlen
= strlcpy(lockdata
.cmd
, cmd
, sizeof lockdata
.cmd
);
241 if (cmdlen
>= sizeof lockdata
.cmd
)
244 tty_stop_tty(&c
->tty
);
245 tty_raw(&c
->tty
, tty_term_string(c
->tty
.term
, TTYC_SMCUP
));
246 tty_raw(&c
->tty
, tty_term_string(c
->tty
.term
, TTYC_CLEAR
));
248 c
->flags
|= CLIENT_SUSPENDED
;
249 server_write_client(c
, MSG_LOCK
, &lockdata
, sizeof lockdata
);
253 server_kill_window(struct window
*w
)
259 for (i
= 0; i
< ARRAY_LENGTH(&sessions
); i
++) {
260 s
= ARRAY_ITEM(&sessions
, i
);
261 if (s
== NULL
|| !session_has(s
, w
))
263 while ((wl
= winlink_find_by_window(&s
->windows
, w
)) != NULL
) {
264 if (session_detach(s
, wl
)) {
265 server_destroy_session_group(s
);
268 server_redraw_session_group(s
);
274 server_link_window(struct session
*src
, struct winlink
*srcwl
,
275 struct session
*dst
, int dstidx
, int killflag
, int selectflag
, char **cause
)
277 struct winlink
*dstwl
;
278 struct session_group
*srcsg
, *dstsg
;
280 srcsg
= session_group_find(src
);
281 dstsg
= session_group_find(dst
);
282 if (src
!= dst
&& srcsg
!= NULL
&& dstsg
!= NULL
&& srcsg
== dstsg
) {
283 xasprintf(cause
, "sessions are grouped");
289 dstwl
= winlink_find_by_index(&dst
->windows
, dstidx
);
291 if (dstwl
->window
== srcwl
->window
)
295 * Can't use session_detach as it will destroy session
296 * if this makes it empty.
298 session_alert_cancel(dst
, dstwl
);
299 winlink_stack_remove(&dst
->lastw
, dstwl
);
300 winlink_remove(&dst
->windows
, dstwl
);
302 /* Force select/redraw if current. */
303 if (dstwl
== dst
->curw
) {
311 dstidx
= -1 - options_get_number(&dst
->options
, "base-index");
312 dstwl
= session_attach(dst
, srcwl
->window
, dstidx
, cause
);
317 session_select(dst
, dstwl
->idx
);
318 server_redraw_session_group(dst
);
324 server_unlink_window(struct session
*s
, struct winlink
*wl
)
326 if (session_detach(s
, wl
))
327 server_destroy_session_group(s
);
329 server_redraw_session_group(s
);
333 server_destroy_pane(struct window_pane
*wp
)
335 struct window
*w
= wp
->window
;
338 bufferevent_free(wp
->event
);
341 if (options_get_number(&w
->options
, "remain-on-exit"))
344 layout_close_pane(wp
);
345 window_remove_pane(w
, wp
);
347 if (TAILQ_EMPTY(&w
->panes
))
348 server_kill_window(w
);
350 server_redraw_window(w
);
354 server_destroy_session_group(struct session
*s
)
356 struct session_group
*sg
;
358 if ((sg
= session_group_find(s
)) == NULL
)
359 server_destroy_session(s
);
361 TAILQ_FOREACH(s
, &sg
->sessions
, gentry
)
362 server_destroy_session(s
);
363 TAILQ_REMOVE(&session_groups
, sg
, entry
);
369 server_destroy_session(struct session
*s
)
374 for (i
= 0; i
< ARRAY_LENGTH(&clients
); i
++) {
375 c
= ARRAY_ITEM(&clients
, i
);
376 if (c
== NULL
|| c
->session
!= s
)
379 server_write_client(c
, MSG_EXIT
, NULL
, 0);
384 server_set_identify(struct client
*c
)
389 delay
= options_get_number(&c
->session
->options
, "display-panes-time");
390 tv
.tv_sec
= delay
/ 1000;
391 tv
.tv_usec
= (delay
% 1000) * 1000L;
393 evtimer_del(&c
->identify_timer
);
394 evtimer_set(&c
->identify_timer
, server_callback_identify
, c
);
395 evtimer_add(&c
->identify_timer
, &tv
);
397 c
->flags
|= CLIENT_IDENTIFY
;
398 c
->tty
.flags
|= (TTY_FREEZE
|TTY_NOCURSOR
);
399 server_redraw_client(c
);
403 server_clear_identify(struct client
*c
)
405 if (c
->flags
& CLIENT_IDENTIFY
) {
406 c
->flags
&= ~CLIENT_IDENTIFY
;
407 c
->tty
.flags
&= ~(TTY_FREEZE
|TTY_NOCURSOR
);
408 server_redraw_client(c
);
414 server_callback_identify(unused
int fd
, unused
short events
, void *data
)
416 struct client
*c
= data
;
418 server_clear_identify(c
);
422 server_update_event(struct client
*c
)
427 if (!(c
->flags
& CLIENT_BAD
))
429 if (c
->ibuf
.w
.queued
> 0)
431 event_del(&c
->event
);
432 event_set(&c
->event
, c
->ibuf
.fd
, events
, server_client_callback
, c
);
433 event_add(&c
->event
, NULL
);