GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tmux/server.c Lines: 10 200 5.0 %
Date: 2017-11-07 Branches: 2 137 1.5 %

Line Branch Exec Source
1
/* $OpenBSD: server.c,v 1.176 2017/07/14 18:49:07 nicm 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
static int		 server_fd;
48
static int		 server_exit;
49
static struct event	 server_ev_accept;
50
51
struct cmd_find_state	 marked_pane;
52
53
static int	server_create_socket(void);
54
static int	server_loop(void);
55
static void	server_send_exit(void);
56
static void	server_accept(int, short, void *);
57
static void	server_signal(int);
58
static void	server_child_signal(void);
59
static void	server_child_exited(pid_t, int);
60
static void	server_child_stopped(pid_t, int);
61
62
/* Set marked pane. */
63
void
64
server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
65
{
66
	cmd_find_clear_state(&marked_pane, 0);
67
	marked_pane.s = s;
68
	marked_pane.wl = wl;
69
	marked_pane.w = wl->window;
70
	marked_pane.wp = wp;
71
}
72
73
/* Clear marked pane. */
74
void
75
server_clear_marked(void)
76
{
77
	cmd_find_clear_state(&marked_pane, 0);
78
}
79
80
/* Is this the marked pane? */
81
int
82
server_is_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
83
{
84
	if (s == NULL || wl == NULL || wp == NULL)
85
		return (0);
86
	if (marked_pane.s != s || marked_pane.wl != wl)
87
		return (0);
88
	if (marked_pane.wp != wp)
89
		return (0);
90
	return (server_check_marked());
91
}
92
93
/* Check if the marked pane is still valid. */
94
int
95
server_check_marked(void)
96
{
97
	return (cmd_find_valid_state(&marked_pane));
98
}
99
100
/* Create server socket. */
101
static int
102
server_create_socket(void)
103
{
104
	struct sockaddr_un	sa;
105
	size_t			size;
106
	mode_t			mask;
107
	int			fd;
108
109
	memset(&sa, 0, sizeof sa);
110
	sa.sun_family = AF_UNIX;
111
	size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
112
	if (size >= sizeof sa.sun_path) {
113
		errno = ENAMETOOLONG;
114
		return (-1);
115
	}
116
	unlink(sa.sun_path);
117
118
	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
119
		return (-1);
120
121
	mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
122
	if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
123
		close(fd);
124
		return (-1);
125
	}
126
	umask(mask);
127
128
	if (listen(fd, 128) == -1) {
129
		close(fd);
130
		return (-1);
131
	}
132
	setblocking(fd, 0);
133
134
	return (fd);
135
}
136
137
/* Fork new server. */
138
int
139
server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
140
    char *lockfile)
141
{
142
4
	int		 pair[2];
143
	struct job	*job;
144
2
	sigset_t	 set, oldset;
145
146
2
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
147
		fatal("socketpair failed");
148
149
2
	sigfillset(&set);
150
2
	sigprocmask(SIG_BLOCK, &set, &oldset);
151
2
	switch (fork()) {
152
	case -1:
153
		fatal("fork failed");
154
	case 0:
155
		break;
156
	default:
157
2
		sigprocmask(SIG_SETMASK, &oldset, NULL);
158
2
		close(pair[1]);
159
4
		return (pair[0]);
160
	}
161
	close(pair[0]);
162
	if (daemon(1, 0) != 0)
163
		fatal("daemon failed");
164
	proc_clear_signals(client, 0);
165
	if (event_reinit(base) != 0)
166
		fatalx("event_reinit failed");
167
	server_proc = proc_start("server");
168
	proc_set_signals(server_proc, server_signal);
169
	sigprocmask(SIG_SETMASK, &oldset, NULL);
170
171
	if (log_get_level() > 1)
172
		tty_create_log();
173
	if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
174
	    "tty ps", NULL) != 0)
175
		fatal("pledge failed");
176
177
	RB_INIT(&windows);
