Coverage Report

Created: 2025-08-29 06:28

/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
  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
  TAILQ_INIT(&message_log);
218
0
  gettimeofday(&start_time, NULL);
219
220
#ifdef HAVE_SYSTEMD
221
  server_fd = systemd_create_socket(flags, &cause);
222
#else
223
0
  server_fd = server_create_socket(flags, &cause);
224
0
#endif
225
0
  if (server_fd != -1)
226
0
    server_update_socket();
227
0
  if (~flags & CLIENT_NOFORK)
228
0
    c = server_client_create(fd);
229
0
  else
230
0
    options_set_number(global_options, "exit-empty", 0);
231
232
0
  if (lockfd >= 0) {
233
0
    unlink(lockfile);
234
0
    free(lockfile);
235
0
    close(lockfd);
236
0
  }
237
238
0
  if (cause != NULL) {
239
0
    if (c != NULL) {
240
0
      c->exit_message = cause;
241
0
      c->flags |= CLIENT_EXIT;
242
0
    } else {
243
0
      fprintf(stderr, "%s\n", cause);
244
0
      exit(1);
245
0
    }
246
0
  }
247
248
0
  evtimer_set(&server_ev_tidy, server_tidy_event, NULL);
249
0
  evtimer_add(&server_ev_tidy, &tv);
250
251
0
  server_acl_init();
252
253
0
  server_add_accept(0);
254
0
  proc_loop(server_proc, server_loop);
255
256
0
  job_kill_all();
257
0
  status_prompt_save_history();
258
259
0
  exit(0);
260
0
}
261
262
/* Server loop callback. */
263
static int
264
server_loop(void)
265
0
{
266
0
  struct client *c;
267
0
  u_int    items;
268
269
0
  current_time = time(NULL);
270
271
0
  do {
272
0
    items = cmdq_next(NULL);
273
0
    TAILQ_FOREACH(c, &clients, entry) {
274
0
      if (c->flags & CLIENT_IDENTIFIED)
275
0
        items += cmdq_next(c);
276
0
    }
277
0
  } while (items != 0);
278
279
0
  server_client_loop();
280
281
0
  if (!options_get_number(global_options, "exit-empty") && !server_exit)
282
0
    return (0);
283
284
0
  if (!options_get_number(global_options, "exit-unattached")) {
285
0
    if (!RB_EMPTY(&sessions))
286
0
      return (0);
287
0
  }
288
289
0
  TAILQ_FOREACH(c, &clients, entry) {
290
0
    if (c->session != NULL)
291
0
      return (0);
292
0
  }
293
294
  /*
295
   * No attached clients therefore want to exit - flush any waiting
296
   * clients but don't actually exit until they've gone.
297
   */
298
0
  cmd_wait_for_flush();
299
0
  if (!TAILQ_EMPTY(&clients))
300
0
    return (0);
301
302
0
  if (job_still_running())
303
0
    return (0);
304
305
0
  return (1);
306
0
}
307
308
/* Exit the server by killing all clients and windows. */
309
static void
310
server_send_exit(void)
311
0
{
312
0
  struct client *c, *c1;
313
0
  struct session  *s, *s1;
314
315
0
  cmd_wait_for_flush();
316
317
0
  TAILQ_FOREACH_SAFE(c, &clients, entry, c1) {
318
0
    if (c->flags & CLIENT_SUSPENDED)
319
0
      server_client_lost(c);
320
0
    else {
321
0
      c->flags |= CLIENT_EXIT;
322
0
      c->exit_type = CLIENT_EXIT_SHUTDOWN;
323
0
    }
324
0
    c->session = NULL;
325
0
  }
326
327
0
  RB_FOREACH_SAFE(s, sessions, &sessions, s1)
328
0
    session_destroy(s, 1, __func__);
329
0
}
330
331
/* Update socket execute permissions based on whether sessions are attached. */
332
void
333
server_update_socket(void)
334
0
{
335
0
  struct session  *s;
336
0
  static int   last = -1;
337
0
  int    n, mode;
338
0
  struct stat      sb;
339
340
0
  n = 0;
341
0
  RB_FOREACH(s, sessions, &sessions) {
342
0
    if (s->attached != 0) {
343
0
      n++;
344
0
      break;
345
0
    }
346
0
  }
347
348
0
  if (n != last) {
349
0
    last = n;
350
351
0
    if (stat(socket_path, &sb) != 0)
352
0
      return;
353
0
    mode = sb.st_mode & ACCESSPERMS;
354
0
    if (n != 0) {
355
0
      if (mode & S_IRUSR)
356
0
        mode |= S_IXUSR;
357
0
      if (mode & S_IRGRP)
358
0
        mode |= S_IXGRP;
359
0
      if (mode & S_IROTH)
360
0
        mode |= S_IXOTH;
361
0
    } else
362
0
      mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
363
0
    chmod(socket_path, mode);
364
0
  }
365
0
}
366
367
/* Callback for server socket. */
368
static void
369
server_accept(int fd, short events, __unused void *data)
370
0
{
371
0
  struct sockaddr_storage  sa;
372
0
  socklen_t    slen = sizeof sa;
373
0
  int      newfd;
374
0
  struct client   *c;
375
376
0
  server_add_accept(0);
377
0
  if (!(events & EV_READ))
378
0
    return;
379
380
0
  newfd = accept(fd, (struct sockaddr *) &sa, &slen);
381
0
  if (newfd == -1) {
382
0
    if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
383
0
      return;
384
0
    if (errno == ENFILE || errno == EMFILE) {
385
      /* Delete and don't try again for 1 second. */
386
0
      server_add_accept(1);
387
0
      return;
388
0
    }
389
0
    fatal("accept failed");
390
0
  }
391
392
0
  if (server_exit) {
393
0
    close(newfd);
394
0
    return;
395
0
  }
396
0
  c = server_client_create(newfd);
397
0
  if (!server_acl_join(c)) {
398
0
    c->exit_message = xstrdup("access not allowed");
399
0
    c->flags |= CLIENT_EXIT;
400
0
  }
401
0
}
402
403
/*
404
 * Add accept event. If timeout is nonzero, add as a timeout instead of a read
405
 * event - used to backoff when running out of file descriptors.
406
 */
