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