tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

session.c
Go to the documentation of this file.
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/time.h>
21 
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <time.h>
26 
27 #include "tmux.h"
28 
29 struct sessions sessions;
30 static u_int next_session_id;
31 struct session_groups session_groups = RB_INITIALIZER(&session_groups);
32 
33 static void session_free(int, short, void *);
34 
35 static void session_lock_timer(int, short, void *);
36 
37 static struct winlink *session_next_alert(struct winlink *);
38 static struct winlink *session_previous_alert(struct winlink *);
39 
40 static void session_group_remove(struct session *);
41 static void session_group_synchronize1(struct session *, struct session *);
42 
43 int
44 session_cmp(struct session *s1, struct session *s2)
45 {
46  return (strcmp(s1->name, s2->name));
47 }
49 
50 static int
52 {
53  return (strcmp(s1->name, s2->name));
54 }
56 
57 /*
58  * Find if session is still alive. This is true if it is still on the global
59  * sessions list.
60  */
61 int
63 {
64  struct session *s_loop;
65 
66  RB_FOREACH(s_loop, sessions, &sessions) {
67  if (s_loop == s)
68  return (1);
69  }
70  return (0);
71 }
72 
73 /* Find session by name. */
74 struct session *
75 session_find(const char *name)
76 {
77  struct session s;
78 
79  s.name = (char *) name;
80  return (RB_FIND(sessions, &sessions, &s));
81 }
82 
83 /* Find session by id parsed from a string. */
84 struct session *
85 session_find_by_id_str(const char *s)
86 {
87  const char *errstr;
88  u_int id;
89 
90  if (*s != '$')
91  return (NULL);
92 
93  id = strtonum(s + 1, 0, UINT_MAX, &errstr);
94  if (errstr != NULL)
95  return (NULL);
96  return (session_find_by_id(id));
97 }
98 
99 /* Find session by id. */
100 struct session *
102 {
103  struct session *s;
104 
105  RB_FOREACH(s, sessions, &sessions) {
106  if (s->id == id)
107  return (s);
108  }
109  return (NULL);
110 }
111 
112 /* Create a new session. */
113 struct session *
114 session_create(const char *prefix, const char *name, const char *cwd,
115  struct environ *env, struct options *oo, struct termios *tio)
116 {
117  struct session *s;
118 
119  s = xcalloc(1, sizeof *s);
120  s->references = 1;
121  s->flags = 0;
122 
123  s->cwd = xstrdup(cwd);
124 
125  TAILQ_INIT(&s->lastw);
126  RB_INIT(&s->windows);
127 
128  s->environ = env;
129  s->options = oo;
130 
132 
133  s->tio = NULL;
134  if (tio != NULL) {
135  s->tio = xmalloc(sizeof *s->tio);
136  memcpy(s->tio, tio, sizeof *s->tio);
137  }
138 
139  if (name != NULL) {
140  s->name = xstrdup(name);
141  s->id = next_session_id++;
142  } else {
143  do {
144  s->id = next_session_id++;
145  free(s->name);
146  if (prefix != NULL)
147  xasprintf(&s->name, "%s-%u", prefix, s->id);
148  else
149  xasprintf(&s->name, "%u", s->id);
150  } while (RB_FIND(sessions, &sessions, s) != NULL);
151  }
152  RB_INSERT(sessions, &sessions, s);
153 
154  log_debug("new session %s $%u", s->name, s->id);
155 
156  if (gettimeofday(&s->creation_time, NULL) != 0)
157  fatal("gettimeofday failed");
159 
160  return (s);
161 }
162 
163 /* Add a reference to a session. */
164 void
165 session_add_ref(struct session *s, const char *from)
166 {
167  s->references++;
168  log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references);
169 }
170 
171 /* Remove a reference from a session. */
172 void
173 session_remove_ref(struct session *s, const char *from)
174 {
175  s->references--;
176  log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references);
177 
178  if (s->references == 0)
179  event_once(-1, EV_TIMEOUT, session_free, s, NULL);
180 }
181 
182 /* Free session. */
183 static void
184 session_free(__unused int fd, __unused short events, void *arg)
185 {
186  struct session *s = arg;
187 
188  log_debug("session %s freed (%d references)", s->name, s->references);
189 
190  if (s->references == 0) {
191  environ_free(s->environ);
192  options_free(s->options);
193 
194  free(s->name);
195  free(s);
196  }
197 }
198 
199 /* Destroy a session. */
200 void
201 session_destroy(struct session *s, int notify, const char *from)
202 {
203  struct winlink *wl;
204 
205  log_debug("session %s destroyed (%s)", s->name, from);
206  s->curw = NULL;
207 
208  RB_REMOVE(sessions, &sessions, s);
209  if (notify)
210  notify_session("session-closed", s);
211 
212  free(s->tio);
213 
214  if (event_initialized(&s->lock_timer))
215  event_del(&s->lock_timer);
216 
218 
219  while (!TAILQ_EMPTY(&s->lastw))
220  winlink_stack_remove(&s->lastw, TAILQ_FIRST(&s->lastw));
221  while (!RB_EMPTY(&s->windows)) {
222  wl = RB_ROOT(&s->windows);
223  notify_session_window("window-unlinked", s, wl->window);
224  winlink_remove(&s->windows, wl);
225  }
226 
227  free((void *)s->cwd);
228 
229  session_remove_ref(s, __func__);
230 }
231 
232 /* Sanitize session name. */
233 char *
235 {
236  char *copy, *cp, *new_name;
237 
238  copy = xstrdup(name);
239  for (cp = copy; *cp != '\0'; cp++) {
240  if (*cp == ':' || *cp == '.')
241  *cp = '_';
242  }
243  utf8_stravis(&new_name, copy, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
244  free(copy);
245  return (new_name);
246 }
247 
248 /* Lock session if it has timed out. */
249 static void
250 session_lock_timer(__unused int fd, __unused short events, void *arg)
251 {
252  struct session *s = arg;
253 
254  if (s->attached == 0)
255  return;
256 
257  log_debug("session %s locked, activity time %lld", s->name,
258  (long long)s->activity_time.tv_sec);
259 
262 }
263 
264 /* Update activity time. */
265 void
266 session_update_activity(struct session *s, struct timeval *from)
267 {
268  struct timeval *last = &s->last_activity_time;
269  struct timeval tv;
270 
271  memcpy(last, &s->activity_time, sizeof *last);
272  if (from == NULL)
273  gettimeofday(&s->activity_time, NULL);
274  else
275  memcpy(&s->activity_time, from, sizeof s->activity_time);
276 
277  log_debug("session $%u %s activity %lld.%06d (last %lld.%06d)", s->id,
278  s->name, (long long)s->activity_time.tv_sec,
279  (int)s->activity_time.tv_usec, (long long)last->tv_sec,
280  (int)last->tv_usec);
281 
282  if (evtimer_initialized(&s->lock_timer))
283  evtimer_del(&s->lock_timer);
284  else
285  evtimer_set(&s->lock_timer, session_lock_timer, s);
286 
287  if (s->attached != 0) {
288  timerclear(&tv);
289  tv.tv_sec = options_get_number(s->options, "lock-after-time");
290  if (tv.tv_sec != 0)
291  evtimer_add(&s->lock_timer, &tv);
292  }
293 }
294 
295 /* Find the next usable session. */
296 struct session *
298 {
299  struct session *s2;
300 
301  if (RB_EMPTY(&sessions) || !session_alive(s))
302  return (NULL);
303 
304  s2 = RB_NEXT(sessions, &sessions, s);
305  if (s2 == NULL)
306  s2 = RB_MIN(sessions, &sessions);
307  if (s2 == s)
308  return (NULL);
309  return (s2);
310 }
311 
312 /* Find the previous usable session. */
313 struct session *
315 {
316  struct session *s2;
317 
318  if (RB_EMPTY(&sessions) || !session_alive(s))
319  return (NULL);
320 
321  s2 = RB_PREV(sessions, &sessions, s);
322  if (s2 == NULL)
323  s2 = RB_MAX(sessions, &sessions);
324  if (s2 == s)
325  return (NULL);
326  return (s2);
327 }
328 
329 /* Attach a window to a session. */
330 struct winlink *
331 session_attach(struct session *s, struct window *w, int idx, char **cause)
332 {
333  struct winlink *wl;
334 
335  if ((wl = winlink_add(&s->windows, idx)) == NULL) {
336  xasprintf(cause, "index in use: %d", idx);
337  return (NULL);
338  }
339  wl->session = s;
340  winlink_set_window(wl, w);
341  notify_session_window("window-linked", s, w);
342 
344  return (wl);
345 }
346 
347 /* Detach a window from a session. */
348 int
349 session_detach(struct session *s, struct winlink *wl)
350 {
351  if (s->curw == wl &&
352  session_last(s) != 0 &&
353  session_previous(s, 0) != 0)
354  session_next(s, 0);
355 
356  wl->flags &= ~~WINLINK_ALERTFLAGS;
357  notify_session_window("window-unlinked", s, wl->window);
358  winlink_stack_remove(&s->lastw, wl);
359  winlink_remove(&s->windows, wl);
360 
362 
363  if (RB_EMPTY(&s->windows)) {
364  session_destroy(s, 1, __func__);
365  return (1);
366  }
367  return (0);
368 }
369 
370 /* Return if session has window. */
371 int
372 session_has(struct session *s, struct window *w)
373 {
374  struct winlink *wl;
375 
376  TAILQ_FOREACH(wl, &w->winlinks, wentry) {
377  if (wl->session == s)
378  return (1);
379  }
380  return (0);
381 }
382 
383 /*
384  * Return 1 if a window is linked outside this session (not including session
385  * groups). The window must be in this session!
386  */
387 int
388 session_is_linked(struct session *s, struct window *w)
389 {
390  struct session_group *sg;
391 
392  if ((sg = session_group_contains(s)) != NULL)
393  return (w->references != session_group_count(sg));
394  return (w->references != 1);
395 }
396 
397 static struct winlink *
399 {
400  while (wl != NULL) {
401  if (wl->flags & WINLINK_ALERTFLAGS)
402  break;
403  wl = winlink_next(wl);
404  }
405  return (wl);
406 }
407 
408 /* Move session to next window. */
409 int
410 session_next(struct session *s, int alert)
411 {
412  struct winlink *wl;
413 
414  if (s->curw == NULL)
415  return (-1);
416 
417  wl = winlink_next(s->curw);
418  if (alert)
419  wl = session_next_alert(wl);
420  if (wl == NULL) {
421  wl = RB_MIN(winlinks, &s->windows);
422  if (alert && ((wl = session_next_alert(wl)) == NULL))
423  return (-1);
424  }
425  return (session_set_current(s, wl));
426 }
427 
428 static struct winlink *
430 {
431  while (wl != NULL) {
432  if (wl->flags & WINLINK_ALERTFLAGS)
433  break;
434  wl = winlink_previous(wl);
435  }
436  return (wl);
437 }
438 
439 /* Move session to previous window. */
440 int
441 session_previous(struct session *s, int alert)
442 {
443  struct winlink *wl;
444 
445  if (s->curw == NULL)
446  return (-1);
447 
448  wl = winlink_previous(s->curw);
449  if (alert)
450  wl = session_previous_alert(wl);
451  if (wl == NULL) {
452  wl = RB_MAX(winlinks, &s->windows);
453  if (alert && (wl = session_previous_alert(wl)) == NULL)
454  return (-1);
455  }
456  return (session_set_current(s, wl));
457 }
458 
459 /* Move session to specific window. */
460 int
461 session_select(struct session *s, int idx)
462 {
463  struct winlink *wl;
464 
465  wl = winlink_find_by_index(&s->windows, idx);
466  return (session_set_current(s, wl));
467 }
468 
469 /* Move session to last used window. */
470 int
472 {
473  struct winlink *wl;
474 
475  wl = TAILQ_FIRST(&s->lastw);
476  if (wl == NULL)
477  return (-1);
478  if (wl == s->curw)
479  return (1);
480 
481  return (session_set_current(s, wl));
482 }
483 
484 /* Set current winlink to wl .*/
485 int
486 session_set_current(struct session *s, struct winlink *wl)
487 {
488  if (wl == NULL)
489  return (-1);
490  if (wl == s->curw)
491  return (1);
492 
493  winlink_stack_remove(&s->lastw, wl);
494  winlink_stack_push(&s->lastw, s->curw);
495  s->curw = wl;
499  notify_session("session-window-changed", s);
500  return (0);
501 }
502 
503 /* Find the session group containing a session. */
504 struct session_group *
506 {
507  struct session_group *sg;
508  struct session *s;
509 
510  RB_FOREACH(sg, session_groups, &session_groups) {
511  TAILQ_FOREACH(s, &sg->sessions, gentry) {
512  if (s == target)
513  return (sg);
514  }
515  }
516  return (NULL);
517 }
518 
519 /* Find session group by name. */
520 struct session_group *
522 {
523  struct session_group sg;
524 
525  sg.name = name;
526  return (RB_FIND(session_groups, &session_groups, &sg));
527 }
528 
529 /* Create a new session group. */
530 struct session_group *
532 {
533  struct session_group *sg;
534 
535  if ((sg = session_group_find(name)) != NULL)
536  return (sg);
537 
538  sg = xcalloc(1, sizeof *sg);
539  sg->name = xstrdup(name);
540  TAILQ_INIT(&sg->sessions);
541 
542  RB_INSERT(session_groups, &session_groups, sg);
543  return (sg);
544 }
545 
546 /* Add a session to a session group. */
547 void
549 {
550  if (session_group_contains(s) == NULL)
551  TAILQ_INSERT_TAIL(&sg->sessions, s, gentry);
552 }
553 
554 /* Remove a session from its group and destroy the group if empty. */
555 static void
557 {
558  struct session_group *sg;
559 
560  if ((sg = session_group_contains(s)) == NULL)
561  return;
562  TAILQ_REMOVE(&sg->sessions, s, gentry);
563  if (TAILQ_EMPTY(&sg->sessions)) {
564  RB_REMOVE(session_groups, &session_groups, sg);
565  free((void *)sg->name);
566  free(sg);
567  }
568 }
569 
570 /* Count number of sessions in session group. */
571 u_int
573 {
574  struct session *s;
575  u_int n;
576 
577  n = 0;
578  TAILQ_FOREACH(s, &sg->sessions, gentry)
579  n++;
580  return (n);
581 }
582 
583 /* Count number of clients attached to sessions in session group. */
584 u_int
586 {
587  struct session *s;
588  u_int n;
589 
590  n = 0;
591  TAILQ_FOREACH(s, &sg->sessions, gentry)
592  n += s->attached;
593  return (n);
594 }
595 
596 /* Synchronize a session to its session group. */
597 void
599 {
600  struct session_group *sg;
601  struct session *target;
602 
603  if ((sg = session_group_contains(s)) == NULL)
604  return;
605 
606  target = NULL;
607  TAILQ_FOREACH(target, &sg->sessions, gentry) {
608  if (target != s)
609  break;
610  }
611  if (target != NULL)
612  session_group_synchronize1(target, s);
613 }
614 
615 /* Synchronize a session group to a session. */
616 void
618 {
619  struct session_group *sg;
620  struct session *s;
621 
622  if ((sg = session_group_contains(target)) == NULL)
623  return;
624 
625  TAILQ_FOREACH(s, &sg->sessions, gentry) {
626  if (s != target)
627  session_group_synchronize1(target, s);
628  }
629 }
630 
631 /*
632  * Synchronize a session with a target session. This means destroying all
633  * winlinks then recreating them, then updating the current window, last window
634  * stack and alerts.
635  */
636 static void
637 session_group_synchronize1(struct session *target, struct session *s)
638 {
639  struct winlinks old_windows, *ww;
640  struct winlink_stack old_lastw;
641  struct winlink *wl, *wl2;
642 
643  /* Don't do anything if the session is empty (it'll be destroyed). */
644  ww = &target->windows;
645  if (RB_EMPTY(ww))
646  return;
647 
648  /* If the current window has vanished, move to the next now. */
649  if (s->curw != NULL &&
650  winlink_find_by_index(ww, s->curw->idx) == NULL &&
651  session_last(s) != 0 && session_previous(s, 0) != 0)
652  session_next(s, 0);
653 
654  /* Save the old pointer and reset it. */
655  memcpy(&old_windows, &s->windows, sizeof old_windows);
656  RB_INIT(&s->windows);
657 
658  /* Link all the windows from the target. */
659  RB_FOREACH(wl, winlinks, ww) {
660  wl2 = winlink_add(&s->windows, wl->idx);
661  wl2->session = s;
662  winlink_set_window(wl2, wl->window);
663  notify_session_window("window-linked", s, wl2->window);
664  wl2->flags |= wl->flags & WINLINK_ALERTFLAGS;
665  }
666 
667  /* Fix up the current window. */
668  if (s->curw != NULL)
669  s->curw = winlink_find_by_index(&s->windows, s->curw->idx);
670  else
671  s->curw = winlink_find_by_index(&s->windows, target->curw->idx);
672 
673  /* Fix up the last window stack. */
674  memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
675  TAILQ_INIT(&s->lastw);
676  TAILQ_FOREACH(wl, &old_lastw, sentry) {
677  wl2 = winlink_find_by_index(&s->windows, wl->idx);
678  if (wl2 != NULL)
679  TAILQ_INSERT_TAIL(&s->lastw, wl2, sentry);
680  }
681 
682  /* Then free the old winlinks list. */
683  while (!RB_EMPTY(&old_windows)) {
684  wl = RB_ROOT(&old_windows);
685  wl2 = winlink_find_by_window_id(&s->windows, wl->window->id);
686  if (wl2 == NULL)
687  notify_session_window("window-unlinked", s, wl->window);
688  winlink_remove(&old_windows, wl);
689  }
690 }
691 
692 /* Renumber the windows across winlinks attached to a specific session. */
693 void
695 {
696  struct winlink *wl, *wl1, *wl_new;
697  struct winlinks old_wins;
698  struct winlink_stack old_lastw;
699  int new_idx, new_curw_idx;
700 
701  /* Save and replace old window list. */
702  memcpy(&old_wins, &s->windows, sizeof old_wins);
703  RB_INIT(&s->windows);
704 
705  /* Start renumbering from the base-index if it's set. */
706  new_idx = options_get_number(s->options, "base-index");
707  new_curw_idx = 0;
708 
709  /* Go through the winlinks and assign new indexes. */
710  RB_FOREACH(wl, winlinks, &old_wins) {
711  wl_new = winlink_add(&s->windows, new_idx);
712  wl_new->session = s;
713  winlink_set_window(wl_new, wl->window);
714  wl_new->flags |= wl->flags & WINLINK_ALERTFLAGS;
715 
716  if (wl == s->curw)
717  new_curw_idx = wl_new->idx;
718 
719  new_idx++;
720  }
721 
722  /* Fix the stack of last windows now. */
723  memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
724  TAILQ_INIT(&s->lastw);
725  TAILQ_FOREACH(wl, &old_lastw, sentry) {
726  wl_new = winlink_find_by_window(&s->windows, wl->window);
727  if (wl_new != NULL)
728  TAILQ_INSERT_TAIL(&s->lastw, wl_new, sentry);
729  }
730 
731  /* Set the current window. */
732  s->curw = winlink_find_by_index(&s->windows, new_curw_idx);
733 
734  /* Free the old winlinks (reducing window references too). */
735  RB_FOREACH_SAFE(wl, winlinks, &old_wins, wl1)
736  winlink_remove(&old_wins, wl);
737 }
#define __unused
Definition: compat.h:60
long long strtonum(const char *, long long, long long, const char **)
void environ_free(struct environ *env)
Definition: environ.c:56
const char * name
Definition: layout-set.c:38
void fatal(const char *msg,...)
Definition: log.c:144
void log_debug(const char *msg,...)
Definition: log.c:130
void notify_session(const char *name, struct session *s)
Definition: notify.c:223
void notify_session_window(const char *name, struct session *s, struct window *w)
Definition: notify.c:244
void options_free(struct options *oo)
Definition: options.c:182
long long options_get_number(struct options *oo, const char *name)
Definition: options.c:699
void recalculate_sizes(void)
Definition: resize.c:355
void server_lock_session(struct session *s)
Definition: server-fn.c:144
struct session * session_find_by_id(u_int id)
Definition: session.c:101
RB_GENERATE_STATIC(session_groups, session_group, entry, session_group_cmp)
struct sessions sessions
Definition: session.c:29
void session_add_ref(struct session *s, const char *from)
Definition: session.c:165
static struct winlink * session_next_alert(struct winlink *)
Definition: session.c:398
struct session * session_create(const char *prefix, const char *name, const char *cwd, struct environ *env, struct options *oo, struct termios *tio)
Definition: session.c:114
int session_alive(struct session *s)
Definition: session.c:62
static void session_free(int, short, void *)
Definition: session.c:184
static void session_group_synchronize1(struct session *, struct session *)
Definition: session.c:637
void session_group_synchronize_to(struct session *s)
Definition: session.c:598
struct session_group * session_group_contains(struct session *target)
Definition: session.c:505
int session_is_linked(struct session *s, struct window *w)
Definition: session.c:388
void session_group_synchronize_from(struct session *target)
Definition: session.c:617
static void session_group_remove(struct session *)
Definition: session.c:556
int session_last(struct session *s)
Definition: session.c:471
struct session_group * session_group_new(const char *name)
Definition: session.c:531
void session_group_add(struct session_group *sg, struct session *s)
Definition: session.c:548
static struct winlink * session_previous_alert(struct winlink *)
Definition: session.c:429
int session_set_current(struct session *s, struct winlink *wl)
Definition: session.c:486
int session_cmp(struct session *s1, struct session *s2)
Definition: session.c:44
struct session * session_next_session(struct session *s)
Definition: session.c:297
struct session_group * session_group_find(const char *name)
Definition: session.c:521
int session_select(struct session *s, int idx)
Definition: session.c:461
void session_update_activity(struct session *s, struct timeval *from)
Definition: session.c:266
void session_remove_ref(struct session *s, const char *from)
Definition: session.c:173
struct session * session_previous_session(struct session *s)
Definition: session.c:314
static u_int next_session_id
Definition: session.c:30
struct session_groups session_groups
Definition: session.c:31
static void session_lock_timer(int, short, void *)
Definition: session.c:250
int session_next(struct session *s, int alert)
Definition: session.c:410
char * session_check_name(const char *name)
Definition: session.c:234
int session_previous(struct session *s, int alert)
Definition: session.c:441
u_int session_group_attached_count(struct session_group *sg)
Definition: session.c:585
struct winlink * session_attach(struct session *s, struct window *w, int idx, char **cause)
Definition: session.c:331
void session_destroy(struct session *s, int notify, const char *from)
Definition: session.c:201
u_int session_group_count(struct session_group *sg)
Definition: session.c:572
RB_GENERATE(sessions, session, entry, session_cmp)
struct session * session_find_by_id_str(const char *s)
Definition: session.c:85
int session_detach(struct session *s, struct winlink *wl)
Definition: session.c:349
int session_has(struct session *s, struct window *w)
Definition: session.c:372
struct session * session_find(const char *name)
Definition: session.c:75
static int session_group_cmp(struct session_group *s1, struct session_group *s2)
Definition: session.c:51
void session_renumber_windows(struct session *s)
Definition: session.c:694
void status_update_cache(struct session *s)
Definition: status.c:197
const char * name
Definition: tmux.h:1172
Definition: tmux.h:1179
char * name
Definition: tmux.h:1182
u_int id
Definition: tmux.h:1180
struct timeval creation_time
Definition: tmux.h:1185
struct winlinks windows
Definition: tmux.h:1194
struct winlink_stack lastw
Definition: tmux.h:1193
struct event lock_timer
Definition: tmux.h:1190
struct timeval activity_time
Definition: tmux.h:1187
struct timeval last_activity_time
Definition: tmux.h:1188
int references
Definition: tmux.h:1211
struct environ * environ
Definition: tmux.h:1209
struct winlink * curw
Definition: tmux.h:1192
const char * cwd
Definition: tmux.h:1183
struct termios * tio
Definition: tmux.h:1207
struct options * options
Definition: tmux.h:1199
u_int attached
Definition: tmux.h:1205
int flags
Definition: tmux.h:1203
Definition: tmux.h:1041
u_int id
Definition: tmux.h:1042
u_int references
Definition: tmux.h:1087
void winlink_stack_push(struct winlink_stack *, struct winlink *)
Definition: window.c:241
struct winlink * winlink_next(struct winlink *)
Definition: window.c:207
void winlink_clear_flags(struct winlink *)
Definition: window.c:1478
void winlink_stack_remove(struct winlink_stack *, struct winlink *)
Definition: window.c:251
void window_update_activity(struct window *)
Definition: window.c:291
void winlink_set_window(struct winlink *, struct window *)
Definition: window.c:181
char ** environ
int utf8_stravis(char **, const char *, int)
Definition: utf8.c:352
struct winlink * winlink_previous(struct winlink *)
Definition: window.c:213
#define WINLINK_ALERTFLAGS
Definition: tmux.h:1104
struct winlink * winlink_find_by_window_id(struct winlinks *, u_int)
Definition: window.c:121
struct winlink * winlink_add(struct winlinks *, int)
Definition: window.c:163
void winlink_remove(struct winlinks *, struct winlink *)
Definition: window.c:193
void tty_update_window_offset(struct window *)
Definition: tty.c:856
struct winlink * winlink_find_by_window(struct winlinks *, struct window *)
Definition: window.c:96
struct winlink * winlink_find_by_index(struct winlinks *, int)
Definition: window.c:109
void * xmalloc(size_t size)
Definition: xmalloc.c:27
int xasprintf(char **ret, const char *fmt,...)
Definition: xmalloc.c:109
void * xcalloc(size_t nmemb, size_t size)
Definition: xmalloc.c:41
char * xstrdup(const char *str)
Definition: xmalloc.c:89