Annotation of src/usr.bin/tmux/server.c, Revision 1.37
1.37 ! nicm 1: /* $OpenBSD: server.c,v 1.36 2009/09/14 11:25:35 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: #include <sys/ioctl.h>
21: #include <sys/socket.h>
22: #include <sys/stat.h>
23: #include <sys/un.h>
24: #include <sys/wait.h>
25:
26: #include <errno.h>
27: #include <fcntl.h>
1.5 nicm 28: #include <paths.h>
1.1 nicm 29: #include <signal.h>
30: #include <stdio.h>
31: #include <stdlib.h>
32: #include <string.h>
33: #include <syslog.h>
34: #include <termios.h>
35: #include <time.h>
36: #include <unistd.h>
37:
38: #include "tmux.h"
39:
40: /*
41: * Main server functions.
42: */
43:
44: /* Client list. */
45: struct clients clients;
1.31 nicm 46: struct clients dead_clients;
1.1 nicm 47:
1.13 nicm 48: void server_create_client(int);
1.1 nicm 49: int server_create_socket(void);
50: int server_main(int);
51: void server_shutdown(void);
52: void server_child_signal(void);
53: void server_fill_windows(struct pollfd **);
54: void server_handle_windows(struct pollfd **);
55: void server_fill_clients(struct pollfd **);
56: void server_handle_clients(struct pollfd **);
1.13 nicm 57: void server_accept_client(int);
1.1 nicm 58: void server_handle_client(struct client *);
59: void server_handle_window(struct window *, struct window_pane *);
1.10 nicm 60: int server_check_window_bell(struct session *, struct window *);
1.1 nicm 61: int server_check_window_activity(struct session *,
62: struct window *);
63: int server_check_window_content(struct session *, struct window *,
64: struct window_pane *);
1.31 nicm 65: void server_clean_dead(void);
1.1 nicm 66: void server_lost_client(struct client *);
67: void server_check_window(struct window *);
68: void server_check_redraw(struct client *);
69: void server_redraw_locked(struct client *);
70: void server_check_timers(struct client *);
71: void server_second_timers(void);
72: int server_update_socket(void);
73:
74: /* Create a new client. */
1.13 nicm 75: void
1.1 nicm 76: server_create_client(int fd)
77: {
78: struct client *c;
79: int mode;
80: u_int i;
81:
82: if ((mode = fcntl(fd, F_GETFL)) == -1)
83: fatal("fcntl failed");
84: if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
85: fatal("fcntl failed");
86: if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
87: fatal("fcntl failed");
88:
89: c = xcalloc(1, sizeof *c);
1.31 nicm 90: c->references = 0;
1.18 nicm 91: imsg_init(&c->ibuf, fd);
1.1 nicm 92:
93: ARRAY_INIT(&c->prompt_hdata);
94:
95: c->tty.fd = -1;
96: c->title = NULL;
97:
98: c->session = NULL;
99: c->tty.sx = 80;
1.37 ! nicm 100: c->tty.sy = 24;
1.1 nicm 101: screen_init(&c->status, c->tty.sx, 1, 0);
102:
103: c->message_string = NULL;
104:
105: c->prompt_string = NULL;
106: c->prompt_buffer = NULL;
107: c->prompt_index = 0;
108:
109: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
110: if (ARRAY_ITEM(&clients, i) == NULL) {
111: ARRAY_SET(&clients, i, c);
1.13 nicm 112: return;
1.1 nicm 113: }
114: }
115: ARRAY_ADD(&clients, c);
1.20 nicm 116: log_debug("new client %d", fd);
1.1 nicm 117: }
118:
119: /* Fork new server. */
120: int
121: server_start(char *path)
122: {
1.16 nicm 123: struct client *c;
124: int pair[2], srv_fd;
125: char *cause;
126: char rpathbuf[MAXPATHLEN];
1.1 nicm 127:
128: /* The first client is special and gets a socketpair; create it. */
129: if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
130: fatal("socketpair failed");
131:
132: switch (fork()) {
133: case -1:
134: fatal("fork failed");
135: case 0:
136: break;
137: default:
138: close(pair[1]);
139: return (pair[0]);
140: }
141: close(pair[0]);
142:
143: /*
144: * Must daemonise before loading configuration as the PID changes so
145: * $TMUX would be wrong for sessions created in the config file.
146: */
1.16 nicm 147: if (daemon(1, 0) != 0)
1.1 nicm 148: fatal("daemon failed");
149:
1.16 nicm 150: logfile("server");
151: log_debug("server started, pid %ld", (long) getpid());
152:
1.1 nicm 153: ARRAY_INIT(&windows);
154: ARRAY_INIT(&clients);
1.31 nicm 155: ARRAY_INIT(&dead_clients);
1.1 nicm 156: ARRAY_INIT(&sessions);
1.31 nicm 157: ARRAY_INIT(&dead_sessions);
1.15 nicm 158: mode_key_init_trees();
1.1 nicm 159: key_bindings_init();
160: utf8_build();
161:
162: server_locked = 0;
163: server_password = NULL;
164: server_activity = time(NULL);
165:
166: start_time = time(NULL);
167: socket_path = path;
168:
1.16 nicm 169: if (realpath(socket_path, rpathbuf) == NULL)
170: strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
171: log_debug("socket path %s", socket_path);
172: setproctitle("server (%s)", rpathbuf);
173:
174: srv_fd = server_create_socket();
175: server_create_client(pair[1]);
176:
1.7 nicm 177: if (access(SYSTEM_CFG, R_OK) != 0) {
178: if (errno != ENOENT) {
1.16 nicm 179: xasprintf(
180: &cause, "%s: %s", strerror(errno), SYSTEM_CFG);
181: goto error;
182: }
1.24 nicm 183: } else if (load_cfg(SYSTEM_CFG, NULL, &cause) != 0)
1.16 nicm 184: goto error;
1.24 nicm 185: if (cfg_file != NULL && load_cfg(cfg_file, NULL, &cause) != 0)
1.16 nicm 186: goto error;
1.5 nicm 187:
1.16 nicm 188: exit(server_main(srv_fd));
1.1 nicm 189:
1.16 nicm 190: error:
191: /* Write the error and shutdown the server. */
192: c = ARRAY_FIRST(&clients);
1.1 nicm 193:
1.16 nicm 194: server_write_error(c, cause);
195: xfree(cause);
1.1 nicm 196:
1.27 nicm 197: sigterm = 1;
1.16 nicm 198: server_shutdown();
1.1 nicm 199:
200: exit(server_main(srv_fd));
201: }
202:
203: /* Create server socket. */
204: int
205: server_create_socket(void)
206: {
207: struct sockaddr_un sa;
208: size_t size;
209: mode_t mask;
210: int fd, mode;
211:
212: memset(&sa, 0, sizeof sa);
213: sa.sun_family = AF_UNIX;
214: size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
215: if (size >= sizeof sa.sun_path) {
216: errno = ENAMETOOLONG;
217: fatal("socket failed");
218: }
219: unlink(sa.sun_path);
220:
221: if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
222: fatal("socket failed");
223:
224: mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
225: if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
226: fatal("bind failed");
227: umask(mask);
228:
229: if (listen(fd, 16) == -1)
230: fatal("listen failed");
231:
232: if ((mode = fcntl(fd, F_GETFL)) == -1)
233: fatal("fcntl failed");
234: if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
235: fatal("fcntl failed");
236: if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
237: fatal("fcntl failed");
238:
239: return (fd);
240: }
241:
242: /* Main server loop. */
243: int
244: server_main(int srv_fd)
245: {
246: struct window *w;
247: struct pollfd *pfds, *pfd;
248: int nfds, xtimeout;
249: u_int i, n;
250: time_t now, last;
251:
252: siginit();
1.20 nicm 253: log_debug("server socket is %d", srv_fd);
1.1 nicm 254:
255: last = time(NULL);
256:
257: pfds = NULL;
258: for (;;) {
259: /* If sigterm, kill all windows and clients. */
260: if (sigterm)
261: server_shutdown();
262:
263: /* Handle child exit. */
264: if (sigchld) {
265: server_child_signal();
266: sigchld = 0;
267: }
268:
269: /* Recreate socket on SIGUSR1. */
270: if (sigusr1) {
271: close(srv_fd);
272: srv_fd = server_create_socket();
273: sigusr1 = 0;
274: }
275:
276: /* Initialise pollfd array. */
277: nfds = 1;
278: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
279: w = ARRAY_ITEM(&windows, i);
280: if (w != NULL)
281: nfds += window_count_panes(w);
282: }
283: nfds += ARRAY_LENGTH(&clients) * 2;
284: pfds = xrealloc(pfds, nfds, sizeof *pfds);
285: memset(pfds, 0, nfds * sizeof *pfds);
286: pfd = pfds;
287:
288: /* Fill server socket. */
289: pfd->fd = srv_fd;
290: pfd->events = POLLIN;
291: pfd++;
292:
293: /* Fill window and client sockets. */
294: server_fill_windows(&pfd);
295: server_fill_clients(&pfd);
296:
297: /* Update socket permissions. */
298: xtimeout = INFTIM;
1.27 nicm 299: if (server_update_socket() != 0)
1.1 nicm 300: xtimeout = POLL_TIMEOUT;
301:
302: /* Do the poll. */
1.4 nicm 303: if (poll(pfds, nfds, xtimeout) == -1) {
1.1 nicm 304: if (errno == EAGAIN || errno == EINTR)
305: continue;
306: fatal("poll failed");
307: }
308: pfd = pfds;
309:
310: /* Handle server socket. */
311: if (pfd->revents & (POLLERR|POLLNVAL|POLLHUP))
312: fatalx("lost server socket");
313: if (pfd->revents & POLLIN) {
314: server_accept_client(srv_fd);
315: continue;
316: }
317: pfd++;
318:
319: /* Call second-based timers. */
320: now = time(NULL);
321: if (now != last) {
322: last = now;
323: server_second_timers();
324: }
325:
326: /* Set window names. */
327: set_window_names();
328:
329: /*
330: * Handle window and client sockets. Clients can create
331: * windows, so windows must come first to avoid messing up by
332: * increasing the array size.
333: */
334: server_handle_windows(&pfd);
335: server_handle_clients(&pfd);
336:
1.8 nicm 337: /* Collect any unset key bindings. */
338: key_bindings_clean();
1.31 nicm 339:
340: /* Collect dead clients and sessions. */
341: server_clean_dead();
1.8 nicm 342:
1.1 nicm 343: /*
344: * If we have no sessions and clients left, let's get out
345: * of here...
346: */
347: n = 0;
348: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
349: if (ARRAY_ITEM(&sessions, i) != NULL)
350: n++;
351: }
352: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
353: if (ARRAY_ITEM(&clients, i) != NULL)
354: n++;
355: }
356: if (n == 0)
357: break;
358: }
359: if (pfds != NULL)
360: xfree(pfds);
361:
362: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
363: if (ARRAY_ITEM(&sessions, i) != NULL)
364: session_destroy(ARRAY_ITEM(&sessions, i));
365: }
366: ARRAY_FREE(&sessions);
367:
368: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
369: if (ARRAY_ITEM(&clients, i) != NULL)
370: server_lost_client(ARRAY_ITEM(&clients, i));
371: }
372: ARRAY_FREE(&clients);
373:
1.15 nicm 374: mode_key_free_trees();
1.1 nicm 375: key_bindings_free();
376:
377: close(srv_fd);
378:
379: unlink(socket_path);
380: xfree(socket_path);
381:
1.6 nicm 382: options_free(&global_s_options);
383: options_free(&global_w_options);
1.1 nicm 384: if (server_password != NULL)
385: xfree(server_password);
386:
387: return (0);
388: }
389:
390: /* Kill all clients. */
391: void
392: server_shutdown(void)
393: {
394: struct session *s;
395: struct client *c;
396: u_int i, j;
397:
398: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
399: s = ARRAY_ITEM(&sessions, i);
400: for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
401: c = ARRAY_ITEM(&clients, j);
402: if (c != NULL && c->session == s) {
403: s = NULL;
404: break;
405: }
406: }
407: if (s != NULL)
408: session_destroy(s);
409: }
410:
411: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
412: c = ARRAY_ITEM(&clients, i);
1.16 nicm 413: if (c != NULL) {
414: if (c->flags & CLIENT_BAD)
415: server_lost_client(c);
416: else
417: server_write_client(c, MSG_SHUTDOWN, NULL, 0);
418: }
1.1 nicm 419: }
420: }
421:
422: /* Handle SIGCHLD. */
423: void
424: server_child_signal(void)
425: {
426: struct window *w;
427: struct window_pane *wp;
428: int status;
429: pid_t pid;
430: u_int i;
431:
432: for (;;) {
433: switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
434: case -1:
435: if (errno == ECHILD)
436: return;
437: fatal("waitpid");
438: case 0:
439: return;
440: }
441: if (!WIFSTOPPED(status))
442: continue;
443: if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
444: continue;
445:
446: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
447: w = ARRAY_ITEM(&windows, i);
448: if (w == NULL)
449: continue;
450: TAILQ_FOREACH(wp, &w->panes, entry) {
451: if (wp->pid == pid) {
452: if (killpg(pid, SIGCONT) != 0)
453: kill(pid, SIGCONT);
454: }
455: }
456: }
457: }
458: }
459:
460: /* Fill window pollfds. */
461: void
462: server_fill_windows(struct pollfd **pfd)
463: {
464: struct window *w;
465: struct window_pane *wp;
466: u_int i;
467:
468: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
469: w = ARRAY_ITEM(&windows, i);
470: if (w == NULL)
471: continue;
472:
473: TAILQ_FOREACH(wp, &w->panes, entry) {
474: (*pfd)->fd = wp->fd;
475: if (wp->fd != -1) {
476: (*pfd)->events = POLLIN;
477: if (BUFFER_USED(wp->out) > 0)
478: (*pfd)->events |= POLLOUT;
479: }
480: (*pfd)++;
481: }
482: }
483: }
484:
485: /* Handle window pollfds. */
486: void
487: server_handle_windows(struct pollfd **pfd)
488: {
489: struct window *w;
490: struct window_pane *wp;
491: u_int i;
492:
493: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
494: w = ARRAY_ITEM(&windows, i);
495: if (w == NULL)
496: continue;
497:
498: TAILQ_FOREACH(wp, &w->panes, entry) {
499: if (wp->fd != -1) {
500: if (buffer_poll(*pfd, wp->in, wp->out) != 0) {
501: close(wp->fd);
502: wp->fd = -1;
503: } else
504: server_handle_window(w, wp);
505: }
506: (*pfd)++;
507: }
508:
509: server_check_window(w);
510: }
511: }
512:
513: /* Check for general redraw on client. */
514: void
515: server_check_redraw(struct client *c)
516: {
517: struct session *s;
518: struct window_pane *wp;
519: char title[512];
520: int flags, redraw;
521:
522: if (c == NULL || c->session == NULL)
523: return;
524: s = c->session;
525:
526: flags = c->tty.flags & TTY_FREEZE;
527: c->tty.flags &= ~TTY_FREEZE;
528:
529: if (options_get_number(&s->options, "set-titles")) {
530: xsnprintf(title, sizeof title, "%s:%u:%s - \"%s\"",
531: s->name, s->curw->idx, s->curw->window->name,
532: s->curw->window->active->screen->title);
533: if (c->title == NULL || strcmp(title, c->title) != 0) {
534: if (c->title != NULL)
535: xfree(c->title);
536: c->title = xstrdup(title);
537: tty_set_title(&c->tty, c->title);
538: }
539: }
540:
541: if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
542: if (c->message_string != NULL)
543: redraw = status_message_redraw(c);
544: else if (c->prompt_string != NULL)
545: redraw = status_prompt_redraw(c);
546: else
547: redraw = status_redraw(c);
548: if (!redraw)
549: c->flags &= ~CLIENT_STATUS;
550: }
551:
552: if (c->flags & CLIENT_REDRAW) {
553: if (server_locked)
554: server_redraw_locked(c);
555: else
1.9 nicm 556: screen_redraw_screen(c, 0);
1.1 nicm 557: c->flags &= ~CLIENT_STATUS;
558: } else {
559: TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
560: if (wp->flags & PANE_REDRAW)
561: screen_redraw_pane(c, wp);
562: }
563: }
564:
565: if (c->flags & CLIENT_STATUS)
1.9 nicm 566: screen_redraw_screen(c, 1);
1.1 nicm 567:
568: c->tty.flags |= flags;
569:
570: c->flags &= ~(CLIENT_REDRAW|CLIENT_STATUS);
571: }
572:
573: /* Redraw client when locked. */
574: void
575: server_redraw_locked(struct client *c)
576: {
577: struct screen_write_ctx ctx;
578: struct screen screen;
1.12 nicm 579: struct grid_cell gc;
1.1 nicm 580: u_int colour, xx, yy, i;
581: int style;
582:
583: xx = c->tty.sx;
584: yy = c->tty.sy - 1;
585: if (xx == 0 || yy == 0)
586: return;
1.6 nicm 587: colour = options_get_number(&global_w_options, "clock-mode-colour");
588: style = options_get_number(&global_w_options, "clock-mode-style");
1.1 nicm 589:
1.12 nicm 590: memcpy(&gc, &grid_default_cell, sizeof gc);
1.33 nicm 591: colour_set_fg(&gc, colour);
1.12 nicm 592: gc.attr |= GRID_ATTR_BRIGHT;
593:
1.1 nicm 594: screen_init(&screen, xx, yy, 0);
595:
596: screen_write_start(&ctx, NULL, &screen);
597: clock_draw(&ctx, colour, style);
1.12 nicm 598:
599: if (password_failures != 0) {
600: screen_write_cursormove(&ctx, 0, 0);
601: screen_write_puts(
602: &ctx, &gc, "%u failed attempts", password_failures);
1.28 nicm 603: if (time(NULL) < password_backoff)
604: screen_write_puts(&ctx, &gc, "; sleeping");
1.12 nicm 605: }
606:
1.1 nicm 607: screen_write_stop(&ctx);
608:
609: for (i = 0; i < screen_size_y(&screen); i++)
610: tty_draw_line(&c->tty, &screen, i, 0, 0);
1.9 nicm 611: screen_redraw_screen(c, 1);
1.1 nicm 612:
613: screen_free(&screen);
614: }
615:
616: /* Check for timers on client. */
617: void
618: server_check_timers(struct client *c)
619: {
620: struct session *s;
621: struct timeval tv;
622: u_int interval;
623:
624: if (c == NULL || c->session == NULL)
625: return;
626: s = c->session;
627:
628: if (gettimeofday(&tv, NULL) != 0)
629: fatal("gettimeofday");
630:
1.26 nicm 631: if (c->flags & CLIENT_IDENTIFY && timercmp(&tv, &c->identify_timer, >))
632: server_clear_identify(c);
633:
1.1 nicm 634: if (c->message_string != NULL && timercmp(&tv, &c->message_timer, >))
635: status_message_clear(c);
636:
637: if (c->message_string != NULL || c->prompt_string != NULL) {
638: /*
639: * Don't need timed redraw for messages/prompts so bail now.
640: * The status timer isn't reset when they are redrawn anyway.
641: */
642: return;
643: }
644: if (!options_get_number(&s->options, "status"))
645: return;
646:
647: /* Check timer; resolution is only a second so don't be too clever. */
648: interval = options_get_number(&s->options, "status-interval");
649: if (interval == 0)
650: return;
651: if (tv.tv_sec < c->status_timer.tv_sec ||
652: ((u_int) tv.tv_sec) - c->status_timer.tv_sec >= interval)
653: c->flags |= CLIENT_STATUS;
654: }
655:
656: /* Fill client pollfds. */
657: void
658: server_fill_clients(struct pollfd **pfd)
659: {
660: struct client *c;
661: struct window *w;
662: struct window_pane *wp;
663: u_int i;
664:
665: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
666: c = ARRAY_ITEM(&clients, i);
667:
668: server_check_timers(c);
669: server_check_redraw(c);
670:
671: if (c == NULL)
672: (*pfd)->fd = -1;
673: else {
1.18 nicm 674: (*pfd)->fd = c->ibuf.fd;
1.16 nicm 675: if (!(c->flags & CLIENT_BAD))
1.18 nicm 676: (*pfd)->events |= POLLIN;
677: if (c->ibuf.w.queued > 0)
1.1 nicm 678: (*pfd)->events |= POLLOUT;
679: }
680: (*pfd)++;
681:
682: if (c == NULL || c->flags & CLIENT_SUSPENDED ||
683: c->tty.fd == -1 || c->session == NULL)
684: (*pfd)->fd = -1;
685: else {
686: (*pfd)->fd = c->tty.fd;
687: (*pfd)->events = POLLIN;
688: if (BUFFER_USED(c->tty.out) > 0)
689: (*pfd)->events |= POLLOUT;
690: }
691: (*pfd)++;
692: }
693:
694: /*
695: * Clear any window redraw flags (will have been redrawn as part of
696: * client).
697: */
698: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
699: w = ARRAY_ITEM(&windows, i);
700: if (w == NULL)
701: continue;
702:
703: w->flags &= ~WINDOW_REDRAW;
704: TAILQ_FOREACH(wp, &w->panes, entry)
705: wp->flags &= ~PANE_REDRAW;
706: }
707: }
708:
709: /* Handle client pollfds. */
710: void
711: server_handle_clients(struct pollfd **pfd)
712: {
713: struct client *c;
714: u_int i;
715:
716: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
717: c = ARRAY_ITEM(&clients, i);
718:
719: if (c != NULL) {
1.18 nicm 720: if ((*pfd)->revents & (POLLERR|POLLNVAL|POLLHUP)) {
1.1 nicm 721: server_lost_client(c);
722: (*pfd) += 2;
723: continue;
1.18 nicm 724: }
725:
726: if ((*pfd)->revents & POLLOUT) {
727: if (msgbuf_write(&c->ibuf.w) < 0) {
728: server_lost_client(c);
729: (*pfd) += 2;
730: continue;
731: }
732: }
733:
734: if (c->flags & CLIENT_BAD) {
735: if (c->ibuf.w.queued == 0)
1.16 nicm 736: server_lost_client(c);
737: (*pfd) += 2;
1.18 nicm 738: continue;
739: } else if ((*pfd)->revents & POLLIN) {
740: if (server_msg_dispatch(c) != 0) {
741: server_lost_client(c);
742: (*pfd) += 2;
743: continue;
744: }
745: }
1.1 nicm 746: }
747: (*pfd)++;
748:
749: if (c != NULL && !(c->flags & CLIENT_SUSPENDED) &&
750: c->tty.fd != -1 && c->session != NULL) {
751: if (buffer_poll(*pfd, c->tty.in, c->tty.out) != 0)
752: server_lost_client(c);
753: else
754: server_handle_client(c);
755: }
756: (*pfd)++;
757: }
758: }
759:
760: /* accept(2) and create new client. */
1.13 nicm 761: void
1.1 nicm 762: server_accept_client(int srv_fd)
763: {
764: struct sockaddr_storage sa;
765: socklen_t slen = sizeof sa;
766: int fd;
767:
768: fd = accept(srv_fd, (struct sockaddr *) &sa, &slen);
769: if (fd == -1) {
770: if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
1.13 nicm 771: return;
1.1 nicm 772: fatal("accept failed");
773: }
774: if (sigterm) {
775: close(fd);
1.13 nicm 776: return;
1.1 nicm 777: }
1.13 nicm 778: server_create_client(fd);
1.1 nicm 779: }
780:
781: /* Input data from client. */
782: void
783: server_handle_client(struct client *c)
784: {
1.32 nicm 785: struct window *w;
1.1 nicm 786: struct window_pane *wp;
787: struct screen *s;
788: struct timeval tv;
789: struct key_binding *bd;
790: int key, prefix, status, xtimeout;
791: int mode;
792: u_char mouse[3];
793:
794: xtimeout = options_get_number(&c->session->options, "repeat-time");
795: if (xtimeout != 0 && c->flags & CLIENT_REPEAT) {
796: if (gettimeofday(&tv, NULL) != 0)
797: fatal("gettimeofday");
798: if (timercmp(&tv, &c->repeat_timer, >))
799: c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT);
800: }
801:
802: /* Process keys. */
803: prefix = options_get_number(&c->session->options, "prefix");
804: while (tty_keys_next(&c->tty, &key, mouse) == 0) {
805: server_activity = time(NULL);
806:
807: if (c->session == NULL)
808: return;
1.32 nicm 809: w = c->session->curw->window;
810: wp = w->active; /* could die */
1.1 nicm 811:
1.32 nicm 812: /* Special case: number keys jump to pane in identify mode. */
813: if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
814: wp = window_pane_at_index(w, key - '0');
815: if (wp != NULL && window_pane_visible(wp))
816: window_set_active_pane(w, wp);
817: server_clear_identify(c);
818: continue;
819: }
820:
1.1 nicm 821: status_message_clear(c);
1.26 nicm 822: server_clear_identify(c);
1.1 nicm 823: if (c->prompt_string != NULL) {
824: status_prompt_key(c, key);
825: continue;
826: }
827: if (server_locked)
828: continue;
829:
830: /* Check for mouse keys. */
831: if (key == KEYC_MOUSE) {
832: window_pane_mouse(wp, c, mouse[0], mouse[1], mouse[2]);
833: continue;
834: }
835:
836: /* No previous prefix key. */
837: if (!(c->flags & CLIENT_PREFIX)) {
838: if (key == prefix)
839: c->flags |= CLIENT_PREFIX;
1.14 nicm 840: else {
841: /* Try as a non-prefix key binding. */
842: if ((bd = key_bindings_lookup(key)) == NULL)
843: window_pane_key(wp, c, key);
844: else
845: key_bindings_dispatch(bd, c);
846: }
1.1 nicm 847: continue;
848: }
849:
850: /* Prefix key already pressed. Reset prefix and lookup key. */
851: c->flags &= ~CLIENT_PREFIX;
1.14 nicm 852: if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) {
1.1 nicm 853: /* If repeating, treat this as a key, else ignore. */
854: if (c->flags & CLIENT_REPEAT) {
855: c->flags &= ~CLIENT_REPEAT;
856: if (key == prefix)
857: c->flags |= CLIENT_PREFIX;
858: else
859: window_pane_key(wp, c, key);
860: }
861: continue;
862: }
863:
864: /* If already repeating, but this key can't repeat, skip it. */
865: if (c->flags & CLIENT_REPEAT && !bd->can_repeat) {
866: c->flags &= ~CLIENT_REPEAT;
867: if (key == prefix)
868: c->flags |= CLIENT_PREFIX;
869: else
870: window_pane_key(wp, c, key);
871: continue;
872: }
873:
874: /* If this key can repeat, reset the repeat flags and timer. */
875: if (xtimeout != 0 && bd->can_repeat) {
876: c->flags |= CLIENT_PREFIX|CLIENT_REPEAT;
877:
878: tv.tv_sec = xtimeout / 1000;
879: tv.tv_usec = (xtimeout % 1000) * 1000L;
880: if (gettimeofday(&c->repeat_timer, NULL) != 0)
881: fatal("gettimeofday");
882: timeradd(&c->repeat_timer, &tv, &c->repeat_timer);
883: }
884:
885: /* Dispatch the command. */
886: key_bindings_dispatch(bd, c);
887: }
888: if (c->session == NULL)
889: return;
890: wp = c->session->curw->window->active; /* could die - do each loop */
891: s = wp->screen;
892:
1.21 nicm 893: /*
894: * Update cursor position and mode settings. The scroll region and
895: * attributes are cleared across poll(2) as this is the most likely
896: * time a user may interrupt tmux, for example with ~^Z in ssh(1). This
897: * is a compromise between excessive resets and likelihood of an
898: * interrupt.
899: *
900: * tty_region/tty_reset/tty_update_mode already take care of not
901: * resetting things that are already in their default state.
902: */
1.1 nicm 903: status = options_get_number(&c->session->options, "status");
1.17 nicm 904: tty_region(&c->tty, 0, c->tty.sy - 1, 0);
1.11 nicm 905: if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
906: tty_cursor(&c->tty, 0, 0, 0, 0);
907: else
1.1 nicm 908: tty_cursor(&c->tty, s->cx, s->cy, wp->xoff, wp->yoff);
909:
910: mode = s->mode;
911: if (server_locked)
912: mode &= ~TTY_NOCURSOR;
913: tty_update_mode(&c->tty, mode);
1.21 nicm 914: tty_reset(&c->tty);
1.1 nicm 915: }
916:
917: /* Lost a client. */
918: void
919: server_lost_client(struct client *c)
920: {
921: u_int i;
922:
923: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
924: if (ARRAY_ITEM(&clients, i) == c)
925: ARRAY_SET(&clients, i, NULL);
926: }
1.20 nicm 927: log_debug("lost client %d", c->ibuf.fd);
1.1 nicm 928:
1.25 nicm 929: /*
930: * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
931: * and tty_free might close an unrelated fd.
932: */
933: if (c->flags & CLIENT_TERMINAL)
934: tty_free(&c->tty);
1.1 nicm 935:
936: screen_free(&c->status);
937:
938: if (c->title != NULL)
939: xfree(c->title);
940:
941: if (c->message_string != NULL)
942: xfree(c->message_string);
943:
944: if (c->prompt_string != NULL)
945: xfree(c->prompt_string);
946: if (c->prompt_buffer != NULL)
947: xfree(c->prompt_buffer);
948: for (i = 0; i < ARRAY_LENGTH(&c->prompt_hdata); i++)
949: xfree(ARRAY_ITEM(&c->prompt_hdata, i));
950: ARRAY_FREE(&c->prompt_hdata);
951:
952: if (c->cwd != NULL)
953: xfree(c->cwd);
954:
1.18 nicm 955: close(c->ibuf.fd);
956: imsg_clear(&c->ibuf);
1.31 nicm 957:
958: for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
959: if (ARRAY_ITEM(&dead_clients, i) == NULL) {
960: ARRAY_SET(&dead_clients, i, c);
961: break;
962: }
963: }
964: if (i == ARRAY_LENGTH(&dead_clients))
965: ARRAY_ADD(&dead_clients, c);
966: c->flags |= CLIENT_DEAD;
1.1 nicm 967:
968: recalculate_sizes();
1.31 nicm 969: }
970:
971: /* Free dead, unreferenced clients and sessions. */
972: void
973: server_clean_dead(void)
974: {
975: struct session *s;
976: struct client *c;
977: u_int i;
978:
979: for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
980: s = ARRAY_ITEM(&dead_sessions, i);
981: if (s == NULL || s->references != 0)
982: continue;
983: ARRAY_SET(&dead_sessions, i, NULL);
984: xfree(s);
985: }
986:
987: for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
988: c = ARRAY_ITEM(&dead_clients, i);
989: if (c == NULL || c->references != 0)
990: continue;
991: ARRAY_SET(&dead_clients, i, NULL);
992: xfree(c);
993: }
1.1 nicm 994: }
995:
996: /* Handle window data. */
997: void
998: server_handle_window(struct window *w, struct window_pane *wp)
999: {
1000: struct session *s;
1001: u_int i;
1002: int update;
1003:
1004: window_pane_parse(wp);
1005:
1006: if ((w->flags & (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT)) == 0)
1007: return;
1008:
1009: update = 0;
1010: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
1011: s = ARRAY_ITEM(&sessions, i);
1012: if (s == NULL || !session_has(s, w))
1013: continue;
1014:
1.10 nicm 1015: update += server_check_window_bell(s, w);
1.1 nicm 1016: update += server_check_window_activity(s, w);
1017: update += server_check_window_content(s, w, wp);
1018: }
1019: if (update)
1020: server_status_window(w);
1021:
1022: w->flags &= ~(WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_CONTENT);
1023: }
1024:
1025: int
1.10 nicm 1026: server_check_window_bell(struct session *s, struct window *w)
1.1 nicm 1027: {
1028: struct client *c;
1029: u_int i;
1.10 nicm 1030: int action, visual;
1.1 nicm 1031:
1032: if (!(w->flags & WINDOW_BELL))
1033: return (0);
1034: if (session_alert_has_window(s, w, WINDOW_BELL))
1035: return (0);
1036: session_alert_add(s, w, WINDOW_BELL);
1037:
1038: action = options_get_number(&s->options, "bell-action");
1039: switch (action) {
1040: case BELL_ANY:
1041: if (s->flags & SESSION_UNATTACHED)
1042: break;
1.10 nicm 1043: visual = options_get_number(&s->options, "visual-bell");
1.1 nicm 1044: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1045: c = ARRAY_ITEM(&clients, i);
1.10 nicm 1046: if (c == NULL || c->session != s)
1047: continue;
1048: if (!visual) {
1.1 nicm 1049: tty_putcode(&c->tty, TTYC_BEL);
1.10 nicm 1050: continue;
1051: }
1052: if (c->session->curw->window == w) {
1053: status_message_set(c, "Bell in current window");
1054: continue;
1055: }
1056: status_message_set(c, "Bell in window %u",
1057: winlink_find_by_window(&s->windows, w)->idx);
1.1 nicm 1058: }
1059: break;
1060: case BELL_CURRENT:
1.10 nicm 1061: if (s->flags & SESSION_UNATTACHED)
1.1 nicm 1062: break;
1.10 nicm 1063: visual = options_get_number(&s->options, "visual-bell");
1.1 nicm 1064: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1065: c = ARRAY_ITEM(&clients, i);
1.10 nicm 1066: if (c == NULL || c->session != s)
1067: continue;
1068: if (c->session->curw->window != w)
1069: continue;
1070: if (!visual) {
1.1 nicm 1071: tty_putcode(&c->tty, TTYC_BEL);
1.10 nicm 1072: continue;
1073: }
1074: status_message_set(c, "Bell in current window");
1.1 nicm 1075: }
1076: break;
1077: }
1078: return (1);
1079: }
1080:
1081: int
1082: server_check_window_activity(struct session *s, struct window *w)
1083: {
1.10 nicm 1084: struct client *c;
1085: u_int i;
1086:
1.1 nicm 1087: if (!(w->flags & WINDOW_ACTIVITY))
1088: return (0);
1.10 nicm 1089:
1.1 nicm 1090: if (!options_get_number(&w->options, "monitor-activity"))
1091: return (0);
1.10 nicm 1092:
1.1 nicm 1093: if (session_alert_has_window(s, w, WINDOW_ACTIVITY))
1094: return (0);
1.10 nicm 1095: if (s->curw->window == w)
1096: return (0);
1097:
1.1 nicm 1098: session_alert_add(s, w, WINDOW_ACTIVITY);
1.10 nicm 1099: if (s->flags & SESSION_UNATTACHED)
1100: return (0);
1101: if (options_get_number(&s->options, "visual-activity")) {
1102: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1103: c = ARRAY_ITEM(&clients, i);
1104: if (c == NULL || c->session != s)
1105: continue;
1106: status_message_set(c, "Activity in window %u",
1107: winlink_find_by_window(&s->windows, w)->idx);
1108: }
1109: }
1110:
1.1 nicm 1111: return (1);
1112: }
1113:
1114: int
1115: server_check_window_content(
1116: struct session *s, struct window *w, struct window_pane *wp)
1117: {
1.10 nicm 1118: struct client *c;
1119: u_int i;
1120: char *found, *ptr;
1121:
1122: if (!(w->flags & WINDOW_ACTIVITY)) /* activity for new content */
1123: return (0);
1.1 nicm 1124:
1.10 nicm 1125: ptr = options_get_string(&w->options, "monitor-content");
1126: if (ptr == NULL || *ptr == '\0')
1.1 nicm 1127: return (0);
1.10 nicm 1128:
1129: if (session_alert_has_window(s, w, WINDOW_CONTENT))
1.1 nicm 1130: return (0);
1.10 nicm 1131: if (s->curw->window == w)
1.1 nicm 1132: return (0);
1.10 nicm 1133:
1.3 nicm 1134: if ((found = window_pane_search(wp, ptr, NULL)) == NULL)
1.1 nicm 1135: return (0);
1.10 nicm 1136: xfree(found);
1137:
1.1 nicm 1138: session_alert_add(s, w, WINDOW_CONTENT);
1.10 nicm 1139: if (s->flags & SESSION_UNATTACHED)
1140: return (0);
1141: if (options_get_number(&s->options, "visual-content")) {
1142: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1143: c = ARRAY_ITEM(&clients, i);
1144: if (c == NULL || c->session != s)
1145: continue;
1146: status_message_set(c, "Content in window %u",
1147: winlink_find_by_window(&s->windows, w)->idx);
1148: }
1149: }
1150:
1.1 nicm 1151: return (1);
1152: }
1153:
1.2 nicm 1154: /* Check if window still exists. */
1.1 nicm 1155: void
1156: server_check_window(struct window *w)
1157: {
1158: struct window_pane *wp, *wq;
1.22 nicm 1159: struct options *oo = &w->options;
1.1 nicm 1160: struct session *s;
1161: struct winlink *wl;
1.35 nicm 1162: u_int i;
1.22 nicm 1163: int destroyed;
1.1 nicm 1164:
1165: destroyed = 1;
1166:
1167: wp = TAILQ_FIRST(&w->panes);
1168: while (wp != NULL) {
1169: wq = TAILQ_NEXT(wp, entry);
1.2 nicm 1170: /*
1171: * If the pane has died and the remain-on-exit flag is not set,
1172: * remove the pane; otherwise, if the flag is set, don't allow
1173: * the window to be destroyed (or it'll close when the last
1174: * pane dies).
1175: */
1.23 nicm 1176: if (wp->fd == -1 && !options_get_number(oo, "remain-on-exit")) {
1.11 nicm 1177: layout_close_pane(wp);
1.1 nicm 1178: window_remove_pane(w, wp);
1179: server_redraw_window(w);
1.2 nicm 1180: } else
1181: destroyed = 0;
1.1 nicm 1182: wp = wq;
1183: }
1184:
1185: if (!destroyed)
1186: return;
1187:
1188: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
1189: s = ARRAY_ITEM(&sessions, i);
1190: if (s == NULL)
1191: continue;
1192: if (!session_has(s, w))
1193: continue;
1194:
1195: restart:
1196: /* Detach window and either redraw or kill clients. */
1197: RB_FOREACH(wl, winlinks, &s->windows) {
1198: if (wl->window != w)
1199: continue;
1.34 nicm 1200: if (session_detach(s, wl)) {
1201: server_destroy_session(s);
1202: break;
1.1 nicm 1203: }
1.34 nicm 1204: server_redraw_session(s);
1.1 nicm 1205: goto restart;
1206: }
1207: }
1208:
1209: recalculate_sizes();
1210: }
1211:
1212: /* Call any once-per-second timers. */
1213: void
1214: server_second_timers(void)
1215: {
1216: struct window *w;
1.28 nicm 1217: struct client *c;
1.1 nicm 1218: struct window_pane *wp;
1219: u_int i;
1220: int xtimeout;
1221: struct tm now, then;
1222: static time_t last_t = 0;
1223: time_t t;
1224:
1225: t = time(NULL);
1.28 nicm 1226:
1.6 nicm 1227: xtimeout = options_get_number(&global_s_options, "lock-after-time");
1.1 nicm 1228: if (xtimeout > 0 && t > server_activity + xtimeout)
1229: server_lock();
1230:
1231: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
1232: w = ARRAY_ITEM(&windows, i);
1233: if (w == NULL)
1234: continue;
1235:
1236: TAILQ_FOREACH(wp, &w->panes, entry) {
1237: if (wp->mode != NULL && wp->mode->timer != NULL)
1238: wp->mode->timer(wp);
1.28 nicm 1239: }
1240: }
1241:
1.29 nicm 1242: if (password_backoff != 0 && t >= password_backoff) {
1.28 nicm 1243: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1244: if ((c = ARRAY_ITEM(&clients, i)) != NULL)
1245: server_redraw_client(c);
1.1 nicm 1246: }
1.29 nicm 1247: password_backoff = 0;
1.1 nicm 1248: }
1249:
1250: /* Check for a minute having passed. */
1251: gmtime_r(&t, &now);
1252: gmtime_r(&last_t, &then);
1253: if (now.tm_min == then.tm_min)
1254: return;
1255: last_t = t;
1256:
1257: /* If locked, redraw all clients. */
1258: if (server_locked) {
1259: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1.30 kili 1260: if ((c = ARRAY_ITEM(&clients, i)) != NULL)
1261: server_redraw_client(c);
1.1 nicm 1262: }
1263: }
1264: }
1265:
1266: /* Update socket execute permissions based on whether sessions are attached. */
1267: int
1268: server_update_socket(void)
1269: {
1270: struct session *s;
1271: u_int i;
1272: static int last = -1;
1273: int n;
1274:
1275: n = 0;
1276: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
1277: s = ARRAY_ITEM(&sessions, i);
1278: if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
1279: n++;
1280: break;
1281: }
1282: }
1283:
1284: if (n != last) {
1285: last = n;
1286: if (n != 0)
1287: chmod(socket_path, S_IRWXU);
1288: else
1289: chmod(socket_path, S_IRUSR|S_IWUSR);
1290: }
1291:
1292: return (n);
1293: }