178
	RB_INIT(&all_window_panes);
179
	TAILQ_INIT(&clients);
180
	RB_INIT(&sessions);
181
	RB_INIT(&session_groups);
182
	key_bindings_init();
183
184
	gettimeofday(&start_time, NULL);
185
186
	server_fd = server_create_socket();
187
	if (server_fd == -1)
188
		fatal("couldn't create socket");
189
	server_update_socket();
190
	server_client_create(pair[1]);
191
192
	if (lockfd >= 0) {
193
		unlink(lockfile);
194
		free(lockfile);
195
		close(lockfd);
196
	}
197
198
	start_cfg();
199
200
	server_add_accept(0);
201
202
	proc_loop(server_proc, server_loop);
203
204
	LIST_FOREACH(job, &all_jobs, entry) {
205
		if (job->pid != -1)
206
			kill(job->pid, SIGTERM);
207
	}
208
209
	status_prompt_save_history();
210
	exit(0);
211
2
}
212
213
/* Server loop callback. */
214
static int
215
server_loop(void)
216
{
217
	struct client	*c;
218
	u_int		 items;
219
220
	do {
221
		items = cmdq_next(NULL);
222
		TAILQ_FOREACH(c, &clients, entry) {
223
			if (c->flags & CLIENT_IDENTIFIED)
224
				items += cmdq_next(c);
225
		}
226
	} while (items != 0);
227
228
	server_client_loop();
229
230
	if (!options_get_number(global_options, "exit-unattached")) {
231
		if (!RB_EMPTY(&sessions))
232
			return (0);
233
	}
234
235
	TAILQ_FOREACH(c, &clients, entry) {
236
		if (c->session != NULL)
237
			return (0);
238
	}
239
240
	/*
241
	 * No attached clients therefore want to exit - flush any waiting
242
	 * clients but don't actually exit until they've gone.
243
	 */
244
	cmd_wait_for_flush();
245
	if (!TAILQ_EMPTY(&clients))
246
		return (0);
247
248
	return (1);
249
}
250
251
/* Exit the server by killing all clients and windows. */
252
static void
253
server_send_exit(void)
254
{
255
	struct client	*c, *c1;
256
	struct session	*s, *s1;
257
258
	cmd_wait_for_flush();
259
260
	TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
261
		if (c->flags & CLIENT_SUSPENDED)
262
			server_client_lost(c);
263
		else
264
			proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
265
		c->session = NULL;
266
	}
267
268
	RB_FOREACH_SAFE(s, sessions, &sessions, s1)
269
		session_destroy(s, __func__);
270
}
271
272
/* Update socket execute permissions based on whether sessions are attached. */
273
void
274
server_update_socket(void)
275
{
276
	struct session	*s;
277
	static int	 last = -1;
278
	int		 n, mode;
279
	struct stat      sb;
280
281
	n = 0;
282
	RB_FOREACH(s, sessions, &sessions) {
283
		if (!(s->flags & SESSION_UNATTACHED)) {
284
			n++;
285
			break;
286
		}
287
	}
288
289
	if (n != last) {
290
		last = n;
291
292
		if (stat(socket_path, &sb) != 0)
293
			return;
294
		mode = sb.st_mode & ACCESSPERMS;
295
		if (n != 0) {
296
			if (mode & S_IRUSR)
297
				mode |= S_IXUSR;
298
			if (mode & S_IRGRP)
299
				mode |= S_IXGRP;
300
			if (mode & S_IROTH)
301
				mode |= S_IXOTH;
302
		} else
303
			mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
304
		chmod(socket_path, mode);
305
	}
306
}
307
308
/* Callback for server socket. */
309
static void
310
server_accept(int fd, short events, __unused void *data)
311
{
312
	struct sockaddr_storage	sa;
313
	socklen_t		slen = sizeof sa;
314
	int			newfd;
315
316
	server_add_accept(0);
317
	if (!(events & EV_READ))
318
		return;
319
320
	newfd = accept(fd, (struct sockaddr *) &sa, &slen);
321
	if (newfd == -1) {
322
		if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
323
			return;
324
		if (errno == ENFILE || errno == EMFILE) {
325
			/* Delete and don't try again for 1 second. */
326
			server_add_accept(1);
327
			return;
328
		}
329
		fatal("accept failed");
330
	}
331
	if (server_exit) {
332
		close(newfd);
333
		return;
334
	}
335
	server_client_create(newfd);
336
}
337
338
/*
339
 * Add accept event. If timeout is nonzero, add as a timeout instead of a read
340
 * event - used to backoff when running out of file descriptors.
341
 */
