xref: /openbsd-src/usr.bin/tmux/server.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /* $OpenBSD: server.c,v 1.159 2016/07/07 09:24:09 semarie Exp $ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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 <event.h>
28 #include <fcntl.h>
29 #include <paths.h>
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 
44 struct clients		 clients;
45 
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;
52 
53 int	server_create_socket(void);
54 int	server_loop(void);
55 int	server_should_exit(void);
56 void	server_send_exit(void);
57 void	server_accept(int, short, void *);
58 void	server_signal(int);
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 {
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;
72 }
73 
74 /* Clear marked pane. */
75 void
76 server_clear_marked(void)
77 {
78 	cmd_find_clear_state(&marked_pane, NULL, 0);
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);
87 	if (marked_pane.s != s || marked_pane.wl != wl)
88 		return (0);
89 	if (marked_pane.wp != wp)
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 {
98 	return (cmd_find_valid_state(&marked_pane));
99 }
100 
101 /* Create server socket. */
102 int
103 server_create_socket(void)
104 {
105 	struct sockaddr_un	sa;
106 	size_t			size;
107 	mode_t			mask;
108 	int			fd;
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;
115 		return (-1);
116 	}
117 	unlink(sa.sun_path);
118 
119 	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
120 		return (-1);
121 
122 	mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
123 	if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1)
124 		return (-1);
125 	umask(mask);
126 
127 	if (listen(fd, 128) == -1)
128 		return (-1);
129 	setblocking(fd, 0);
130 
131 	return (fd);
132 }
133 
134 /* Fork new server. */
135 int
136 server_start(struct event_base *base, int lockfd, char *lockfile)
137 {
138 	int	pair[2];
139 
140 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
141 		fatal("socketpair failed");
142 
143 	server_proc = proc_start("server", base, 1, server_signal);
144 	if (server_proc == NULL) {
145 		close(pair[1]);
146 		return (pair[0]);
147 	}
148 	close(pair[0]);
149 
150 	if (log_get_level() > 3)
151 		tty_create_log();
152 	if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
153 	    "tty ps", NULL) != 0)
154 		fatal("pledge failed");
155 
156 	RB_INIT(&windows);
157 	RB_INIT(&all_window_panes);
158 	TAILQ_INIT(&clients);
159 	RB_INIT(&sessions);
160 	TAILQ_INIT(&session_groups);
161 	mode_key_init_trees();
162 	key_bindings_init();
163 
164 	gettimeofday(&start_time, NULL);
165 
166 	server_fd = server_create_socket();
167 	if (server_fd == -1)
168 		fatal("couldn't create socket");
169 	server_update_socket();
170 	server_client_create(pair[1]);
171 
172 	if (lockfd >= 0) {
173 		unlink(lockfile);
174 		free(lockfile);
175 		close(lockfd);
176 	}
177 
178 	start_cfg();
179 
180 	status_prompt_load_history();
181 
182 	server_add_accept(0);
183 
184 	proc_loop(server_proc, server_loop);
185 	status_prompt_save_history();
186 	exit(0);
187 }
188 
189 /* Server loop callback. */
190 int
191 server_loop(void)
192 {
193 	struct client	*c;
194 
195 	server_client_loop();
196 
197 	if (!options_get_number(global_options, "exit-unattached")) {
198 		if (!RB_EMPTY(&sessions))
199 			return (0);
200 	}
201 
202 	TAILQ_FOREACH(c, &clients, entry) {
203 		if (c->session != NULL)
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();
212 	if (!TAILQ_EMPTY(&clients))
213 		return (0);
214 
215 	return (1);
216 }
217 
218 /* Exit the server by killing all clients and windows. */
219 void
220 server_send_exit(void)
221 {
222 	struct client	*c, *c1;
223 	struct session	*s, *s1;
224 
225 	cmd_wait_for_flush();
226 
227 	TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
228 		if (c->flags & CLIENT_SUSPENDED)
229 			server_client_lost(c);
230 		else
231 			proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
232 		c->session = NULL;
233 	}
234 
235 	RB_FOREACH_SAFE(s, sessions, &sessions, s1)
236 		session_destroy(s);
237 }
238 
239 /* Update socket execute permissions based on whether sessions are attached. */
240 void
241 server_update_socket(void)
242 {
243 	struct session	*s;
244 	static int	 last = -1;
245 	int		 n, mode;
246 	struct stat      sb;
247 
248 	n = 0;
249 	RB_FOREACH(s, sessions, &sessions) {
250 		if (!(s->flags & SESSION_UNATTACHED)) {
251 			n++;
252 			break;
253 		}
254 	}
255 
256 	if (n != last) {
257 		last = n;
258 
259 		if (stat(socket_path, &sb) != 0)
260 			return;
261 		mode = sb.st_mode & ACCESSPERMS;
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);
272 	}
273 }
274 
275 /* Callback for server socket. */
276 void
277 server_accept(int fd, short events, __unused void *data)
278 {
279 	struct sockaddr_storage	sa;
280 	socklen_t		slen = sizeof sa;
281 	int			newfd;
282 
283 	server_add_accept(0);
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;
291 		if (errno == ENFILE || errno == EMFILE) {
292 			/* Delete and don't try again for 1 second. */
293 			server_add_accept(1);
294 			return;
295 		}
296 		fatal("accept failed");
297 	}
298 	if (server_exit) {
299 		close(newfd);
300 		return;
301 	}
302 	server_client_create(newfd);
303 }
304 
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) {
318 		event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
319 		    NULL);
320 		event_add(&server_ev_accept, NULL);
321 	} else {
322 		event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
323 		    server_accept, NULL);
324 		event_add(&server_ev_accept, &tv);
325 	}
326 }
327 
328 /* Signal handler. */
329 void
330 server_signal(int sig)
331 {
332 	int	fd;
333 
334 	switch (sig) {
335 	case SIGTERM:
336 		server_exit = 1;
337 		server_send_exit();
338 		break;
339 	case SIGCHLD:
340 		server_child_signal();
341 		break;
342 	case SIGUSR1:
343 		event_del(&server_ev_accept);
344 		fd = server_create_socket();
345 		if (fd != -1) {
346 			close(server_fd);
347 			server_fd = fd;
348 			server_update_socket();
349 		}
350 		server_add_accept(0);
351 		break;
352 	}
353 }
354 
355 /* Handle SIGCHLD. */
356 void
357 server_child_signal(void)
358 {
359 	int	 status;
360 	pid_t	 pid;
361 
362 	for (;;) {
363 		switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
364 		case -1:
365 			if (errno == ECHILD)
366 				return;
367 			fatal("waitpid failed");
368 		case 0:
369 			return;
370 		}
371 		if (WIFSTOPPED(status))
372 			server_child_stopped(pid, status);
373 		else if (WIFEXITED(status) || WIFSIGNALED(status))
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 {
382 	struct window		*w, *w1;
383 	struct window_pane	*wp;
384 	struct job		*job;
385 
386 	RB_FOREACH_SAFE(w, windows, &windows, w1) {
387 		TAILQ_FOREACH(wp, &w->panes, entry) {
388 			if (wp->pid == pid) {
389 				wp->status = status;
390 				server_destroy_pane(wp, 1);
391 				break;
392 			}
393 		}
394 	}
395 
396 	LIST_FOREACH(job, &all_jobs, lentry) {
397 		if (pid == job->pid) {
398 			job_died(job, status);	/* might free job */
399 			break;
400 		}
401 	}
402 }
403 
404 /* Handle stopped children. */
405 void
406 server_child_stopped(pid_t pid, int status)
407 {
408 	struct window		*w;
409 	struct window_pane	*wp;
410 
411 	if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
412 		return;
413 
414 	RB_FOREACH(w, windows, &windows) {
415 		TAILQ_FOREACH(wp, &w->panes, entry) {
416 			if (wp->pid == pid) {
417 				if (killpg(pid, SIGCONT) != 0)
418 					kill(pid, SIGCONT);
419 			}
420 		}
421 	}
422 }
423