Coverage Report

Created: 2025-04-11 06:41

/src/tmux/server.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD$ */
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 <fcntl.h>
28
#include <signal.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <termios.h>
33
#include <time.h>
34
#include <unistd.h>
35
36
#include "tmux.h"
37
38
/*
39
 * Main server functions.
40
 */
41
42
struct clients     clients;
43
44
struct tmuxproc   *server_proc;
45
static int     server_fd = -1;
46
static uint64_t    server_client_flags;
47
static int     server_exit;
48
static struct event  server_ev_accept;
49
static struct event  server_ev_tidy;
50
51
struct cmd_find_state  marked_pane;
52
53
static u_int     message_next;
54
struct message_list  message_log;
55
56
time_t       current_time;
57
58
static int  server_loop(void);
59
static void server_send_exit(void);
60
static void server_accept(int, short, void *);
61
static void server_signal(int);
62
static void server_child_signal(void);
63
static void server_child_exited(pid_t, int);
64
static void server_child_stopped(pid_t, int);
65
66
/* Set marked pane. */
67
void
68
server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
69
0
{
70
0
  cmd_find_clear_state(&marked_pane, 0);
71
0
  marked_pane.s = s;
72
0
  marked_pane.wl = wl;
73
0
  marked_pane.w = wl->window;
74
0
  marked_pane.wp = wp;
75
0
}
76
77
/* Clear marked pane. */
78
void
79
server_clear_marked(void)
80
0
{
81
0
  cmd_find_clear_state(&marked_pane, 0);
82
0
}
83
84
/* Is this the marked pane? */
85
int
86
server_is_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
87
0
{
88
0
  if (s == NULL || wl == NULL || wp == NULL)
89
0
    return (0);
90
0
  if (marked_pane.s != s || marked_pane.wl != wl)
91
0
    return (0);
92
0
  if (marked_pane.wp != wp)
93
0
    return (0);
94
0
  return (server_check_marked());
95
0
}
96
97
/* Check if the marked pane is still valid. */
98
int
99
server_check_marked(void)
100
0
{
101
0
  return (cmd_find_valid_state(&marked_pane));
102
0
}
103
104
/* Create server socket. */
105
int
106
server_create_socket(uint64_t flags, char **cause)
107
0
{
108
0
  struct sockaddr_un  sa;
109
0
  size_t      size;
110
0
  mode_t      mask;
111
0
  int     fd, saved_errno;
112
113
0
  memset(&sa, 0, sizeof sa);
114
0
  sa.sun_family = AF_UNIX;
115
0
  size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
116
0
  if (size >= sizeof sa.sun_path) {
117
0
    errno = ENAMETOOLONG;
118
0
    goto fail;
119
0
  }
120
0
  unlink(sa.sun_path);
121
122
0
  if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
123
0
    goto fail;
124
125
0
  if (flags & CLIENT_DEFAULTSOCKET)
126
0
    mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
127
0
  else
128
0
    mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
129
0
  if (bind(fd, (struct sockaddr *)&sa, sizeof sa) == -1) {
130
0
    saved_errno = errno;
131
0
    close(fd);
132
0
    errno = saved_errno;
133
0
    goto fail;
134
0
  }
135
0
  umask(mask);
136
137
0
  if (listen(fd, 128) == -1) {
138
0
    saved_errno = errno;
139
0
    close(fd);
140
0
    errno = saved_errno;
141
0
    goto fail;
142
0
  }
143
0
  setblocking(fd, 0);
144
145
0
  return (fd);
146
147
0
fail:
148
0
  if (cause != NULL) {
149
0
    xasprintf(cause, "error creating %s (%s)", socket_path,
150
0
        strerror(errno));
151
0
  }
152
0
  return (-1);
153
0
}
154
155
/* Tidy up every hour. */
156
static void
157
server_tidy_event(__unused int fd, __unused short events, __unused void *data)
158
0
{
159
0
    struct timeval  tv = { .tv_sec = 3600 };
160
0
    uint64_t    t = get_timer();
161
162
0
    format_tidy_jobs();
163
164
0
#ifdef HAVE_MALLOC_TRIM
165
0
    malloc_trim(0);
166
0
#endif
167
168
0
    log_debug("%s: took %llu milliseconds", __func__,
169
0
        (unsigned long long)(get_timer() - t));
170
0
    evtimer_add(&server_ev_tidy, &tv);
171
0
}
172
173
/* Fork new server. */
174
int
175
server_start(struct tmuxproc *client, uint64_t flags, struct event_base *base,
176
    int lockfd, char *lockfile)