342
void
343
server_add_accept(int timeout)
344
{
345
	struct timeval tv = { timeout, 0 };
346
347
	if (event_initialized(&server_ev_accept))
348
		event_del(&server_ev_accept);
349
350
	if (timeout == 0) {
351
		event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
352
		    NULL);
353
		event_add(&server_ev_accept, NULL);
354
	} else {
355
		event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
356
		    server_accept, NULL);
357
		event_add(&server_ev_accept, &tv);
358
	}
359
}
360
361
/* Signal handler. */
362
static void
363
server_signal(int sig)
364
{
365
	int	fd;
366
367
	log_debug("%s: %s", __func__, strsignal(sig));
368
	switch (sig) {
369
	case SIGTERM:
370
		server_exit = 1;
371
		server_send_exit();
372
		break;
373
	case SIGCHLD:
374
		server_child_signal();
375
		break;
376
	case SIGUSR1:
377
		event_del(&server_ev_accept);
378
		fd = server_create_socket();
379
		if (fd != -1) {
380
			close(server_fd);
381
			server_fd = fd;
382
			server_update_socket();
383
		}
384
		server_add_accept(0);
385
		break;
386
	case SIGUSR2:
387
		proc_toggle_log(server_proc);
388
		break;
389
	}
390
}
391
392
/* Handle SIGCHLD. */
393
static void
394
server_child_signal(void)
395
{
396
	int	 status;
397
	pid_t	 pid;
398
399
	for (;;) {
400
		switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
401
		case -1:
402
			if (errno == ECHILD)
403
				return;
404
			fatal("waitpid failed");
405
		case 0:
406
			return;
407
		}
408
		if (WIFSTOPPED(status))
409
			server_child_stopped(pid, status);
410
		else if (WIFEXITED(status) || WIFSIGNALED(status))
411
			server_child_exited(pid, status);
412
	}
413
}
414
415
/* Handle exited children. */
416
static void
417
server_child_exited(pid_t pid, int status)
418
{
419
	struct window		*w, *w1;
420
	struct window_pane	*wp;
421
	struct job		*job;
422
423
	RB_FOREACH_SAFE(w, windows, &windows, w1) {
424
		TAILQ_FOREACH(wp, &w->panes, entry) {
425
			if (wp->pid == pid) {
426
				wp->status = status;
427
428
				log_debug("%%%u exited", wp->id);
429
				wp->flags |= PANE_EXITED;
430
431
				if (window_pane_destroy_ready(wp))
432
					server_destroy_pane(wp, 1);
433
				break;
434
			}
435
		}
436
	}
437
438
	LIST_FOREACH(job, &all_jobs, entry) {
439
		if (pid == job->pid) {
440
			job_died(job, status);	/* might free job */
441
			break;
442
		}
443
	}
444
}
445
446
/* Handle stopped children. */
447
static void
448
server_child_stopped(pid_t pid, int status)
449
{
450
	struct window		*w;
451
	struct window_pane	*wp;
452
453
	if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
454
		return;
455
456
	RB_FOREACH(w, windows, &windows) {
457
		TAILQ_FOREACH(wp, &w->panes, entry) {
458
			if (wp->pid == pid) {
459
				if (killpg(pid, SIGCONT) != 0)
460
					kill(pid, SIGCONT);
461
			}
462
		}
463
	}
464
}