Annotation of src/usr.bin/tmux/server.c, Revision 1.64
1.64 ! nicm 1: /* $OpenBSD: server.c,v 1.63 2009/10/27 13:03:33 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.45 nicm 48: /* Mapping of a pollfd to an fd independent of its position in the array. */
49: struct poll_item {
1.60 nicm 50: int fd;
51: int events;
52:
53: void (*fn)(int, int, void *);
54: void *data;
1.45 nicm 55:
56: RB_ENTRY(poll_item) entry;
57: };
58: RB_HEAD(poll_items, poll_item) poll_items;
59:
60: int server_poll_cmp(struct poll_item *, struct poll_item *);
1.60 nicm 61: struct poll_item*server_poll_lookup(int);
1.45 nicm 62: struct pollfd *server_poll_flatten(int *);
1.60 nicm 63: void server_poll_dispatch(struct pollfd *, int);
1.45 nicm 64: void server_poll_reset(void);
65: RB_PROTOTYPE(poll_items, poll_item, entry, server_poll_cmp);
66: RB_GENERATE(poll_items, poll_item, entry, server_poll_cmp);
67:
1.1 nicm 68: int server_create_socket(void);
1.60 nicm 69: void server_callback(int, int, void *);
1.1 nicm 70: int server_main(int);
71: void server_shutdown(void);
1.42 nicm 72: int server_should_shutdown(void);
1.1 nicm 73: void server_child_signal(void);
1.31 nicm 74: void server_clean_dead(void);
1.60 nicm 75: void server_second_timers(void);
1.46 nicm 76: void server_lock_server(void);
77: void server_lock_sessions(void);
1.1 nicm 78: int server_update_socket(void);
79:
1.45 nicm 80: int
81: server_poll_cmp(struct poll_item *pitem1, struct poll_item *pitem2)
82: {
1.60 nicm 83: return (pitem1->fd - pitem2->fd);
1.45 nicm 84: }
85:
1.60 nicm 86: void
87: server_poll_add(int fd, int events, void (*fn)(int, int, void *), void *data)
1.45 nicm 88: {
1.60 nicm 89: struct poll_item *pitem;
90:
91: pitem = xmalloc(sizeof *pitem);
92: pitem->fd = fd;
93: pitem->events = events;
94:
95: pitem->fn = fn;
96: pitem->data = data;
1.45 nicm 97:
1.60 nicm 98: RB_INSERT(poll_items, &poll_items, pitem);
1.45 nicm 99: }
100:
1.60 nicm 101: struct poll_item *
102: server_poll_lookup(int fd)
1.45 nicm 103: {
1.60 nicm 104: struct poll_item pitem;
1.45 nicm 105:
1.60 nicm 106: pitem.fd = fd;
107: return (RB_FIND(poll_items, &poll_items, &pitem));
1.45 nicm 108: }
109:
110: struct pollfd *
111: server_poll_flatten(int *nfds)
112: {
113: struct poll_item *pitem;
114: struct pollfd *pfds;
115:
116: pfds = NULL;
117: *nfds = 0;
118: RB_FOREACH(pitem, poll_items, &poll_items) {
119: pfds = xrealloc(pfds, (*nfds) + 1, sizeof *pfds);
1.60 nicm 120: pfds[*nfds].fd = pitem->fd;
121: pfds[*nfds].events = pitem->events;
1.45 nicm 122: (*nfds)++;
123: }
124: return (pfds);
125: }
126:
127: void
1.60 nicm 128: server_poll_dispatch(struct pollfd *pfds, int nfds)
1.45 nicm 129: {
130: struct poll_item *pitem;
1.60 nicm 131: struct pollfd *pfd;
1.45 nicm 132:
1.60 nicm 133: while (nfds > 0) {
134: pfd = &pfds[--nfds];
135: if (pfd->revents != 0) {
136: pitem = server_poll_lookup(pfd->fd);
137: pitem->fn(pitem->fd, pfd->revents, pitem->data);
138: }
1.45 nicm 139: }
140: xfree(pfds);
141: }
142:
143: void
144: server_poll_reset(void)
145: {
146: struct poll_item *pitem;
147:
148: while (!RB_EMPTY(&poll_items)) {
149: pitem = RB_ROOT(&poll_items);
150: RB_REMOVE(poll_items, &poll_items, pitem);
151: xfree(pitem);
152: }
153: }
154:
1.60 nicm 155: /* Create server socket. */
156: int
157: server_create_socket(void)
1.1 nicm 158: {
1.60 nicm 159: struct sockaddr_un sa;
160: size_t size;
161: mode_t mask;
162: int fd, mode;
163:
164: memset(&sa, 0, sizeof sa);
165: sa.sun_family = AF_UNIX;
166: size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
167: if (size >= sizeof sa.sun_path) {
168: errno = ENAMETOOLONG;
169: fatal("socket failed");
170: }
171: unlink(sa.sun_path);
172:
173: if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
174: fatal("socket failed");
175:
176: mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
177: if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
178: fatal("bind failed");
179: umask(mask);
180:
181: if (listen(fd, 16) == -1)
182: fatal("listen failed");
1.1 nicm 183:
184: if ((mode = fcntl(fd, F_GETFL)) == -1)
185: fatal("fcntl failed");
186: if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
187: fatal("fcntl failed");
188: if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
189: fatal("fcntl failed");
190:
1.60 nicm 191: return (fd);
192: }
193:
194: /* Callback for server socket. */
195: void
196: server_callback(int fd, int events, unused void *data)
197: {
198: struct sockaddr_storage sa;
199: socklen_t slen = sizeof sa;
200: int newfd;
201:
202: if (events & (POLLERR|POLLNVAL|POLLHUP))
203: fatalx("lost server socket");
204: if (!(events & POLLIN))
205: return;
1.1 nicm 206:
1.60 nicm 207: newfd = accept(fd, (struct sockaddr *) &sa, &slen);
208: if (newfd == -1) {
209: if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
1.13 nicm 210: return;
1.60 nicm 211: fatal("accept failed");
212: }
213: if (sigterm) {
214: close(newfd);
215: return;
1.1 nicm 216: }
1.60 nicm 217: server_client_create(newfd);
1.1 nicm 218: }
219:
220: /* Fork new server. */
221: int
222: server_start(char *path)
223: {
1.16 nicm 224: struct client *c;
225: int pair[2], srv_fd;
226: char *cause;
227: char rpathbuf[MAXPATHLEN];
1.1 nicm 228:
229: /* The first client is special and gets a socketpair; create it. */
230: if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
231: fatal("socketpair failed");
232:
233: switch (fork()) {
234: case -1:
235: fatal("fork failed");
236: case 0:
237: break;
238: default:
239: close(pair[1]);
240: return (pair[0]);
241: }
242: close(pair[0]);
243:
244: /*
245: * Must daemonise before loading configuration as the PID changes so
246: * $TMUX would be wrong for sessions created in the config file.
247: */
1.16 nicm 248: if (daemon(1, 0) != 0)
1.1 nicm 249: fatal("daemon failed");
250:
1.16 nicm 251: logfile("server");
252: log_debug("server started, pid %ld", (long) getpid());
253:
1.1 nicm 254: ARRAY_INIT(&windows);
255: ARRAY_INIT(&clients);
1.31 nicm 256: ARRAY_INIT(&dead_clients);
1.1 nicm 257: ARRAY_INIT(&sessions);
1.31 nicm 258: ARRAY_INIT(&dead_sessions);
1.47 nicm 259: TAILQ_INIT(&session_groups);
1.15 nicm 260: mode_key_init_trees();
1.1 nicm 261: key_bindings_init();
262: utf8_build();
263:
264: start_time = time(NULL);
265: socket_path = path;
266:
1.16 nicm 267: if (realpath(socket_path, rpathbuf) == NULL)
268: strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
269: log_debug("socket path %s", socket_path);
270: setproctitle("server (%s)", rpathbuf);
271:
272: srv_fd = server_create_socket();
1.60 nicm 273: server_client_create(pair[1]);
1.16 nicm 274:
1.64 ! nicm 275: if (access(SYSTEM_CFG, R_OK) == 0) {
! 276: if (load_cfg(SYSTEM_CFG, NULL, &cause) != 0)
1.16 nicm 277: goto error;
1.64 ! nicm 278: } else if (errno != ENOENT) {
! 279: xasprintf(&cause, "%s: %s", strerror(errno), SYSTEM_CFG);
1.16 nicm 280: goto error;
1.64 ! nicm 281: }
1.24 nicm 282: if (cfg_file != NULL && load_cfg(cfg_file, NULL, &cause) != 0)
1.16 nicm 283: goto error;
1.5 nicm 284:
1.16 nicm 285: exit(server_main(srv_fd));
1.1 nicm 286:
1.16 nicm 287: error:
288: /* Write the error and shutdown the server. */
289: c = ARRAY_FIRST(&clients);
1.1 nicm 290:
1.16 nicm 291: server_write_error(c, cause);
292: xfree(cause);
1.1 nicm 293:
1.27 nicm 294: sigterm = 1;
1.16 nicm 295: server_shutdown();
1.1 nicm 296:
297: exit(server_main(srv_fd));
298: }
299:
300: /* Main server loop. */
301: int
302: server_main(int srv_fd)
303: {
1.60 nicm 304: struct pollfd *pfds;
1.1 nicm 305: int nfds, xtimeout;
1.42 nicm 306: u_int i;
1.1 nicm 307: time_t now, last;
308:
309: siginit();
1.20 nicm 310: log_debug("server socket is %d", srv_fd);
1.1 nicm 311:
312: last = time(NULL);
313:
314: pfds = NULL;
315: for (;;) {
316: /* If sigterm, kill all windows and clients. */
317: if (sigterm)
318: server_shutdown();
319:
1.42 nicm 320: /* Stop if no sessions or clients left. */
321: if (server_should_shutdown())
322: break;
323:
1.1 nicm 324: /* Handle child exit. */
325: if (sigchld) {
1.61 nicm 326: sigchld = 0;
1.1 nicm 327: server_child_signal();
1.61 nicm 328: continue;
1.1 nicm 329: }
330:
331: /* Recreate socket on SIGUSR1. */
332: if (sigusr1) {
1.61 nicm 333: sigusr1 = 0;
1.1 nicm 334: close(srv_fd);
335: srv_fd = server_create_socket();
1.61 nicm 336: continue;
1.1 nicm 337: }
338:
1.45 nicm 339: /* Initialise pollfd array and add server socket. */
340: server_poll_reset();
1.60 nicm 341: server_poll_add(srv_fd, POLLIN, server_callback, NULL);
1.1 nicm 342:
343: /* Fill window and client sockets. */
1.63 nicm 344: server_job_prepare();
345: server_window_prepare();
346: server_client_prepare();
347:
1.1 nicm 348: /* Update socket permissions. */
349: xtimeout = INFTIM;
1.27 nicm 350: if (server_update_socket() != 0)
1.1 nicm 351: xtimeout = POLL_TIMEOUT;
352:
353: /* Do the poll. */
1.45 nicm 354: pfds = server_poll_flatten(&nfds);
1.4 nicm 355: if (poll(pfds, nfds, xtimeout) == -1) {
1.1 nicm 356: if (errno == EAGAIN || errno == EINTR)
357: continue;
358: fatal("poll failed");
359: }
1.60 nicm 360: server_poll_dispatch(pfds, nfds);
1.1 nicm 361:
362: /* Call second-based timers. */
363: now = time(NULL);
364: if (now != last) {
365: last = now;
366: server_second_timers();
367: }
368:
1.60 nicm 369: /* Run once-per-loop events. */
370: server_job_loop();
371: server_window_loop();
372: server_client_loop();
1.1 nicm 373:
1.8 nicm 374: /* Collect any unset key bindings. */
375: key_bindings_clean();
1.31 nicm 376:
377: /* Collect dead clients and sessions. */
378: server_clean_dead();
1.1 nicm 379: }
1.45 nicm 380: server_poll_reset();
1.1 nicm 381:
382: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
383: if (ARRAY_ITEM(&sessions, i) != NULL)
384: session_destroy(ARRAY_ITEM(&sessions, i));
385: }
386: ARRAY_FREE(&sessions);
387:
388: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
389: if (ARRAY_ITEM(&clients, i) != NULL)
1.60 nicm 390: server_client_lost(ARRAY_ITEM(&clients, i));
1.1 nicm 391: }
392: ARRAY_FREE(&clients);
393:
1.15 nicm 394: mode_key_free_trees();
1.1 nicm 395: key_bindings_free();
396:
397: close(srv_fd);
398:
399: unlink(socket_path);
400: xfree(socket_path);
401:
1.6 nicm 402: options_free(&global_s_options);
403: options_free(&global_w_options);
1.1 nicm 404:
405: return (0);
406: }
407:
408: /* Kill all clients. */
409: void
410: server_shutdown(void)
411: {
412: struct session *s;
413: struct client *c;
414: u_int i, j;
415:
1.42 nicm 416: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
417: c = ARRAY_ITEM(&clients, i);
418: if (c != NULL) {
419: if (c->flags & (CLIENT_BAD|CLIENT_SUSPENDED))
1.60 nicm 420: server_client_lost(c);
1.42 nicm 421: else
422: server_write_client(c, MSG_SHUTDOWN, NULL, 0);
423: }
424: }
425:
1.1 nicm 426: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
427: s = ARRAY_ITEM(&sessions, i);
428: for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
429: c = ARRAY_ITEM(&clients, j);
430: if (c != NULL && c->session == s) {
431: s = NULL;
432: break;
433: }
434: }
435: if (s != NULL)
436: session_destroy(s);
437: }
1.42 nicm 438: }
439:
440: /* Check if the server should be shutting down (no more clients or windows). */
441: int
442: server_should_shutdown(void)
443: {
444: u_int i;
1.1 nicm 445:
1.42 nicm 446: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
447: if (ARRAY_ITEM(&sessions, i) != NULL)
448: return (0);
449: }
1.1 nicm 450: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1.42 nicm 451: if (ARRAY_ITEM(&clients, i) != NULL)
452: return (0);
1.1 nicm 453: }
1.42 nicm 454: return (1);
1.1 nicm 455: }
456:
457: /* Handle SIGCHLD. */
458: void
459: server_child_signal(void)
460: {
461: struct window *w;
462: struct window_pane *wp;
1.53 nicm 463: struct job *job;
1.1 nicm 464: int status;
465: pid_t pid;
466: u_int i;
467:
468: for (;;) {
469: switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
470: case -1:
471: if (errno == ECHILD)
472: return;
1.39 nicm 473: fatal("waitpid failed");
1.1 nicm 474: case 0:
475: return;
476: }
1.53 nicm 477: if (!WIFSTOPPED(status)) {
478: SLIST_FOREACH(job, &all_jobs, lentry) {
479: if (pid == job->pid) {
480: job->pid = -1;
481: job->status = status;
482: }
483: }
1.1 nicm 484: continue;
1.53 nicm 485: }
1.1 nicm 486: if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
487: continue;
488:
489: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
490: w = ARRAY_ITEM(&windows, i);
491: if (w == NULL)
492: continue;
493: TAILQ_FOREACH(wp, &w->panes, entry) {
494: if (wp->pid == pid) {
495: if (killpg(pid, SIGCONT) != 0)
496: kill(pid, SIGCONT);
497: }
498: }
499: }
1.53 nicm 500: }
501: }
502:
1.31 nicm 503: /* Free dead, unreferenced clients and sessions. */
504: void
505: server_clean_dead(void)
506: {
507: struct session *s;
508: struct client *c;
509: u_int i;
510:
511: for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
512: s = ARRAY_ITEM(&dead_sessions, i);
513: if (s == NULL || s->references != 0)
514: continue;
515: ARRAY_SET(&dead_sessions, i, NULL);
516: xfree(s);
517: }
518:
519: for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
520: c = ARRAY_ITEM(&dead_clients, i);
521: if (c == NULL || c->references != 0)
522: continue;
523: ARRAY_SET(&dead_clients, i, NULL);
524: xfree(c);
525: }
1.1 nicm 526: }
527:
1.60 nicm 528: /* Call any once-per-second timers. */
1.1 nicm 529: void
1.60 nicm 530: server_second_timers(void)
1.1 nicm 531: {
1.60 nicm 532: struct window *w;
533: struct window_pane *wp;
1.35 nicm 534: u_int i;
1.1 nicm 535:
1.60 nicm 536: if (options_get_number(&global_s_options, "lock-server"))
537: server_lock_server();
538: else
539: server_lock_sessions();
1.1 nicm 540:
1.60 nicm 541: for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
542: w = ARRAY_ITEM(&windows, i);
543: if (w == NULL)
1.1 nicm 544: continue;
545:
1.60 nicm 546: TAILQ_FOREACH(wp, &w->panes, entry) {
547: if (wp->mode != NULL && wp->mode->timer != NULL)
548: wp->mode->timer(wp);
1.1 nicm 549: }
550: }
551: }
552:
1.46 nicm 553: /* Lock the server if ALL sessions have hit the time limit. */
554: void
555: server_lock_server(void)
556: {
557: struct session *s;
558: u_int i;
559: int timeout;
560: time_t t;
561:
562: t = time(NULL);
563: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
564: if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
565: continue;
566:
1.59 nicm 567: if (s->flags & SESSION_UNATTACHED) {
568: s->activity = time(NULL);
569: continue;
570: }
571:
1.46 nicm 572: timeout = options_get_number(&s->options, "lock-after-time");
573: if (timeout <= 0 || t <= s->activity + timeout)
574: return; /* not timed out */
575: }
576:
577: server_lock();
578: recalculate_sizes();
579: }
580:
581: /* Lock any sessions which have timed out. */
582: void
583: server_lock_sessions(void)
584: {
585: struct session *s;
1.62 deraadt 586: u_int i;
1.46 nicm 587: int timeout;
1.62 deraadt 588: time_t t;
1.46 nicm 589:
1.62 deraadt 590: t = time(NULL);
591: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
1.46 nicm 592: if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
593: continue;
1.59 nicm 594:
595: if (s->flags & SESSION_UNATTACHED) {
596: s->activity = time(NULL);
597: continue;
598: }
1.46 nicm 599:
600: timeout = options_get_number(&s->options, "lock-after-time");
601: if (timeout > 0 && t > s->activity + timeout) {
602: server_lock_session(s);
603: recalculate_sizes();
1.1 nicm 604: }
605: }
606: }
607:
608: /* Update socket execute permissions based on whether sessions are attached. */
609: int
610: server_update_socket(void)
611: {
612: struct session *s;
613: u_int i;
614: static int last = -1;
615: int n;
616:
617: n = 0;
618: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
619: s = ARRAY_ITEM(&sessions, i);
620: if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
621: n++;
622: break;
623: }
624: }
625:
626: if (n != last) {
627: last = n;
628: if (n != 0)
629: chmod(socket_path, S_IRWXU);
630: else
631: chmod(socket_path, S_IRUSR|S_IWUSR);
632: }
633:
634: return (n);
635: }