177
0
{
178
0
  int    fd;
179
0
  sigset_t   set, oldset;
180
0
  struct client *c = NULL;
181
0
  char    *cause = NULL;
182
0
  struct timeval   tv = { .tv_sec = 3600 };
183
184
0
  sigfillset(&set);
185
0
  sigprocmask(SIG_BLOCK, &set, &oldset);
186
187
0
  if (~flags & CLIENT_NOFORK) {
188
0
    if (proc_fork_and_daemon(&fd) != 0) {
189
0
      sigprocmask(SIG_SETMASK, &oldset, NULL);
190
0
      return (fd);
191
0
    }
192
0
  }
193
0
  proc_clear_signals(client, 0);
194
0
  server_client_flags = flags;
195
196
0
  if (event_reinit(base) != 0)
197
0
    fatalx("event_reinit failed");
198
0
  server_proc = proc_start("server");
199
200
0
  proc_set_signals(server_proc, server_signal);
201
0
  sigprocmask(SIG_SETMASK, &oldset, NULL);
202
203
0
  if (log_get_level() > 1)
204
0
    tty_create_log();
205
0
  if (pledge("stdio rpath wpath cpath fattr unix getpw recvfd proc exec "
206
0
      "tty ps", NULL) != 0)
207
0
    fatal("pledge failed");
208
209
0
  input_key_build();
210
0
  utf8_update_width_cache();
211
0
  RB_INIT(&windows);
212
0
  RB_INIT(&all_window_panes);
213
0
  TAILQ_INIT(&clients);
214
0
  RB_INIT(&sessions);
215
0
  key_bindings_init();
216
0
  TAILQ_INIT(&message_log);
217
0
  gettimeofday(&start_time, NULL);
218
219
#ifdef HAVE_SYSTEMD
220
  server_fd = systemd_create_socket(flags, &cause);
221
#else
222
0
  server_fd = server_create_socket(flags, &cause);
223
0
#endif
224
0
  if (server_fd != -1)
225
0
    server_update_socket();
226
0
  if (~flags & CLIENT_NOFORK)
227
0
    c = server_client_create(fd);
228
0
  else
229
0
    options_set_number(global_options, "exit-empty", 0);
230
231
0
  if (lockfd >= 0) {
232
0
    unlink(lockfile);
233
0
    free(lockfile);
234
0
    close(lockfd);
235
0
  }
236
237
0
  if (cause != NULL) {
238
0
    if (c != NULL) {
239
0
      c->exit_message = cause;
240
0
      c->flags |= CLIENT_EXIT;
241
0
    } else {
242
0
      fprintf(stderr, "%s\n", cause);
243
0
      exit(1);
244
0
    }
245
0
  }
246
247
0
  evtimer_set(&server_ev_tidy, server_tidy_event, NULL);
248
0
  evtimer_add(&server_ev_tidy, &tv);
249
250
0
  server_acl_init();
251
252
0
  server_add_accept(0);
253
0
  proc_loop(server_proc, server_loop);
254
255
0
  job_kill_all();
256
0
  status_prompt_save_history();
257
258
0
  exit(0);
259
0
}
260
261
/* Server loop callback. */
262
static int
263
server_loop(void)
264
0
{
265
0
  struct client *c;
266
0
  u_int    items;
267
268
0
  current_time = time(NULL);
269
270
0
  do {
271
0
    items = cmdq_next(NULL);
272
0
    TAILQ_FOREACH(c, &clients, entry) {
273
0
      if (c->flags & CLIENT_IDENTIFIED)
274
0
        items += cmdq_next(c);
275
0
    }
276
0
  } while (items != 0);
277
278
0
  server_client_loop();
279
280
0
  if (!options_get_number(global_options, "exit-empty") && !server_exit)
281
0
    return (0);
282
283
0
  if (!options_get_number(global_options, "exit-unattached")) {
284
0
    if (!RB_EMPTY(&sessions))
285
0
      return (0);
286
0
  }
287
288
0
  TAILQ_FOREACH(c, &clients, entry) {
289
0
    if (c->session != NULL)
290
0
      return (0);
291
0
  }
292
293
  /*
294
   * No attached clients therefore want to exit - flush any waiting
295
   * clients but don't actually exit until they've gone.
296
   */
297
0
  cmd_wait_for_flush();
298
0
  if (!TAILQ_EMPTY(&clients))
299
0
    return (0);
300
301
0
  if (job_still_running())
302
0
    return (0);
303
304
0
  return (1);
305
0
}
306
307
/* Exit the server by killing all clients and windows. */
308
static void
309
server_send_exit(void)
310
0
{
311
0
  struct client *c, *c1;
312
0
  struct session  *s, *s1;
313
314
0
  cmd_wait_for_flush();
315
316
0
  TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
317
0
    if (c->flags & CLIENT_SUSPENDED)
318
0
      server_client_lost(c);
319
0
    else {
320
0
      c->flags |= CLIENT_EXIT;
321
0
      c->exit_type = CLIENT_EXIT_SHUTDOWN;
322
0
    }
323
0
    c->session = NULL;
324
0
  }
