Annotation of src/usr.bin/tmux/server-fn.c, Revision 1.25
1.25 ! nicm 1: /* $OpenBSD: server-fn.c,v 1.24 2009/10/04 10:55:30 nicm Exp $ */
1.1 nicm 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>
1.5 nicm 22: #include <time.h>
1.1 nicm 23: #include <unistd.h>
24:
25: #include "tmux.h"
26:
1.13 nicm 27: void
28: server_fill_environ(struct session *s, struct environ *env)
1.1 nicm 29: {
1.13 nicm 30: char tmuxvar[MAXPATHLEN], *term;
31: u_int idx;
1.1 nicm 32:
33: if (session_index(s, &idx) != 0)
34: fatalx("session not found");
35: xsnprintf(tmuxvar, sizeof tmuxvar,
1.13 nicm 36: "%s,%ld,%u", socket_path, (long) getpid(), idx);
37: environ_set(env, "TMUX", tmuxvar);
1.1 nicm 38:
1.13 nicm 39: term = options_get_string(&s->options, "default-terminal");
40: environ_set(env, "TERM", term);
1.1 nicm 41: }
42:
43: void
1.10 nicm 44: server_write_error(struct client *c, const char *msg)
45: {
46: struct msg_print_data printdata;
47:
48: strlcpy(printdata.msg, msg, sizeof printdata.msg);
49: server_write_client(c, MSG_ERROR, &printdata, sizeof printdata);
50: }
51:
52: void
1.1 nicm 53: server_write_client(
1.11 nicm 54: struct client *c, enum msgtype type, const void *buf, size_t len)
1.1 nicm 55: {
1.14 nicm 56: struct imsgbuf *ibuf = &c->ibuf;
1.1 nicm 57:
1.12 nicm 58: if (c->flags & CLIENT_BAD)
59: return;
1.14 nicm 60: log_debug("writing %d to client %d", type, c->ibuf.fd);
61: imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, -1, (void *) buf, len);
1.1 nicm 62: }
63:
64: void
65: server_write_session(
1.11 nicm 66: struct session *s, enum msgtype type, const void *buf, size_t len)
1.1 nicm 67: {
68: struct client *c;
69: u_int i;
70:
71: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
72: c = ARRAY_ITEM(&clients, i);
73: if (c == NULL || c->session == NULL)
74: continue;
75: if (c->session == s)
76: server_write_client(c, type, buf, len);
77: }
78: }
79:
80: void
81: server_redraw_client(struct client *c)
82: {
83: c->flags |= CLIENT_REDRAW;
84: }
85:
86: void
87: server_status_client(struct client *c)
88: {
89: c->flags |= CLIENT_STATUS;
90: }
91:
92: void
93: server_redraw_session(struct session *s)
94: {
95: struct client *c;
96: u_int i;
97:
98: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
99: c = ARRAY_ITEM(&clients, i);
100: if (c == NULL || c->session == NULL)
101: continue;
102: if (c->session == s)
103: server_redraw_client(c);
104: }
105: }
106:
107: void
1.25 ! nicm 108: server_redraw_session_group(struct session *s)
! 109: {
! 110: struct session_group *sg;
! 111:
! 112: if ((sg = session_group_find(s)) == NULL)
! 113: server_redraw_session(s);
! 114: else {
! 115: TAILQ_FOREACH(s, &sg->sessions, gentry)
! 116: server_redraw_session(s);
! 117: }
! 118: }
! 119:
! 120: void
1.1 nicm 121: server_status_session(struct session *s)
122: {
123: struct client *c;
124: u_int i;
125:
126: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
127: c = ARRAY_ITEM(&clients, i);
128: if (c == NULL || c->session == NULL)
129: continue;
130: if (c->session == s)
131: server_status_client(c);
132: }
133: }
134:
135: void
1.25 ! nicm 136: server_status_session_group(struct session *s)
! 137: {
! 138: struct session_group *sg;
! 139:
! 140: if ((sg = session_group_find(s)) == NULL)
! 141: server_status_session(s);
! 142: else {
! 143: TAILQ_FOREACH(s, &sg->sessions, gentry)
! 144: server_status_session(s);
! 145: }
! 146: }
! 147:
! 148: void
1.1 nicm 149: server_redraw_window(struct window *w)
150: {
151: struct client *c;
152: u_int i;
153:
154: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
155: c = ARRAY_ITEM(&clients, i);
156: if (c == NULL || c->session == NULL)
157: continue;
158: if (c->session->curw->window == w)
159: server_redraw_client(c);
160: }
161: w->flags |= WINDOW_REDRAW;
162: }
163:
164: void
165: server_status_window(struct window *w)
166: {
167: struct session *s;
168: u_int i;
169:
170: /*
171: * This is slightly different. We want to redraw the status line of any
172: * clients containing this window rather than any where it is the
173: * current window.
174: */
175:
176: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
177: s = ARRAY_ITEM(&sessions, i);
178: if (s != NULL && session_has(s, w))
179: server_status_session(s);
180: }
181: }
182:
183: void
184: server_lock(void)
185: {
1.23 nicm 186: struct client *c;
187: u_int i;
1.17 nicm 188:
1.1 nicm 189: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
190: c = ARRAY_ITEM(&clients, i);
191: if (c == NULL || c->session == NULL)
192: continue;
1.23 nicm 193: server_lock_client(c);
194: }
195: }
1.1 nicm 196:
1.23 nicm 197: void
198: server_lock_session(struct session *s)
199: {
200: struct client *c;
201: u_int i;
202:
203: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
204: c = ARRAY_ITEM(&clients, i);
205: if (c == NULL || c->session == NULL || c->session != s)
206: continue;
207: server_lock_client(c);
208: }
209: }
1.1 nicm 210:
1.23 nicm 211: void
212: server_lock_client(struct client *c)
213: {
214: const char *cmd;
215: size_t cmdlen;
216: struct msg_lock_data lockdata;
1.24 nicm 217:
218: if (c->flags & CLIENT_SUSPENDED)
219: return;
1.1 nicm 220:
1.23 nicm 221: cmd = options_get_string(&c->session->options, "lock-command");
222: cmdlen = strlcpy(lockdata.cmd, cmd, sizeof lockdata.cmd);
223: if (cmdlen >= sizeof lockdata.cmd)
224: return;
225:
226: tty_stop_tty(&c->tty);
227: tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_SMCUP));
228: tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_CLEAR));
229:
230: c->flags |= CLIENT_SUSPENDED;
231: server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
1.8 nicm 232: }
233:
234: void
235: server_kill_window(struct window *w)
236: {
237: struct session *s;
238: struct winlink *wl;
1.19 nicm 239: u_int i;
1.8 nicm 240:
241: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
242: s = ARRAY_ITEM(&sessions, i);
243: if (s == NULL || !session_has(s, w))
244: continue;
245: if ((wl = winlink_find_by_window(&s->windows, w)) == NULL)
246: continue;
247:
1.19 nicm 248: if (session_detach(s, wl))
1.25 ! nicm 249: server_destroy_session_group(s);
! 250: else {
1.19 nicm 251: server_redraw_session(s);
1.25 ! nicm 252: server_status_session_group(s);
! 253: }
1.8 nicm 254: }
1.21 nicm 255: }
256:
257: int
1.25 ! nicm 258: server_link_window(struct session *src, struct winlink *srcwl,
! 259: struct session *dst, int dstidx, int killflag, int selectflag, char **cause)
1.21 nicm 260: {
1.25 ! nicm 261: struct winlink *dstwl;
! 262: struct session_group *srcsg, *dstsg;
! 263:
! 264: srcsg = session_group_find(src);
! 265: dstsg = session_group_find(dst);
! 266: if (src != dst && srcsg != NULL && dstsg != NULL && srcsg == dstsg) {
! 267: xasprintf(cause, "sessions are grouped");
! 268: return (-1);
! 269: }
1.21 nicm 270:
271: dstwl = NULL;
272: if (dstidx != -1)
273: dstwl = winlink_find_by_index(&dst->windows, dstidx);
274: if (dstwl != NULL) {
275: if (dstwl->window == srcwl->window)
276: return (0);
277: if (killflag) {
278: /*
279: * Can't use session_detach as it will destroy session
280: * if this makes it empty.
281: */
282: session_alert_cancel(dst, dstwl);
283: winlink_stack_remove(&dst->lastw, dstwl);
284: winlink_remove(&dst->windows, dstwl);
285:
286: /* Force select/redraw if current. */
287: if (dstwl == dst->curw)
288: selectflag = 1;
289: }
290: }
291:
292: if (dstidx == -1)
293: dstidx = -1 - options_get_number(&dst->options, "base-index");
294: dstwl = session_attach(dst, srcwl->window, dstidx, cause);
295: if (dstwl == NULL)
296: return (-1);
297:
1.25 ! nicm 298: if (selectflag)
1.21 nicm 299: session_select(dst, dstwl->idx);
1.25 ! nicm 300: server_redraw_session_group(dst);
1.21 nicm 301:
302: return (0);
303: }
304:
305: void
306: server_unlink_window(struct session *s, struct winlink *wl)
307: {
308: if (session_detach(s, wl))
1.25 ! nicm 309: server_destroy_session_group(s);
! 310: else
! 311: server_redraw_session_group(s);
! 312: }
! 313:
! 314: void
! 315: server_destroy_session_group(struct session *s)
! 316: {
! 317: struct session_group *sg;
! 318:
! 319: if ((sg = session_group_find(s)) == NULL)
1.21 nicm 320: server_destroy_session(s);
1.25 ! nicm 321: else {
! 322: TAILQ_FOREACH(s, &sg->sessions, gentry)
! 323: server_destroy_session(s);
! 324: TAILQ_REMOVE(&session_groups, sg, entry);
! 325: xfree(sg);
! 326: }
1.19 nicm 327: }
328:
329: void
330: server_destroy_session(struct session *s)
331: {
332: struct client *c;
333: u_int i;
334:
335: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
336: c = ARRAY_ITEM(&clients, i);
337: if (c == NULL || c->session != s)
338: continue;
339: c->session = NULL;
340: server_write_client(c, MSG_EXIT, NULL, 0);
341: }
1.15 nicm 342: }
343:
344: void
345: server_set_identify(struct client *c)
346: {
347: struct timeval tv;
348: int delay;
349:
350: delay = options_get_number(&c->session->options, "display-panes-time");
351: tv.tv_sec = delay / 1000;
352: tv.tv_usec = (delay % 1000) * 1000L;
353:
354: if (gettimeofday(&c->identify_timer, NULL) != 0)
1.20 nicm 355: fatal("gettimeofday failed");
1.15 nicm 356: timeradd(&c->identify_timer, &tv, &c->identify_timer);
357:
358: c->flags |= CLIENT_IDENTIFY;
359: c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
360: server_redraw_client(c);
361: }
362:
363: void
364: server_clear_identify(struct client *c)
365: {
366: if (c->flags & CLIENT_IDENTIFY) {
367: c->flags &= ~CLIENT_IDENTIFY;
368: c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
369: server_redraw_client(c);
370: }
1.1 nicm 371: }