Annotation of src/usr.bin/tmux/server.c, Revision 1.158
1.158 ! nicm 1: /* $OpenBSD: server.c,v 1.157 2016/01/19 15:59:12 nicm Exp $ */
1.1 nicm 2:
3: /*
1.157 nicm 4: * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 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>
1.66 nicm 27: #include <event.h>
1.1 nicm 28: #include <fcntl.h>
1.5 nicm 29: #include <paths.h>
1.1 nicm 30: #include <signal.h>
31: #include <stdio.h>
32: #include <stdlib.h>
33: #include <string.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:
1.155 nicm 44: struct clients clients;
1.1 nicm 45:
1.155 nicm 46: struct tmuxproc *server_proc;
47: int server_fd;
48: int server_exit;
49: struct event server_ev_accept;
50:
51: struct cmd_find_state marked_pane;
1.126 nicm 52:
53: int server_create_socket(void);
1.144 nicm 54: int server_loop(void);
1.141 nicm 55: int server_should_exit(void);
56: void server_send_exit(void);
1.144 nicm 57: void server_accept(int, short, void *);
58: void server_signal(int);
1.126 nicm 59: void server_child_signal(void);
60: void server_child_exited(pid_t, int);
61: void server_child_stopped(pid_t, int);
62:
63: /* Set marked pane. */
64: void
65: server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
66: {
1.155 nicm 67: cmd_find_clear_state(&marked_pane, NULL, 0);
68: marked_pane.s = s;
69: marked_pane.wl = wl;
70: marked_pane.w = wl->window;
71: marked_pane.wp = wp;
1.126 nicm 72: }
73:
74: /* Clear marked pane. */
75: void
76: server_clear_marked(void)
77: {
1.155 nicm 78: cmd_find_clear_state(&marked_pane, NULL, 0);
1.126 nicm 79: }
80:
81: /* Is this the marked pane? */
82: int
83: server_is_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
84: {
85: if (s == NULL || wl == NULL || wp == NULL)
86: return (0);
1.155 nicm 87: if (marked_pane.s != s || marked_pane.wl != wl)
1.126 nicm 88: return (0);
1.155 nicm 89: if (marked_pane.wp != wp)
1.126 nicm 90: return (0);
91: return (server_check_marked());
92: }
93:
94: /* Check if the marked pane is still valid. */
95: int
96: server_check_marked(void)
97: {
1.155 nicm 98: return (cmd_find_valid_state(&marked_pane));
1.126 nicm 99: }
1.45 nicm 100:
1.60 nicm 101: /* Create server socket. */
102: int
103: server_create_socket(void)
1.1 nicm 104: {
1.60 nicm 105: struct sockaddr_un sa;
106: size_t size;
107: mode_t mask;
1.100 nicm 108: int fd;
1.60 nicm 109:
110: memset(&sa, 0, sizeof sa);
111: sa.sun_family = AF_UNIX;
112: size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
113: if (size >= sizeof sa.sun_path) {
114: errno = ENAMETOOLONG;
1.119 nicm 115: return (-1);
1.60 nicm 116: }
117: unlink(sa.sun_path);
118:
119: if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
1.119 nicm 120: return (-1);
1.60 nicm 121:
1.89 nicm 122: mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
1.140 guenther 123: if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1)
1.119 nicm 124: return (-1);
1.60 nicm 125: umask(mask);
126:
1.158 ! nicm 127: if (listen(fd, 128) == -1)
1.119 nicm 128: return (-1);
1.100 nicm 129: setblocking(fd, 0);
1.1 nicm 130:
1.60 nicm 131: return (fd);
132: }
133:
1.1 nicm 134: /* Fork new server. */
135: int
1.138 nicm 136: server_start(struct event_base *base, int lockfd, char *lockfile)
1.1 nicm 137: {
1.139 nicm 138: int pair[2];
1.1 nicm 139:
140: if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
141: fatal("socketpair failed");
142:
1.144 nicm 143: server_proc = proc_start("server", base, 1, server_signal);
144: if (server_proc == NULL) {
1.1 nicm 145: close(pair[1]);
146: return (pair[0]);
147: }
148: close(pair[0]);
1.143 nicm 149:
1.152 nicm 150: if (log_get_level() > 3)
1.146 nicm 151: tty_create_log();
1.151 nicm 152: if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
153: "tty ps", NULL) != 0)
1.143 nicm 154: fatal("pledge failed");
1.1 nicm 155:
1.121 nicm 156: RB_INIT(&windows);
1.102 nicm 157: RB_INIT(&all_window_panes);
1.122 nicm 158: TAILQ_INIT(&clients);
1.97 nicm 159: RB_INIT(&sessions);
1.47 nicm 160: TAILQ_INIT(&session_groups);
1.15 nicm 161: mode_key_init_trees();
1.1 nicm 162: key_bindings_init();
163:
1.153 nicm 164: gettimeofday(&start_time, NULL);
1.16 nicm 165:
1.66 nicm 166: server_fd = server_create_socket();
1.119 nicm 167: if (server_fd == -1)
168: fatal("couldn't create socket");
169: server_update_socket();
1.60 nicm 170: server_client_create(pair[1]);
1.103 nicm 171:
1.154 nicm 172: if (lockfd >= 0) {
173: unlink(lockfile);
174: free(lockfile);
175: close(lockfd);
176: }
1.16 nicm 177:
1.139 nicm 178: start_cfg();
179:
1.129 nicm 180: status_prompt_load_history();
1.66 nicm 181:
1.104 nicm 182: server_add_accept(0);
1.66 nicm 183:
1.144 nicm 184: proc_loop(server_proc, server_loop);
1.129 nicm 185: status_prompt_save_history();
1.66 nicm 186: exit(0);
1.1 nicm 187: }
188:
1.144 nicm 189: /* Server loop callback. */
190: int
1.66 nicm 191: server_loop(void)
1.1 nicm 192: {
1.144 nicm 193: struct client *c;
1.31 nicm 194:
1.144 nicm 195: server_client_loop();
1.1 nicm 196:
1.145 nicm 197: if (!options_get_number(global_options, "exit-unattached")) {
1.97 nicm 198: if (!RB_EMPTY(&sessions))
199: return (0);
1.1 nicm 200: }
1.116 nicm 201:
1.122 nicm 202: TAILQ_FOREACH(c, &clients, entry) {
203: if (c->session != NULL)
1.116 nicm 204: return (0);
205: }
206:
207: /*
208: * No attached clients therefore want to exit - flush any waiting
209: * clients but don't actually exit until they've gone.
210: */
211: cmd_wait_for_flush();
1.122 nicm 212: if (!TAILQ_EMPTY(&clients))
213: return (0);
1.116 nicm 214:
1.66 nicm 215: return (1);
1.1 nicm 216: }
217:
1.141 nicm 218: /* Exit the server by killing all clients and windows. */
1.1 nicm 219: void
1.141 nicm 220: server_send_exit(void)
1.1 nicm 221: {
1.122 nicm 222: struct client *c, *c1;
223: struct session *s, *s1;
1.116 nicm 224:
225: cmd_wait_for_flush();
1.1 nicm 226:
1.122 nicm 227: TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
1.144 nicm 228: if (c->flags & CLIENT_SUSPENDED)
1.122 nicm 229: server_client_lost(c);
230: else
1.144 nicm 231: proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
1.122 nicm 232: c->session = NULL;
1.42 nicm 233: }
234:
1.122 nicm 235: RB_FOREACH_SAFE(s, sessions, &sessions, s1)
1.97 nicm 236: session_destroy(s);
1.66 nicm 237: }
238:
239: /* Update socket execute permissions based on whether sessions are attached. */
1.75 nicm 240: void
1.66 nicm 241: server_update_socket(void)
1.42 nicm 242: {
1.66 nicm 243: struct session *s;
244: static int last = -1;
1.93 nicm 245: int n, mode;
246: struct stat sb;
1.1 nicm 247:
1.66 nicm 248: n = 0;
1.97 nicm 249: RB_FOREACH(s, sessions, &sessions) {
250: if (!(s->flags & SESSION_UNATTACHED)) {
1.66 nicm 251: n++;
252: break;
253: }
254: }
255:
256: if (n != last) {
257: last = n;
1.93 nicm 258:
259: if (stat(socket_path, &sb) != 0)
260: return;
261: mode = sb.st_mode;
262: if (n != 0) {
263: if (mode & S_IRUSR)
264: mode |= S_IXUSR;
265: if (mode & S_IRGRP)
266: mode |= S_IXGRP;
267: if (mode & S_IROTH)
268: mode |= S_IXOTH;
269: } else
270: mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
271: chmod(socket_path, mode);
1.66 nicm 272: }
273: }
274:
275: /* Callback for server socket. */
276: void
1.150 nicm 277: server_accept(int fd, short events, __unused void *data)
1.66 nicm 278: {
279: struct sockaddr_storage sa;
280: socklen_t slen = sizeof sa;
281: int newfd;
282:
1.104 nicm 283: server_add_accept(0);
1.66 nicm 284: if (!(events & EV_READ))
285: return;
286:
287: newfd = accept(fd, (struct sockaddr *) &sa, &slen);
288: if (newfd == -1) {
289: if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
290: return;
1.104 nicm 291: if (errno == ENFILE || errno == EMFILE) {
292: /* Delete and don't try again for 1 second. */
293: server_add_accept(1);
294: return;
295: }
1.66 nicm 296: fatal("accept failed");
297: }
1.141 nicm 298: if (server_exit) {
1.66 nicm 299: close(newfd);
300: return;
1.42 nicm 301: }
1.66 nicm 302: server_client_create(newfd);
303: }
304:
1.104 nicm 305: /*
306: * Add accept event. If timeout is nonzero, add as a timeout instead of a read
307: * event - used to backoff when running out of file descriptors.
308: */
309: void
310: server_add_accept(int timeout)
311: {
312: struct timeval tv = { timeout, 0 };
313:
314: if (event_initialized(&server_ev_accept))
315: event_del(&server_ev_accept);
316:
317: if (timeout == 0) {
1.144 nicm 318: event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
319: NULL);
1.104 nicm 320: event_add(&server_ev_accept, NULL);
321: } else {
1.144 nicm 322: event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
323: server_accept, NULL);
1.104 nicm 324: event_add(&server_ev_accept, &tv);
325: }
326: }
327:
1.66 nicm 328: /* Signal handler. */
329: void
1.144 nicm 330: server_signal(int sig)
1.66 nicm 331: {
1.119 nicm 332: int fd;
1.120 nicm 333:
1.66 nicm 334: switch (sig) {
335: case SIGTERM:
1.141 nicm 336: server_exit = 1;
337: server_send_exit();
1.66 nicm 338: break;
339: case SIGCHLD:
340: server_child_signal();
341: break;
342: case SIGUSR1:
343: event_del(&server_ev_accept);
1.119 nicm 344: fd = server_create_socket();
345: if (fd != -1) {
346: close(server_fd);
347: server_fd = fd;
348: server_update_socket();
349: }
1.104 nicm 350: server_add_accept(0);
1.66 nicm 351: break;
1.1 nicm 352: }
353: }
354:
355: /* Handle SIGCHLD. */
356: void
357: server_child_signal(void)
358: {
1.66 nicm 359: int status;
360: pid_t pid;
1.1 nicm 361:
362: for (;;) {
363: switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
364: case -1:
365: if (errno == ECHILD)
366: return;
1.39 nicm 367: fatal("waitpid failed");
1.1 nicm 368: case 0:
369: return;
370: }
1.66 nicm 371: if (WIFSTOPPED(status))
372: server_child_stopped(pid, status);
1.79 nicm 373: else if (WIFEXITED(status) || WIFSIGNALED(status))
1.66 nicm 374: server_child_exited(pid, status);
375: }
376: }
377:
378: /* Handle exited children. */
379: void
380: server_child_exited(pid_t pid, int status)
381: {
1.121 nicm 382: struct window *w, *w1;
1.66 nicm 383: struct window_pane *wp;
384: struct job *job;
385:
1.121 nicm 386: RB_FOREACH_SAFE(w, windows, &windows, w1) {
1.66 nicm 387: TAILQ_FOREACH(wp, &w->panes, entry) {
388: if (wp->pid == pid) {
1.118 nicm 389: wp->status = status;
1.156 nicm 390: server_destroy_pane(wp, 1);
1.77 nicm 391: break;
1.53 nicm 392: }
393: }
1.80 nicm 394: }
1.1 nicm 395:
1.101 nicm 396: LIST_FOREACH(job, &all_jobs, lentry) {
1.66 nicm 397: if (pid == job->pid) {
1.67 nicm 398: job_died(job, status); /* might free job */
399: break;
1.1 nicm 400: }
1.53 nicm 401: }
402: }
403:
1.66 nicm 404: /* Handle stopped children. */
1.31 nicm 405: void
1.66 nicm 406: server_child_stopped(pid_t pid, int status)
1.31 nicm 407: {
1.66 nicm 408: struct window *w;
409: struct window_pane *wp;
1.31 nicm 410:
1.66 nicm 411: if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
412: return;
1.31 nicm 413:
1.121 nicm 414: RB_FOREACH(w, windows, &windows) {
1.66 nicm 415: TAILQ_FOREACH(wp, &w->panes, entry) {
416: if (wp->pid == pid) {
417: if (killpg(pid, SIGCONT) != 0)
418: kill(pid, SIGCONT);
419: }
1.1 nicm 420: }
421: }
422: }