325
326
0
  RB_FOREACH_SAFE(s, sessions, &sessions, s1)
327
0
    session_destroy(s, 1, __func__);
328
0
}
329
330
/* Update socket execute permissions based on whether sessions are attached. */
331
void
332
server_update_socket(void)
333
0
{
334
0
  struct session  *s;
335
0
  static int   last = -1;
336
0
  int    n, mode;
337
0
  struct stat      sb;
338
339
0
  n = 0;
340
0
  RB_FOREACH(s, sessions, &sessions) {
341
0
    if (s->attached != 0) {
342
0
      n++;
343
0
      break;
344
0
    }
345
0
  }
346
347
0
  if (n != last) {
348
0
    last = n;
349
350
0
    if (stat(socket_path, &sb) != 0)
351
0
      return;
352
0
    mode = sb.st_mode & ACCESSPERMS;
353
0
    if (n != 0) {
354
0
      if (mode & S_IRUSR)
355
0
        mode |= S_IXUSR;
356
0
      if (mode & S_IRGRP)
357
0
        mode |= S_IXGRP;
358
0
      if (mode & S_IROTH)
359
0
        mode |= S_IXOTH;
360
0
    } else
361
0
      mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
362
0
    chmod(socket_path, mode);
363
0
  }
364
0
}
365
366
/* Callback for server socket. */
367
static void
368
server_accept(int fd, short events, __unused void *data)
369
0
{
370
0
  struct sockaddr_storage  sa;
371
0
  socklen_t    slen = sizeof sa;
372
0
  int      newfd;
373
0
  struct client   *c;
374
375
0
  server_add_accept(0);
376
0
  if (!(events & EV_READ))
377
0
    return;
378
379
0
  newfd = accept(fd, (struct sockaddr *) &sa, &slen);
380
0
  if (newfd == -1) {
381
0
    if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
382
0
      return;
383
0
    if (errno == ENFILE || errno == EMFILE) {
384
      /* Delete and don't try again for 1 second. */
385
0
      server_add_accept(1);
386
0
      return;
387
0
    }
388
0
    fatal("accept failed");
389
0
  }
390
391
0
  if (server_exit) {
392
0
    close(newfd);
393
0
    return;
394
0
  }
395
0
  c = server_client_create(newfd);
396
0
  if (!server_acl_join(c)) {
397
0
    c->exit_message = xstrdup("access not allowed");
398
0
    c->flags |= CLIENT_EXIT;
399
0
  }
400
0
}
401
402
/*
403
 * Add accept event. If timeout is nonzero, add as a timeout instead of a read
404
 * event - used to backoff when running out of file descriptors.
405
 */
406
void
407
server_add_accept(int timeout)
408
0
{
409
0
  struct timeval tv = { timeout, 0 };
410
411
0
  if (server_fd == -1)
412
0
    return;
413
414
0
  if (event_initialized(&server_ev_accept))
415
0
    event_del(&server_ev_accept);
416
417
0
  if (timeout == 0) {
418
0
    event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
419
0
        NULL);
420
0
    event_add(&server_ev_accept, NULL);
421
0
  } else {
422
0
    event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
423
0
        server_accept, NULL);
424
0
    event_add(&server_ev_accept, &tv);
425
0
  }
