Coverage Report

Created: 2026-07-30 07:05

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