Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 498 lines (425 sloc) 10.809 kb
c2acb99 Romain Francoise Import upstream snapshot from SVN r2630
orebokech authored
1 /* $Id: server-fn.c 2621 2011-10-23 15:10:22Z tcunha $ */
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
2
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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 <string.h>
22 #include <time.h>
23 #include <unistd.h>
24
25 #include "tmux.h"
26
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
27 struct session *server_next_session(struct session *);
28 void server_callback_identify(int, short, void *);
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
29
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
30 void
31 server_fill_environ(struct session *s, struct environ *env)
32 {
7216c39 Karl Ferdinand Ebert Imported Upstream version 1.5
kfebert authored
33 char var[MAXPATHLEN], *term;
34 u_int idx;
35 long pid;
36
37 if (s != NULL) {
38 term = options_get_string(&s->options, "default-terminal");
39 environ_set(env, "TERM", term);
40
41 idx = s->idx;
42 } else
43 idx = -1;
44 pid = getpid();
45 xsnprintf(var, sizeof var, "%s,%ld,%d", socket_path, pid, idx);
46 environ_set(env, "TMUX", var);
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
47 }
48
49 void
50 server_write_client(
51 struct client *c, enum msgtype type, const void *buf, size_t len)
52 {
53 struct imsgbuf *ibuf = &c->ibuf;
54
55 if (c->flags & CLIENT_BAD)
56 return;
57 log_debug("writing %d to client %d", type, c->ibuf.fd);
58 imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, -1, (void *) buf, len);
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
59 server_update_event(c);
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
60 }
61
62 void
63 server_write_session(
64 struct session *s, enum msgtype type, const void *buf, size_t len)
65 {
66 struct client *c;
67 u_int i;
68
69 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
70 c = ARRAY_ITEM(&clients, i);
71 if (c == NULL || c->session == NULL)
72 continue;
73 if (c->session == s)
74 server_write_client(c, type, buf, len);
75 }
76 }
77
78 void
79 server_redraw_client(struct client *c)
80 {
81 c->flags |= CLIENT_REDRAW;
82 }
83
84 void
85 server_status_client(struct client *c)
86 {
87 c->flags |= CLIENT_STATUS;
88 }
89
90 void
91 server_redraw_session(struct session *s)
92 {
93 struct client *c;
94 u_int i;
95
96 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
97 c = ARRAY_ITEM(&clients, i);
98 if (c == NULL || c->session == NULL)
99 continue;
100 if (c->session == s)
101 server_redraw_client(c);
102 }
103 }
104
105 void
106 server_redraw_session_group(struct session *s)
107 {
108 struct session_group *sg;
109
110 if ((sg = session_group_find(s)) == NULL)
111 server_redraw_session(s);
112 else {
113 TAILQ_FOREACH(s, &sg->sessions, gentry)
114 server_redraw_session(s);
115 }
116 }
117
118 void
119 server_status_session(struct session *s)
120 {
121 struct client *c;
122 u_int i;
123
124 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
125 c = ARRAY_ITEM(&clients, i);
126 if (c == NULL || c->session == NULL)
127 continue;
128 if (c->session == s)
129 server_status_client(c);
130 }
131 }
132
133 void
134 server_status_session_group(struct session *s)
135 {
136 struct session_group *sg;
137
138 if ((sg = session_group_find(s)) == NULL)
139 server_status_session(s);
140 else {
141 TAILQ_FOREACH(s, &sg->sessions, gentry)
142 server_status_session(s);
143 }
144 }
145
146 void
147 server_redraw_window(struct window *w)
148 {
149 struct client *c;
150 u_int i;
151
152 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
153 c = ARRAY_ITEM(&clients, i);
154 if (c == NULL || c->session == NULL)
155 continue;
156 if (c->session->curw->window == w)
157 server_redraw_client(c);
158 }
159 w->flags |= WINDOW_REDRAW;
160 }
161
162 void
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
163 server_redraw_window_borders(struct window *w)
164 {
165 struct client *c;
166 u_int i;
167
168 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
169 c = ARRAY_ITEM(&clients, i);
170 if (c == NULL || c->session == NULL)
171 continue;
172 if (c->session->curw->window == w)
173 c->flags |= CLIENT_BORDERS;
174 }
175 }
176
177 void
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
178 server_status_window(struct window *w)
179 {
180 struct session *s;
181
182 /*
183 * This is slightly different. We want to redraw the status line of any
184 * clients containing this window rather than any where it is the
185 * current window.
186 */
187
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
188 RB_FOREACH(s, sessions, &sessions) {
189 if (session_has(s, w) != NULL)
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
190 server_status_session(s);
191 }
192 }
193
194 void
195 server_lock(void)
196 {
197 struct client *c;
198 u_int i;
199
200 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
201 c = ARRAY_ITEM(&clients, i);
202 if (c == NULL || c->session == NULL)
203 continue;
204 server_lock_client(c);
205 }
206 }
207
208 void
209 server_lock_session(struct session *s)
210 {
211 struct client *c;
212 u_int i;
213
214 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
215 c = ARRAY_ITEM(&clients, i);
216 if (c == NULL || c->session == NULL || c->session != s)
217 continue;
218 server_lock_client(c);
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
219 }
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
220 }
221
222 void
223 server_lock_client(struct client *c)
224 {
225 const char *cmd;
226 size_t cmdlen;
227 struct msg_lock_data lockdata;
228
229 if (c->flags & CLIENT_SUSPENDED)
230 return;
231
232 cmd = options_get_string(&c->session->options, "lock-command");
233 cmdlen = strlcpy(lockdata.cmd, cmd, sizeof lockdata.cmd);
234 if (cmdlen >= sizeof lockdata.cmd)
235 return;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
236
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
237 tty_stop_tty(&c->tty);
238 tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP));
239 tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR));
c2acb99 Romain Francoise Import upstream snapshot from SVN r2630
orebokech authored
240 tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
241
242 c->flags |= CLIENT_SUSPENDED;
243 server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
244 }
245
246 void
247 server_kill_window(struct window *w)
248 {
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
249 struct session *s, *next_s;
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
250 struct winlink *wl;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
251
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
252 next_s = RB_MIN(sessions, &sessions);
253 while (next_s != NULL) {
254 s = next_s;
255 next_s = RB_NEXT(sessions, &sessions, s);
256
257 if (session_has(s, w) == NULL)
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
258 continue;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
259 while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) {
260 if (session_detach(s, wl)) {
261 server_destroy_session_group(s);
262 break;
263 } else
264 server_redraw_session_group(s);
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
265 }
266 }
267 }
268
269 int
270 server_link_window(struct session *src, struct winlink *srcwl,
271 struct session *dst, int dstidx, int killflag, int selectflag, char **cause)
272 {
273 struct winlink *dstwl;
274 struct session_group *srcsg, *dstsg;
275
276 srcsg = session_group_find(src);
277 dstsg = session_group_find(dst);
278 if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) {
279 xasprintf(cause, "sessions are grouped");
280 return (-1);
281 }
282
283 dstwl = NULL;
284 if (dstidx != -1)
285 dstwl = winlink_find_by_index(&dst->windows, dstidx);
286 if (dstwl != NULL) {
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
287 if (dstwl->window == srcwl->window) {
288 xasprintf(cause, "same index: %d", dstidx);
289 return (-1);
290 }
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
291 if (killflag) {
292 /*
293 * Can't use session_detach as it will destroy session
294 * if this makes it empty.
295 */
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
296 dstwl->flags &= ~WINLINK_ALERTFLAGS;
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
297 winlink_stack_remove(&dst->lastw, dstwl);
298 winlink_remove(&dst->windows, dstwl);
299
300 /* Force select/redraw if current. */
301 if (dstwl == dst->curw) {
302 selectflag = 1;
303 dst->curw = NULL;
304 }
305 }
306 }
307
308 if (dstidx == -1)
309 dstidx = -1 - options_get_number(&dst->options, "base-index");
310 dstwl = session_attach(dst, srcwl->window, dstidx, cause);
311 if (dstwl == NULL)
312 return (-1);
313
314 if (selectflag)
315 session_select(dst, dstwl->idx);
316 server_redraw_session_group(dst);
317
318 return (0);
319 }
320
321 void
322 server_unlink_window(struct session *s, struct winlink *wl)
323 {
324 if (session_detach(s, wl))
325 server_destroy_session_group(s);
326 else
327 server_redraw_session_group(s);
328 }
329
330 void
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
331 server_destroy_pane(struct window_pane *wp)
332 {
b016948 Romain Francoise Import upstream snapshot from SVN r2608
orebokech authored
333 struct window *w = wp->window;
334 int old_fd;
335 struct screen_write_ctx ctx;
336 struct grid_cell gc;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
337
b016948 Romain Francoise Import upstream snapshot from SVN r2608
orebokech authored
338 old_fd = wp->fd;
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
339 if (wp->fd != -1) {
340 close(wp->fd);
341 bufferevent_free(wp->event);
342 wp->fd = -1;
343 }
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
344
b016948 Romain Francoise Import upstream snapshot from SVN r2608
orebokech authored
345 if (options_get_number(&w->options, "remain-on-exit")) {
346 if (old_fd == -1)
347 return;
348 screen_write_start(&ctx, wp, &wp->base);
349 screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1);
350 screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1);
351 screen_write_linefeed(&ctx, 1);
352 memcpy(&gc, &grid_default_cell, sizeof gc);
353 gc.attr |= GRID_ATTR_BRIGHT;
354 screen_write_puts(&ctx, &gc, "Pane is dead");
355 screen_write_stop(&ctx);
356 wp->flags |= PANE_REDRAW;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
357 return;
b016948 Romain Francoise Import upstream snapshot from SVN r2608
orebokech authored
358 }
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
359
360 layout_close_pane(wp);
361 window_remove_pane(w, wp);
362
363 if (TAILQ_EMPTY(&w->panes))
364 server_kill_window(w);
365 else
366 server_redraw_window(w);
367 }
368
369 void
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
370 server_destroy_session_group(struct session *s)
371 {
372 struct session_group *sg;
373
374 if ((sg = session_group_find(s)) == NULL)
375 server_destroy_session(s);
376 else {
377 TAILQ_FOREACH(s, &sg->sessions, gentry)
378 server_destroy_session(s);
379 TAILQ_REMOVE(&session_groups, sg, entry);
380 xfree(sg);
381 }
382 }
383
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
384 struct session *
385 server_next_session(struct session *s)
386 {
387 struct session *s_loop, *s_out;
388
389 s_out = NULL;
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
390 RB_FOREACH(s_loop, sessions, &sessions) {
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
391 if (s_loop == s)
392 continue;
393 if (s_out == NULL ||
394 timercmp(&s_loop->activity_time, &s_out->activity_time, <))
395 s_out = s_loop;
396 }
397 return (s_out);
398 }
399
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
400 void
401 server_destroy_session(struct session *s)
402 {
403 struct client *c;
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
404 struct session *s_new;
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
405 u_int i;
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
406
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
407 if (!options_get_number(&s->options, "detach-on-destroy"))
408 s_new = server_next_session(s);
409 else
410 s_new = NULL;
411
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
412 for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
413 c = ARRAY_ITEM(&clients, i);
414 if (c == NULL || c->session != s)
415 continue;
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
416 if (s_new == NULL) {
417 c->session = NULL;
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
418 c->flags |= CLIENT_EXIT;
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
419 } else {
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
420 c->last_session = NULL;
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
421 c->session = s_new;
7216c39 Karl Ferdinand Ebert Imported Upstream version 1.5
kfebert authored
422 session_update_activity(s_new);
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
423 server_redraw_client(c);
424 }
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
425 }
fb53a63 Karl Ferdinand Ebert Imported Upstream version 1.3
kfebert authored
426 recalculate_sizes();
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
427 }
428
429 void
77c63de Romain Francoise Import upstream version 1.4
orebokech authored
430 server_check_unattached (void)
431 {
432 struct session *s;
433
434 /*
435 * If any sessions are no longer attached and have destroy-unattached
436 * set, collect them.
437 */
438 RB_FOREACH(s, sessions, &sessions) {
439 if (!(s->flags & SESSION_UNATTACHED))
440 continue;
441 if (options_get_number (&s->options, "destroy-unattached"))
442 session_destroy(s);
443 }
444 }
445
446 void
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
447 server_set_identify(struct client *c)
448 {
449 struct timeval tv;
450 int delay;
451
452 delay = options_get_number(&c->session->options, "display-panes-time");
453 tv.tv_sec = delay / 1000;
454 tv.tv_usec = (delay % 1000) * 1000L;
455
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
456 evtimer_del(&c->identify_timer);
457 evtimer_set(&c->identify_timer, server_callback_identify, c);
458 evtimer_add(&c->identify_timer, &tv);
8fade26 Imported Upstream version 1.1
Karl Ferdinand Ebert authored
459
460 c->flags |= CLIENT_IDENTIFY;
461 c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
462 server_redraw_client(c);
463 }
464
465 void
466 server_clear_identify(struct client *c)
467 {
468 if (c->flags & CLIENT_IDENTIFY) {
469 c->flags &= ~CLIENT_IDENTIFY;
470 c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
471 server_redraw_client(c);
472 }
473 }
dda8e8e Karl Ferdinand Ebert Imported Upstream version 1.2
kfebert authored
474
475 /* ARGSUSED */
476 void
477 server_callback_identify(unused int fd, unused short events, void *data)
478 {
479 struct client *c = data;
480
481 server_clear_identify(c);
482 }
483
484 void
485 server_update_event(struct client *c)
486 {
487 short events;
488
489 events = 0;
490 if (!(c->flags & CLIENT_BAD))
491 events |= EV_READ;
492 if (c->ibuf.w.queued > 0)
493 events |= EV_WRITE;
494 event_del(&c->event);
495 event_set(&c->event, c->ibuf.fd, events, server_client_callback, c);
496 event_add(&c->event, NULL);
497 }
Something went wrong with that request. Please try again.