426
0
}
427
428
/* Signal handler. */
429
static void
430
server_signal(int sig)
431
0
{
432
0
  int fd;
433
434
0
  log_debug("%s: %s", __func__, strsignal(sig));
435
0
  switch (sig) {
436
0
  case SIGINT:
437
0
  case SIGTERM:
438
0
    server_exit = 1;
439
0
    server_send_exit();
440
0
    break;
441
0
  case SIGCHLD:
442
0
    server_child_signal();
443
0
    break;
444
0
  case SIGUSR1:
445
0
    event_del(&server_ev_accept);
446
0
    fd = server_create_socket(server_client_flags, NULL);
447
0
    if (fd != -1) {
448
0
      close(server_fd);
449
0
      server_fd = fd;
450
0
      server_update_socket();
451
0
    }
452
0
    server_add_accept(0);
453
0
    break;
454
0
  case SIGUSR2:
455
0
    proc_toggle_log(server_proc);
456
0
    break;
457
0
  }
458
0
}
459
460
/* Handle SIGCHLD. */
461
static void
462
server_child_signal(void)
463
0
{
464
0
  int  status;
465
0
  pid_t  pid;
466
467
0
  for (;;) {
468
0
    switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
469
0
    case -1:
470
0
      if (errno == ECHILD)
471
0
        return;
472
0
      fatal("waitpid failed");
473
0
    case 0:
474
0
      return;
475
0
    }
476
0
    if (WIFSTOPPED(status))
477
0
      server_child_stopped(pid, status);
478
0
    else if (WIFEXITED(status) || WIFSIGNALED(status))
479
0
      server_child_exited(pid, status);
480
0
  }
481
0
}
482
483
/* Handle exited children. */
484
static void
485
server_child_exited(pid_t pid, int status)
486
0
{
487
0
  struct window   *w, *w1;
488
0
  struct window_pane  *wp;
489
490
0
  RB_FOREACH_SAFE(w, windows, &windows, w1) {
491
0
    TAILQ_FOREACH(wp, &w->panes, entry) {
492
0
      if (wp->pid == pid) {
493
0
        wp->status = status;
494
0
        wp->flags |= PANE_STATUSREADY;
495
496
0
        log_debug("%%%u exited", wp->id);
497
0
        wp->flags |= PANE_EXITED;
498
499
0
        if (window_pane_destroy_ready(wp))
500
0
          server_destroy_pane(wp, 1);
501
0
        break;
502
0
      }
503
0
    }
504
0
  }
505
0
  job_check_died(pid, status);
506
0
}
507
508
/* Handle stopped children. */
509
static void
510
server_child_stopped(pid_t pid, int status)
511
0
{
512
0
  struct window   *w;
513
0
  struct window_pane  *wp;
514
515
0
  if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
516
0
    return;
517
518
0
  RB_FOREACH(w, windows, &windows) {
519
0
    TAILQ_FOREACH(wp, &w->panes, entry) {
520
0
      if (wp->pid == pid) {
521
0
        if (killpg(pid, SIGCONT) != 0)
522
0
          kill(pid, SIGCONT);
523
0
      }
524
0
    }
525
0
  }
526
0
  job_check_died(pid, status);
527
0
}
528
529
/* Add to message log. */
530
void
531
server_add_message(const char *fmt, ...)
532
0
{
533
0
  struct message_entry  *msg, *msg1;
534
0
  char      *s;
535
0
  va_list      ap;
536
0
  u_int      limit;
537
538
0
  va_start(ap, fmt);
539
0
  xvasprintf(&s, fmt, ap);
540
0
  va_end(ap);
541
542
0
  log_debug("message: %s", s);
543
544
0
  msg = xcalloc(1, sizeof *msg);
545
0
  gettimeofday(&msg->msg_time, NULL);
546
0
  msg->msg_num = message_next++;
547
0
  msg->msg = s;
548
0
  TAILQ_INSERT_TAIL(&message_log, msg, entry);
549
550
0
  limit = options_get_number(global_options, "message-limit");
551
0
  TAILQ_FOREACH_SAFE(msg, &message_log, entry, msg1) {
552
0
    if (msg->msg_num + limit >= message_next)
553
0
      break;
554
0
    free(msg->msg);
555
0
    TAILQ_REMOVE(&message_log, msg, entry);
556
0
    free(msg);
557
0
  }
558
0
}