Annotation of src/usr.bin/tmux/server-fn.c, Revision 1.26
1.26 ! nicm 1: /* $OpenBSD: server-fn.c,v 1.25 2009/10/10 10:02:48 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. */
1.26 ! nicm 287: if (dstwl == dst->curw) {
1.21 nicm 288: selectflag = 1;
1.26 ! nicm 289: dst->curw = NULL;
! 290: }
1.21 nicm 291: }
292: }
293:
294: if (dstidx == -1)
295: dstidx = -1 - options_get_number(&dst->options, "base-index");
296: dstwl = session_attach(dst, srcwl->window, dstidx, cause);
297: if (dstwl == NULL)
298: return (-1);
299:
1.25 nicm 300: if (selectflag)
1.21 nicm 301: session_select(dst, dstwl->idx);
1.25 nicm 302: server_redraw_session_group(dst);
1.21 nicm 303:
304: return (0);
305: }
306:
307: void
308: server_unlink_window(struct session *s, struct winlink *wl)
309: {
310: if (session_detach(s, wl))
1.25 nicm 311: server_destroy_session_group(s);
312: else
313: server_redraw_session_group(s);
314: }
315:
316: void
317: server_destroy_session_group(struct session *s)
318: {
319: struct session_group *sg;
320:
321: if ((sg = session_group_find(s)) == NULL)
1.21 nicm 322: server_destroy_session(s);
1.25 nicm 323: else {
324: TAILQ_FOREACH(s, &sg->sessions, gentry)
325: server_destroy_session(s);
326: TAILQ_REMOVE(&session_groups, sg, entry);
327: xfree(sg);
328: }
1.19 nicm 329: }
330:
331: void
332: server_destroy_session(struct session *s)
333: {
334: struct client *c;
335: u_int i;
336:
337: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
338: c = ARRAY_ITEM(&clients, i);
339: if (c == NULL || c->session != s)
340: continue;
341: c->session = NULL;
342: server_write_client(c, MSG_EXIT, NULL, 0);
343: }
1.15 nicm 344: }
345:
346: void
347: server_set_identify(struct client *c)
348: {
349: struct timeval tv;
350: int delay;
351:
352: delay = options_get_number(&c->session->options, "display-panes-time");
353: tv.tv_sec = delay / 1000;
354: tv.tv_usec = (delay % 1000) * 1000L;
355:
356: if (gettimeofday(&c->identify_timer, NULL) != 0)
1.20 nicm 357: fatal("gettimeofday failed");
1.15 nicm 358: timeradd(&c->identify_timer, &tv, &c->identify_timer);
359:
360: c->flags |= CLIENT_IDENTIFY;
361: c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
362: server_redraw_client(c);
363: }
364:
365: void
366: server_clear_identify(struct client *c)
367: {
368: if (c->flags & CLIENT_IDENTIFY) {
369: c->flags &= ~CLIENT_IDENTIFY;
370: c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
371: server_redraw_client(c);
372: }
1.1 nicm 373: }