407
void
408
server_add_accept(int timeout)
409
0
{
410
0
  struct timeval tv = { timeout, 0 };
411
412
0
  if (server_fd == -1)
413
0
    return;
414
415
0
  if (event_initialized(&server_ev_accept))
416
0
    event_del(&server_ev_accept);
417
418
0
  if (timeout == 0) {
419
0
    event_set(&server_ev_accept, server_fd, EV_READ, server_accept,
420
0
        NULL);
421
0
    event_add(&server_ev_accept, NULL);
422
0
  } else {
423
0
    event_set(&server_ev_accept, server_fd, EV_TIMEOUT,
424
0
        server_accept, NULL);
425
0
    event_add(&server_ev_accept, &tv);
426
0
  }
427
0
}
428
429
/* Signal handler. */
430
static void
431
server_signal(int sig)
432
0
{
433
0
  int fd;
434
435
0
  log_debug("%s: %s", __func__, strsignal(sig));
436
0
  switch (sig) {
437
0
  case SIGINT:
438
0
  case SIGTERM:
439
0
    server_exit = 1;
440
0
    server_send_exit();
441
0
    break;
442
0
  case SIGCHLD:
443
0
    server_child_signal();
444
0
    break;
445
0
  case SIGUSR1:
446
0
    event_del(&server_ev_accept);
447
0
    fd = server_create_socket(server_client_flags, NULL);
448
0
    if (fd != -1) {
449
0
      close(server_fd);
450
0
      server_fd = fd;
451
0
      server_update_socket();
452
0
    }
453
0
    server_add_accept(0);
454
0
    break;
455
0
  case SIGUSR2:
456
0
    proc_toggle_log(server_proc);
457
0
    break;
458
0
  }
459
0
}
460
461
/* Handle SIGCHLD. */
462
static void
463
server_child_signal(void)
464
0
{
465
0
  int  status;
466
0
  pid_t  pid;
467
468
0
  for (;;) {
469
0
    switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
470
0
    case -1:
471
0
      if (errno == ECHILD)
472
0
        return;
473
0
      fatal("waitpid failed");
474
0
    case 0:
475
0
      return;
476
0
    }
477
0
    if (WIFSTOPPED(status))
478
0
      server_child_stopped(pid, status);
479
0
    else if (WIFEXITED(status) || WIFSIGNALED(status))
480
0
      server_child_exited(pid, status);
481
0
  }
482
0
}
483
484
/* Handle exited children. */
485
static void
486
server_child_exited(pid_t pid, int status)
487
0
{
488
0
  struct window   *w, *w1;
489
0
  struct window_pane  *wp;
490
491
0
  RB_FOREACH_SAFE(w, windows, &windows, w1) {
492
0
    TAILQ_FOREACH(wp, &w->panes, entry) {
493
0
      if (wp->pid == pid) {
494
0
        wp->status = status;
495
0
        wp->flags |= PANE_STATUSREADY;
496
497
0
        log_debug("%%%u exited", wp->id);
498
0
        wp->flags |= PANE_EXITED;
499
500
0
        if (window_pane_destroy_ready(wp))
501
0
          server_destroy_pane(wp, 1);
502
0
        break;
503
0
      }
504
0
    }
505
0
  }
506
0
  job_check_died(pid, status);
507
0
}
508
509
/* Handle stopped children. */
510
static void
511
server_child_stopped(pid_t pid, int status)
512
0
{
513
0
  struct window   *w;
514
0
  struct window_pane  *wp;
515
516
0
  if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
517
0
    return;
518
519
0
  RB_FOREACH(w, windows, &windows) {
520
0
    TAILQ_FOREACH(wp, &w->panes, entry) {
521
0
      if (wp->pid == pid) {
522
0
        if (killpg(pid, SIGCONT) != 0)
523
0
          kill(pid, SIGCONT);
524
0
      }
525
0
    }
526
0
  }
527
0
  job_check_died(pid, status);
528
0
}
529
530
/* Add to message log. */
531
void
532
server_add_message(const char *fmt, ...)
533
0
{
534
0
  struct message_entry  *msg, *msg1;
535
0
  char      *s;
536
0
  va_list      ap;
537
0
  u_int      limit;
538
539
0
  va_start(ap, fmt);
540
0
  xvasprintf(&s, fmt, ap);
541
0
  va_end(ap);
542
543
0
  log_debug("message: %s", s);
544
545
0
  msg = xcalloc(1, sizeof *msg);
546
0
  gettimeofday(&msg->msg_time, NULL);
547
0
  msg->msg_num = message_next++;
548
0
  msg->msg = s;
549
0
  TAILQ_INSERT_TAIL(&message_log, msg, entry);
550
551
0
  limit = options_get_number(global_options, "message-limit");
552
0
  TAILQ_FOREACH_SAFE(msg, &message_log, entry, msg1) {
553
0
    if (msg->msg_num + limit >= message_next)
554
0
      break;
555
0
    free(msg->msg);
556
0
    TAILQ_REMOVE(&message_log, msg, entry);
557
0
    free(msg);
558
0
  }
559
0
}