From 89e80cabd56bf2f7fa783575fe9b1f6192fade42 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Apr 2015 15:05:03 +0000 Subject: [PATCH 1/8] window_index is only used in one place (window_destroy) so inline it there. --- server.c | 1 + tmux.h | 1 - window.c | 16 +++++----------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/server.c b/server.c index c8101775..bb96d9af 100644 --- a/server.c +++ b/server.c @@ -389,6 +389,7 @@ void server_signal_callback(int sig, unused short events, unused void *data) { int fd; + switch (sig) { case SIGTERM: server_shutdown = 1; diff --git a/tmux.h b/tmux.h index 53fd9b28..52dc1529 100644 --- a/tmux.h +++ b/tmux.h @@ -2141,7 +2141,6 @@ struct winlink *winlink_previous_by_number(struct winlink *, struct session *, int); void winlink_stack_push(struct winlink_stack *, struct winlink *); void winlink_stack_remove(struct winlink_stack *, struct winlink *); -int window_index(struct window *, u_int *); struct window *window_find_by_id(u_int); struct window *window_create1(u_int, u_int); struct window *window_create(const char *, int, char **, const char *, diff --git a/window.c b/window.c index 3c8d4955..d8f29026 100644 --- a/window.c +++ b/window.c @@ -245,16 +245,6 @@ winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl) } } -int -window_index(struct window *s, u_int *i) -{ - for (*i = 0; *i < ARRAY_LENGTH(&windows); (*i)++) { - if (s == ARRAY_ITEM(&windows, *i)) - return (0); - } - return (-1); -} - struct window * window_find_by_id(u_int id) { @@ -341,7 +331,11 @@ window_destroy(struct window *w) window_unzoom(w); - if (window_index(w, &i) != 0) + for (i = 0; i < ARRAY_LENGTH(&windows); i++) { + if (w == ARRAY_ITEM(&windows, i)) + break; + } + if (i == ARRAY_LENGTH(&windows)) fatalx("index not found"); ARRAY_SET(&windows, i, NULL); while (!ARRAY_EMPTY(&windows) && ARRAY_LAST(&windows) == NULL) From 8d66f4fba4972d45be64d108c7c8d952f85016a8 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Apr 2015 15:30:11 +0000 Subject: [PATCH 2/8] Change the windows array into an RB tree and fix some places where we were only looking at the first winlink for a window in a session. --- cmd-set-option.c | 4 +-- resize.c | 11 ++++---- server-client.c | 6 +---- server-window.c | 24 +++++++---------- server.c | 21 ++++----------- tmux.h | 6 ++++- window.c | 68 ++++++++++++++++-------------------------------- 7 files changed, 50 insertions(+), 90 deletions(-) diff --git a/cmd-set-option.c b/cmd-set-option.c index 01d691d5..e236b95d 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -176,9 +176,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq) /* Start or stop timers when automatic-rename changed. */ if (strcmp(oe->name, "automatic-rename") == 0) { - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) == NULL) - continue; + RB_FOREACH(w, windows, &windows) { if (options_get_number(&w->options, "automatic-rename")) queue_window_name(w); else if (event_initialized(&w->name_timer)) diff --git a/resize.c b/resize.c index 9ad73c81..5b89b093 100644 --- a/resize.c +++ b/resize.c @@ -49,7 +49,7 @@ recalculate_sizes(void) struct client *c; struct window *w; struct window_pane *wp; - u_int i, j, ssx, ssy, has, limit; + u_int i, ssx, ssy, has, limit; int flag, has_status, is_zoomed, forced; RB_FOREACH(s, sessions, &sessions) { @@ -57,8 +57,8 @@ recalculate_sizes(void) s->attached = 0; ssx = ssy = UINT_MAX; - for (j = 0; j < ARRAY_LENGTH(&clients); j++) { - c = ARRAY_ITEM(&clients, j); + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); if (c == NULL || c->flags & CLIENT_SUSPENDED) continue; if (c->session == s) { @@ -92,9 +92,8 @@ recalculate_sizes(void) s->sy = ssy; } - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - w = ARRAY_ITEM(&windows, i); - if (w == NULL || w->active == NULL) + RB_FOREACH(w, windows, &windows) { + if (w->active == NULL) continue; flag = options_get_number(&w->options, "aggressive-resize"); diff --git a/server-client.c b/server-client.c index c022a36f..e2f65e71 100644 --- a/server-client.c +++ b/server-client.c @@ -720,11 +720,7 @@ server_client_loop(void) * Any windows will have been redrawn as part of clients, so clear * their flags now. Also check pane focus and resize. */ - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - w = ARRAY_ITEM(&windows, i); - if (w == NULL) - continue; - + RB_FOREACH(w, windows, &windows) { w->flags &= ~WINDOW_REDRAW; TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->fd != -1) { diff --git a/server-window.c b/server-window.c index a2355701..f157da35 100644 --- a/server-window.c +++ b/server-window.c @@ -34,24 +34,20 @@ void server_window_loop(void) { struct window *w; - struct winlink *wl; struct session *s; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - w = ARRAY_ITEM(&windows, i); - if (w == NULL) - continue; + struct winlink *wl; + RB_FOREACH(w, windows, &windows) { RB_FOREACH(s, sessions, &sessions) { - wl = session_has(s, w); - if (wl == NULL) - continue; + RB_FOREACH(wl, winlinks, &s->windows) { + if (wl->window != w) + continue; - if (server_window_check_bell(s, wl) || - server_window_check_activity(s, wl) || - server_window_check_silence(s, wl)) - server_status_session(s); + if (server_window_check_bell(s, wl) || + server_window_check_activity(s, wl) || + server_window_check_silence(s, wl)) + server_status_session(s); + } } } } diff --git a/server.c b/server.c index bb96d9af..1183d64d 100644 --- a/server.c +++ b/server.c @@ -137,7 +137,7 @@ server_start(int lockfd, char *lockfile) logfile("server"); log_debug("server started, pid %ld", (long) getpid()); - ARRAY_INIT(&windows); + RB_INIT(&windows); RB_INIT(&all_window_panes); ARRAY_INIT(&clients); ARRAY_INIT(&dead_clients); @@ -438,14 +438,11 @@ server_child_signal(void) void server_child_exited(pid_t pid, int status) { - struct window *w; + struct window *w, *w1; struct window_pane *wp; struct job *job; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) == NULL) - continue; + RB_FOREACH_SAFE(w, windows, &windows, w1) { TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->pid == pid) { wp->status = status; @@ -469,14 +466,11 @@ server_child_stopped(pid_t pid, int status) { struct window *w; struct window_pane *wp; - u_int i; if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU) return; - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) == NULL) - continue; + RB_FOREACH(w, windows, &windows) { TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->pid == pid) { if (killpg(pid, SIGCONT) != 0) @@ -493,18 +487,13 @@ server_second_callback(unused int fd, unused short events, unused void *arg) struct window *w; struct window_pane *wp; struct timeval tv; - u_int i; if (options_get_number(&global_s_options, "lock-server")) server_lock_server(); else server_lock_sessions(); - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - w = ARRAY_ITEM(&windows, i); - if (w == NULL) - continue; - + RB_FOREACH(w, windows, &windows) { TAILQ_FOREACH(wp, &w->panes, entry) { if (wp->mode != NULL && wp->mode->timer != NULL) wp->mode->timer(wp); diff --git a/tmux.h b/tmux.h index 52dc1529..e52b14f1 100644 --- a/tmux.h +++ b/tmux.h @@ -983,8 +983,10 @@ struct window { struct options options; u_int references; + + RB_ENTRY(window) entry; }; -ARRAY_DECL(windows, struct window *); +RB_HEAD(windows, window); /* Entry on local window list. */ struct winlink { @@ -2121,6 +2123,8 @@ void screen_reflow(struct screen *, u_int); /* window.c */ extern struct windows windows; extern struct window_pane_tree all_window_panes; +int window_cmp(struct window *, struct window *); +RB_PROTOTYPE(windows, window, entry, window_cmp); int winlink_cmp(struct winlink *, struct winlink *); RB_PROTOTYPE(winlinks, winlink, entry, winlink_cmp); int window_pane_cmp(struct window_pane *, struct window_pane *); diff --git a/window.c b/window.c index d8f29026..5ca8aa0c 100644 --- a/window.c +++ b/window.c @@ -64,6 +64,14 @@ void window_pane_error_callback(struct bufferevent *, short, void *); struct window_pane *window_pane_choose_best(struct window_pane_list *); +RB_GENERATE(windows, window, entry, window_cmp); + +int +window_cmp(struct window *w1, struct window *w2) +{ + return (w1->id - w2->id); +} + RB_GENERATE(winlinks, winlink, entry, winlink_cmp); int @@ -248,25 +256,18 @@ winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl) struct window * window_find_by_id(u_int id) { - struct window *w; - u_int i; + struct window w; - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - w = ARRAY_ITEM(&windows, i); - if (w != NULL && w->id == id) - return (w); - } - return (NULL); + w.id = id; + return (RB_FIND(windows, &windows, &w)); } struct window * window_create1(u_int sx, u_int sy) { struct window *w; - u_int i; w = xcalloc(1, sizeof *w); - w->id = next_window_id++; w->name = NULL; w->flags = 0; @@ -283,16 +284,11 @@ window_create1(u_int sx, u_int sy) if (options_get_number(&w->options, "automatic-rename")) queue_window_name(w); - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if (ARRAY_ITEM(&windows, i) == NULL) { - ARRAY_SET(&windows, i, w); - break; - } - } - if (i == ARRAY_LENGTH(&windows)) - ARRAY_ADD(&windows, w); w->references = 0; + w->id = next_window_id++; + RB_INSERT (windows, &windows, w); + return (w); } @@ -327,19 +323,9 @@ window_create(const char *name, int argc, char **argv, const char *path, void window_destroy(struct window *w) { - u_int i; - window_unzoom(w); - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if (w == ARRAY_ITEM(&windows, i)) - break; - } - if (i == ARRAY_LENGTH(&windows)) - fatalx("index not found"); - ARRAY_SET(&windows, i, NULL); - while (!ARRAY_EMPTY(&windows) && ARRAY_LAST(&windows) == NULL) - ARRAY_TRUNC(&windows, 1); + RB_REMOVE(windows, &windows, w); if (w->layout_root != NULL) layout_free(w); @@ -1328,26 +1314,18 @@ window_pane_find_right(struct window_pane *wp) void winlink_clear_flags(struct winlink *wl) { - struct winlink *wm; struct session *s; - struct window *w; - u_int i; + struct winlink *wl_loop; - for (i = 0; i < ARRAY_LENGTH(&windows); i++) { - if ((w = ARRAY_ITEM(&windows, i)) == NULL) - continue; - - RB_FOREACH(s, sessions, &sessions) { - if ((wm = session_has(s, w)) == NULL) + RB_FOREACH(s, sessions, &sessions) { + RB_FOREACH(wl_loop, winlinks, &s->windows) { + if (wl_loop->window != wl->window) + continue; + if ((wl_loop->flags & WINLINK_ALERTFLAGS) == 0) continue; - if (wm->window != wl->window) - continue; - if ((wm->flags & WINLINK_ALERTFLAGS) == 0) - continue; - - wm->flags &= ~WINLINK_ALERTFLAGS; - wm->window->flags &= ~WINDOW_ALERTFLAGS; + wl_loop->flags &= ~WINLINK_ALERTFLAGS; + wl_loop->window->flags &= ~WINDOW_ALERTFLAGS; server_status_session(s); } } From 9a453dd3546b2c3053e8e34bf4d6775b1a05d3a8 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Apr 2015 15:32:33 +0000 Subject: [PATCH 3/8] Make session_has return a flag, returning the first winlink found is a recipe for errors. --- resize.c | 2 +- server-fn.c | 4 ++-- session.c | 6 +++--- tmux.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/resize.c b/resize.c index 5b89b093..330c37b5 100644 --- a/resize.c +++ b/resize.c @@ -104,7 +104,7 @@ recalculate_sizes(void) if (flag) has = s->curw->window == w; else - has = session_has(s, w) != NULL; + has = session_has(s, w); if (has) { if (s->sx < ssx) ssx = s->sx; diff --git a/server-fn.c b/server-fn.c index 83ea9474..c5487aa6 100644 --- a/server-fn.c +++ b/server-fn.c @@ -199,7 +199,7 @@ server_status_window(struct window *w) */ RB_FOREACH(s, sessions, &sessions) { - if (session_has(s, w) != NULL) + if (session_has(s, w)) server_status_session(s); } } @@ -268,7 +268,7 @@ server_kill_window(struct window *w) s = next_s; next_s = RB_NEXT(sessions, &sessions, s); - if (session_has(s, w) == NULL) + if (!session_has(s, w)) continue; server_unzoom_window(w); while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) { diff --git a/session.c b/session.c index 03ddb10d..c0535725 100644 --- a/session.c +++ b/session.c @@ -309,16 +309,16 @@ session_detach(struct session *s, struct winlink *wl) } /* Return if session has window. */ -struct winlink * +int session_has(struct session *s, struct window *w) { struct winlink *wl; RB_FOREACH(wl, winlinks, &s->windows) { if (wl->window == w) - return (wl); + return (1); } - return (NULL); + return (0); } struct winlink * diff --git a/tmux.h b/tmux.h index e52b14f1..a47218e5 100644 --- a/tmux.h +++ b/tmux.h @@ -2321,7 +2321,7 @@ struct winlink *session_new(struct session *, const char *, int, char **, struct winlink *session_attach(struct session *, struct window *, int, char **); int session_detach(struct session *, struct winlink *); -struct winlink *session_has(struct session *, struct window *); +int session_has(struct session *, struct window *); int session_next(struct session *, int); int session_previous(struct session *, int); int session_select(struct session *, int); From ab73997cc5bd652370beef93db5fca439448734a Mon Sep 17 00:00:00 2001 From: deraadt Date: Thu, 23 Apr 2015 07:45:50 +0000 Subject: [PATCH 4/8] use reallocarray instead of calloc; avoid the zero before infill ok nicm --- grid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grid.c b/grid.c index ef7c374b..2dc266d7 100644 --- a/grid.c +++ b/grid.c @@ -657,7 +657,7 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy, memcpy(dstl, srcl, sizeof *dstl); if (srcl->cellsize != 0) { - dstl->celldata = xcalloc( + dstl->celldata = xreallocarray(NULL, srcl->cellsize, sizeof *dstl->celldata); memcpy(dstl->celldata, srcl->celldata, srcl->cellsize * sizeof *dstl->celldata); From a5a873dcccaabd55dbb0ad32abafbf1049316392 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 24 Apr 2015 20:58:44 +0000 Subject: [PATCH 5/8] Set up signal handler earlier so that we don't get zombies, reported by sobrado@. --- client.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client.c b/client.c index d3ff05a6..e2ffa546 100644 --- a/client.c +++ b/client.c @@ -262,6 +262,9 @@ client_main(int argc, char **argv, int flags) setproctitle("client (%s)", socket_path); logfile("client"); + /* Establish signal handlers. */ + set_signals(client_signal); + /* Initialize the client socket and start the server. */ fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER); if (fd == -1) { @@ -301,9 +304,6 @@ client_main(int argc, char **argv, int flags) tcsetattr(STDIN_FILENO, TCSANOW, &tio); } - /* Establish signal handlers. */ - set_signals(client_signal); - /* Send identify messages. */ client_send_identify(flags); From 5a2d0533a84a13613fb356b66ed8ada2a65f6edf Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 24 Apr 2015 21:38:18 +0000 Subject: [PATCH 6/8] Allow choice options (multiple states) to be toggled between states 0 and 1. --- cmd-set-option.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/cmd-set-option.c b/cmd-set-option.c index e236b95d..e0d1ae6c 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -289,9 +289,15 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq, { struct options_entry *o; - if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) { - cmdq_error(cmdq, "empty value"); - return (-1); + switch (oe->type) { + case OPTIONS_TABLE_FLAG: + case OPTIONS_TABLE_CHOICE: + break; + default: + if (value == NULL) { + cmdq_error(cmdq, "empty value"); + return (-1); + } } o = NULL; @@ -455,21 +461,27 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq, const char **choicep; int n, choice = -1; - n = 0; - for (choicep = oe->choices; *choicep != NULL; choicep++) { - n++; - if (strncmp(*choicep, value, strlen(value)) != 0) - continue; + if (value == NULL) { + choice = options_get_number(oo, oe->name); + if (choice < 2) + choice = !choice; + } else { + n = 0; + for (choicep = oe->choices; *choicep != NULL; choicep++) { + n++; + if (strncmp(*choicep, value, strlen(value)) != 0) + continue; - if (choice != -1) { - cmdq_error(cmdq, "ambiguous value: %s", value); + if (choice != -1) { + cmdq_error(cmdq, "ambiguous value: %s", value); + return (NULL); + } + choice = n - 1; + } + if (choice == -1) { + cmdq_error(cmdq, "unknown value: %s", value); return (NULL); } - choice = n - 1; - } - if (choice == -1) { - cmdq_error(cmdq, "unknown value: %s", value); - return (NULL); } return (options_set_number(oo, oe->name, choice)); From 583b4ab72b7bf66fda8ab63a08fe435483de5e5a Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 24 Apr 2015 22:19:36 +0000 Subject: [PATCH 7/8] Set working directory for run-shell and if-shell. --- cmd-if-shell.c | 15 ++++++++++++--- cmd-run-shell.c | 15 ++++++++++++--- job.c | 5 ++++- status.c | 2 +- tmux.h | 2 +- window-copy.c | 2 +- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/cmd-if-shell.c b/cmd-if-shell.c index cdd2135c..a307bd2f 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -66,16 +66,24 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) struct winlink *wl = NULL; struct window_pane *wp = NULL; struct format_tree *ft; + int cwd; - if (args_has(args, 't')) + if (args_has(args, 't')) { wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); - else { + cwd = wp->cwd; + } else { c = cmd_find_client(cmdq, NULL, 1); if (c != NULL && c->session != NULL) { s = c->session; wl = s->curw; wp = wl->window->active; } + if (cmdq->client != NULL && cmdq->client->session == NULL) + cwd = cmdq->client->cwd; + else if (s != NULL) + cwd = s->cwd; + else + cwd = -1; } ft = format_create(); @@ -118,7 +126,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) cmdq->references++; cdata->references = 1; - job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata); + job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free, + cdata); free(shellcmd); if (cdata->bflag) diff --git a/cmd-run-shell.c b/cmd-run-shell.c index 5d6d178b..134cbeba 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -80,16 +80,24 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) struct winlink *wl = NULL; struct window_pane *wp = NULL; struct format_tree *ft; + int cwd; - if (args_has(args, 't')) + if (args_has(args, 't')) { wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); - else { + cwd = wp->cwd; + } else { c = cmd_find_client(cmdq, NULL, 1); if (c != NULL && c->session != NULL) { s = c->session; wl = s->curw; wp = wl->window->active; } + if (cmdq->client != NULL && cmdq->client->session == NULL) + cwd = cmdq->client->cwd; + else if (s != NULL) + cwd = s->cwd; + else + cwd = -1; } ft = format_create(); @@ -105,7 +113,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) cdata->cmdq = cmdq; cmdq->references++; - job_run(shellcmd, s, cmd_run_shell_callback, cmd_run_shell_free, cdata); + job_run(shellcmd, s, cwd, cmd_run_shell_callback, cmd_run_shell_free, + cdata); if (cdata->bflag) return (CMD_RETURN_NORMAL); diff --git a/job.c b/job.c index c04a70b0..5675eec3 100644 --- a/job.c +++ b/job.c @@ -41,7 +41,7 @@ struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs); /* Start a job running, if it isn't already. */ struct job * -job_run(const char *cmd, struct session *s, +job_run(const char *cmd, struct session *s, int cwd, void (*callbackfn)(struct job *), void (*freefn)(void *), void *data) { struct job *job; @@ -67,6 +67,9 @@ job_run(const char *cmd, struct session *s, case 0: /* child */ clear_signals(1); + if (cwd != -1 && fchdir(cwd) != 0) + chdir("/"); + environ_push(&env); environ_free(&env); diff --git a/status.c b/status.c index ae5d99ab..fd0292c7 100644 --- a/status.c +++ b/status.c @@ -515,7 +515,7 @@ status_find_job(struct client *c, char **iptr) /* If not found at all, start the job and add to the tree. */ if (so == NULL) { - job_run(cmd, NULL, status_job_callback, status_job_free, c); + job_run(cmd, NULL, -1, status_job_callback, status_job_free, c); c->references++; so = xmalloc(sizeof *so); diff --git a/tmux.h b/tmux.h index a47218e5..9a6e4c83 100644 --- a/tmux.h +++ b/tmux.h @@ -1613,7 +1613,7 @@ int options_table_find(const char *, const struct options_table_entry **, /* job.c */ extern struct joblist all_jobs; -struct job *job_run(const char *, struct session *, +struct job *job_run(const char *, struct session *, int, void (*)(struct job *), void (*)(void *), void *); void job_free(struct job *); void job_died(struct job *, int); diff --git a/window-copy.c b/window-copy.c index eb00131e..7d5bae4c 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1465,7 +1465,7 @@ window_copy_copy_pipe(struct window_pane *wp, struct session *sess, format_defaults(ft, NULL, sess, NULL, wp); expanded = format_expand(ft, arg); - job = job_run(expanded, sess, NULL, NULL, NULL); + job = job_run(expanded, sess, -1, NULL, NULL, NULL); bufferevent_write(job->event, buf, len); free(expanded); From aeedb464a6ee038289ddcfefae437928ab020cb1 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 24 Apr 2015 23:17:11 +0000 Subject: [PATCH 8/8] Convert clients list into a TAILQ. --- cmd-attach-session.c | 8 ++--- cmd-choose-client.c | 24 ++++++++------- cmd-detach-client.c | 13 +++----- cmd-list-clients.c | 15 +++++----- cmd-set-option.c | 6 ++-- cmd.c | 26 ++++++++-------- control-notify.c | 28 +++++------------ notify.c | 6 ++-- resize.c | 7 ++--- server-client.c | 45 +++++----------------------- server-fn.c | 58 ++++++++++-------------------------- server-window.c | 24 +++++---------- server.c | 71 +++++++++++++++++--------------------------- tmux.h | 4 ++- tty.c | 6 ++-- 15 files changed, 118 insertions(+), 223 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index a67ec82c..79e14616 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -51,7 +51,6 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, struct window_pane *wp = NULL; const char *update; char *cause; - u_int i; int fd; struct format_tree *ft; char *cp; @@ -92,11 +91,8 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, * Can't use server_write_session in case attaching to * the same session as currently attached to. */ - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s) - continue; - if (c == cmdq->client) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != s || c == cmdq->client) continue; server_write_client(c, MSG_DETACH, c->session->name, diff --git a/cmd-choose-client.c b/cmd-choose-client.c index 3002f7ba..49fe2a34 100644 --- a/cmd-choose-client.c +++ b/cmd-choose-client.c @@ -59,7 +59,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq) struct winlink *wl; const char *template; char *action; - u_int i, idx, cur; + u_int idx, cur; if ((c = cmd_current_client(cmdq)) == NULL) { cmdq_error(cmdq, "no client available"); @@ -81,24 +81,24 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq) action = xstrdup("detach-client -t '%%'"); cur = idx = 0; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c1 = ARRAY_ITEM(&clients, i); - if (c1 == NULL || c1->session == NULL || c1->tty.path == NULL) + TAILQ_FOREACH(c1, &clients, entry) { + if (c1->session == NULL || c1->tty.path == NULL) continue; if (c1 == cmdq->client) cur = idx; - idx++; cdata = window_choose_data_create(TREE_OTHER, c, c->session); - cdata->idx = i; + cdata->idx = idx; cdata->ft_template = xstrdup(template); - format_add(cdata->ft, "line", "%u", i); + format_add(cdata->ft, "line", "%u", idx); format_defaults(cdata->ft, c1, NULL, NULL, NULL); cdata->command = cmd_template_replace(action, c1->tty.path, 1); window_choose_add(wl->window->active, cdata); + + idx++; } free(action); @@ -112,15 +112,19 @@ void cmd_choose_client_callback(struct window_choose_data *cdata) { struct client *c; + u_int idx; if (cdata == NULL) return; if (cdata->start_client->flags & CLIENT_DEAD) return; - if (cdata->idx > ARRAY_LENGTH(&clients) - 1) - return; - c = ARRAY_ITEM(&clients, cdata->idx); + idx = 0; + TAILQ_FOREACH(c, &clients, entry) { + if (idx == cdata->idx) + break; + idx++; + } if (c == NULL || c->session == NULL) return; diff --git a/cmd-detach-client.c b/cmd-detach-client.c index 7f87d2c6..4bae9997 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -51,7 +51,6 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq) struct client *c, *cloop; struct session *s; enum msgtype msgtype; - u_int i; if (self->entry == &cmd_suspend_client_entry) { if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL) @@ -72,9 +71,8 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq) if (s == NULL) return (CMD_RETURN_ERROR); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - cloop = ARRAY_ITEM(&clients, i); - if (cloop == NULL || cloop->session != s) + TAILQ_FOREACH(cloop, &clients, entry) { + if (cloop->session != s) continue; server_write_client(cloop, msgtype, cloop->session->name, @@ -88,11 +86,8 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq) return (CMD_RETURN_ERROR); if (args_has(args, 'a')) { - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - cloop = ARRAY_ITEM(&clients, i); - if (cloop == NULL || cloop->session == NULL) - continue; - if (cloop == c) + TAILQ_FOREACH(cloop, &clients, entry) { + if (cloop->session == NULL || cloop == c) continue; server_write_client(cloop, msgtype, cloop->session->name, diff --git a/cmd-list-clients.c b/cmd-list-clients.c index 893a6d05..372b5283 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -51,7 +51,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq) struct session *s; struct format_tree *ft; const char *template; - u_int i; + u_int idx; char *line; if (args_has(args, 't')) { @@ -64,16 +64,13 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq) if ((template = args_get(args, 'F')) == NULL) template = LIST_CLIENTS_TEMPLATE; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - - if (s != NULL && s != c->session) + idx = 0; + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == NULL || (s != NULL && s != c->session)) continue; ft = format_create(); - format_add(ft, "line", "%u", i); + format_add(ft, "line", "%u", idx); format_defaults(ft, c, NULL, NULL, NULL); line = format_expand(ft, template); @@ -81,6 +78,8 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq) free(line); format_free(ft); + + idx++; } return (CMD_RETURN_NORMAL); diff --git a/cmd-set-option.c b/cmd-set-option.c index e0d1ae6c..83d31b93 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -91,7 +91,6 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq) struct options *oo; struct window *w; const char *optstr, *valstr; - u_int i; /* Get the option name and value. */ optstr = args->argv[0]; @@ -186,9 +185,8 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq) /* Update sizes and redraw. May not need it but meh. */ recalculate_sizes(); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL) server_redraw_client(c); } diff --git a/cmd.c b/cmd.c index 991e079b..b81ffb36 100644 --- a/cmd.c +++ b/cmd.c @@ -116,10 +116,12 @@ const struct cmd_entry *cmd_table[] = { NULL }; +ARRAY_DECL(client_list, struct client *); + int cmd_session_better(struct session *, struct session *, int); struct session *cmd_choose_session_list(struct sessionslist *); struct session *cmd_choose_session(int); -struct client *cmd_choose_client(struct clients *); +struct client *cmd_choose_client(struct client_list *); struct client *cmd_lookup_client(const char *); struct session *cmd_lookup_session(struct cmd_q *, const char *, int *); struct session *cmd_lookup_session_id(const char *); @@ -452,8 +454,7 @@ cmd_current_client(struct cmd_q *cmdq) { struct session *s; struct client *c; - struct clients cc; - u_int i; + struct client_list cc; if (cmdq->client != NULL && cmdq->client->session != NULL) return (cmdq->client); @@ -465,9 +466,7 @@ cmd_current_client(struct cmd_q *cmdq) s = cmd_current_session(cmdq, 0); if (s != NULL && !(s->flags & SESSION_UNATTACHED)) { ARRAY_INIT(&cc); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if ((c = ARRAY_ITEM(&clients, i)) == NULL) - continue; + TAILQ_FOREACH(c, &clients, entry) { if (s == c->session) ARRAY_ADD(&cc, c); } @@ -478,12 +477,17 @@ cmd_current_client(struct cmd_q *cmdq) return (c); } - return (cmd_choose_client(&clients)); + ARRAY_INIT(&cc); + TAILQ_FOREACH(c, &clients, entry) + ARRAY_ADD(&cc, c); + c = cmd_choose_client(&cc); + ARRAY_FREE(&cc); + return (c); } /* Choose the most recently used client from a list. */ struct client * -cmd_choose_client(struct clients *cc) +cmd_choose_client(struct client_list *cc) { struct client *c, *cbest; struct timeval *tv = NULL; @@ -615,11 +619,9 @@ cmd_lookup_client(const char *name) { struct client *c; const char *path; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL || c->tty.path == NULL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == NULL || c->tty.path == NULL) continue; path = c->tty.path; diff --git a/control-notify.c b/control-notify.c index 747ef5b4..943d670c 100644 --- a/control-notify.c +++ b/control-notify.c @@ -64,11 +64,9 @@ control_notify_window_layout_changed(struct window *w) struct session *s; struct format_tree *ft; struct winlink *wl; - u_int i; const char *template; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) continue; s = c->session; @@ -100,10 +98,8 @@ control_notify_window_unlinked(unused struct session *s, struct window *w) { struct client *c; struct session *cs; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) continue; cs = c->session; @@ -120,10 +116,8 @@ control_notify_window_linked(unused struct session *s, struct window *w) { struct client *c; struct session *cs; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) continue; cs = c->session; @@ -140,10 +134,8 @@ control_notify_window_renamed(struct window *w) { struct client *c; struct session *cs; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL) continue; cs = c->session; @@ -174,10 +166,8 @@ void control_notify_session_renamed(struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) continue; @@ -189,10 +179,8 @@ void control_notify_session_created(unused struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) continue; @@ -204,10 +192,8 @@ void control_notify_session_close(unused struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); + TAILQ_FOREACH(c, &clients, entry) { if (!CONTROL_SHOULD_NOTIFY_CLIENT(c)) continue; diff --git a/notify.c b/notify.c index 75a16de9..19bf17e8 100644 --- a/notify.c +++ b/notify.c @@ -136,7 +136,6 @@ void notify_input(struct window_pane *wp, struct evbuffer *input) { struct client *c; - u_int i; /* * notify_input() is not queued and only does anything when @@ -145,9 +144,8 @@ notify_input(struct window_pane *wp, struct evbuffer *input) if (!notify_enabled) return; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && (c->flags & CLIENT_CONTROL)) + TAILQ_FOREACH(c, &clients, entry) { + if (c->flags & CLIENT_CONTROL) control_notify_input(c, wp, input); } } diff --git a/resize.c b/resize.c index 330c37b5..3606bfeb 100644 --- a/resize.c +++ b/resize.c @@ -49,7 +49,7 @@ recalculate_sizes(void) struct client *c; struct window *w; struct window_pane *wp; - u_int i, ssx, ssy, has, limit; + u_int ssx, ssy, has, limit; int flag, has_status, is_zoomed, forced; RB_FOREACH(s, sessions, &sessions) { @@ -57,9 +57,8 @@ recalculate_sizes(void) s->attached = 0; ssx = ssy = UINT_MAX; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->flags & CLIENT_SUSPENDED) + TAILQ_FOREACH(c, &clients, entry) { + if (c->flags & CLIENT_SUSPENDED) continue; if (c->session == s) { if (c->tty.sx < ssx) diff --git a/server-client.c b/server-client.c index e2f65e71..a0f81b73 100644 --- a/server-client.c +++ b/server-client.c @@ -60,7 +60,6 @@ void server_client_create(int fd) { struct client *c; - u_int i; setblocking(fd, 0); @@ -108,13 +107,7 @@ server_client_create(int fd) evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if (ARRAY_ITEM(&clients, i) == NULL) { - ARRAY_SET(&clients, i, c); - return; - } - } - ARRAY_ADD(&clients, c); + TAILQ_INSERT_TAIL(&clients, c, entry); log_debug("new client %d", fd); } @@ -148,10 +141,7 @@ server_client_lost(struct client *c) struct message_entry *msg; u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if (ARRAY_ITEM(&clients, i) == c) - ARRAY_SET(&clients, i, NULL); - } + TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %d", c->ibuf.fd); /* @@ -205,14 +195,7 @@ server_client_lost(struct client *c) if (event_initialized(&c->event)) event_del(&c->event); - for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) { - if (ARRAY_ITEM(&dead_clients, i) == NULL) { - ARRAY_SET(&dead_clients, i, c); - break; - } - } - if (i == ARRAY_LENGTH(&dead_clients)) - ARRAY_ADD(&dead_clients, c); + TAILQ_INSERT_TAIL(&dead_clients, c, entry); c->flags |= CLIENT_DEAD; server_add_accept(0); /* may be more file descriptors now */ @@ -263,16 +246,14 @@ server_client_status_timer(void) struct client *c; struct session *s; struct timeval tv; - u_int i; int interval; time_t difference; if (gettimeofday(&tv, NULL) != 0) fatal("gettimeofday failed"); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == NULL) continue; if (c->message_string != NULL || c->prompt_string != NULL) { /* @@ -702,13 +683,8 @@ server_client_loop(void) struct client *c; struct window *w; struct window_pane *wp; - u_int i; - - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL) - continue; + TAILQ_FOREACH(c, &clients, entry) { server_client_check_exit(c); if (c->session != NULL) { server_client_check_redraw(c); @@ -755,7 +731,6 @@ server_client_check_resize(struct window_pane *wp) void server_client_check_focus(struct window_pane *wp) { - u_int i; struct client *c; int push; @@ -783,12 +758,8 @@ server_client_check_focus(struct window_pane *wp) * If our window is the current window in any focused clients with an * attached session, we're focused. */ - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - - if (!(c->flags & CLIENT_FOCUSED)) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == NULL || !(c->flags & CLIENT_FOCUSED)) continue; if (c->session->flags & SESSION_UNATTACHED) continue; diff --git a/server-fn.c b/server-fn.c index c5487aa6..85067a87 100644 --- a/server-fn.c +++ b/server-fn.c @@ -77,12 +77,8 @@ server_write_session(struct session *s, enum msgtype type, const void *buf, size_t len) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; + TAILQ_FOREACH(c, &clients, entry) { if (c->session == s) server_write_client(c, type, buf, len); } @@ -104,12 +100,8 @@ void server_redraw_session(struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; + TAILQ_FOREACH(c, &clients, entry) { if (c->session == s) server_redraw_client(c); } @@ -132,12 +124,8 @@ void server_status_session(struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; + TAILQ_FOREACH(c, &clients, entry) { if (c->session == s) server_status_client(c); } @@ -160,13 +148,9 @@ void server_redraw_window(struct window *w) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (c->session->curw->window == w) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL && c->session->curw->window == w) server_redraw_client(c); } w->flags |= WINDOW_REDRAW; @@ -176,13 +160,9 @@ void server_redraw_window_borders(struct window *w) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - if (c->session->curw->window == w) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL && c->session->curw->window == w) c->flags |= CLIENT_BORDERS; } } @@ -208,13 +188,10 @@ void server_lock(void) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL) - continue; - server_lock_client(c); + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL) + server_lock_client(c); } } @@ -222,13 +199,10 @@ void server_lock_session(struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL || c->session != s) - continue; - server_lock_client(c); + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == s) + server_lock_client(c); } } @@ -430,16 +404,14 @@ server_destroy_session(struct session *s) { struct client *c; struct session *s_new; - u_int i; if (!options_get_number(&s->options, "detach-on-destroy")) s_new = server_next_session(s); else s_new = NULL; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != s) continue; if (s_new == NULL) { c->session = NULL; diff --git a/server-window.c b/server-window.c index f157da35..4385dd90 100644 --- a/server-window.c +++ b/server-window.c @@ -58,7 +58,6 @@ server_window_check_bell(struct session *s, struct winlink *wl) { struct client *c; struct window *w = wl->window; - u_int i; int action, visual; if (!(w->flags & WINDOW_BELL) || wl->flags & WINLINK_BELL) @@ -74,9 +73,8 @@ server_window_check_bell(struct session *s, struct winlink *wl) action = options_get_number(&s->options, "bell-action"); if (action == BELL_NONE) return (0); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s || c->flags & CLIENT_CONTROL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != s || c->flags & CLIENT_CONTROL) continue; if (!visual) { if (c->session->curw->window == w || action == BELL_ANY) @@ -98,7 +96,6 @@ server_window_check_activity(struct session *s, struct winlink *wl) { struct client *c; struct window *w = wl->window; - u_int i; if (s->curw->window == w) w->flags &= ~WINDOW_ACTIVITY; @@ -116,9 +113,8 @@ server_window_check_activity(struct session *s, struct winlink *wl) wl->flags |= WINLINK_ACTIVITY; if (options_get_number(&s->options, "visual-activity")) { - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != s) continue; status_message_set(c, "Activity in window %d", wl->idx); } @@ -134,7 +130,6 @@ server_window_check_silence(struct session *s, struct winlink *wl) struct client *c; struct window *w = wl->window; struct timeval timer; - u_int i; int silence_interval, timer_difference; if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE) @@ -167,9 +162,8 @@ server_window_check_silence(struct session *s, struct winlink *wl) wl->flags |= WINLINK_SILENCE; if (options_get_number(&s->options, "visual-silence")) { - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session != s) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != s) continue; status_message_set(c, "Silence in window %d", wl->idx); } @@ -183,11 +177,9 @@ void ring_bell(struct session *s) { struct client *c; - u_int i; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session == s && !(c->flags & CLIENT_CONTROL)) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == s && !(c->flags & CLIENT_CONTROL)) tty_bell(&c->tty); } } diff --git a/server.c b/server.c index 1183d64d..ba161c4b 100644 --- a/server.c +++ b/server.c @@ -139,8 +139,8 @@ server_start(int lockfd, char *lockfile) RB_INIT(&windows); RB_INIT(&all_window_panes); - ARRAY_INIT(&clients); - ARRAY_INIT(&dead_clients); + TAILQ_INIT(&clients); + TAILQ_INIT(&dead_clients); RB_INIT(&sessions); RB_INIT(&dead_sessions); TAILQ_INIT(&session_groups); @@ -166,7 +166,7 @@ server_start(int lockfd, char *lockfile) cfg_cmd_q->emptyfn = cfg_default_done; cfg_finished = 0; cfg_references = 1; - cfg_client = ARRAY_FIRST(&clients); + cfg_client = TAILQ_FIRST(&clients); if (cfg_client != NULL) cfg_client->references++; @@ -212,16 +212,14 @@ int server_should_shutdown(void) { struct client *c; - u_int i; if (!options_get_number(&global_options, "exit-unattached")) { if (!RB_EMPTY(&sessions)) return (0); } - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL && c->session != NULL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session != NULL) return (0); } @@ -230,10 +228,8 @@ server_should_shutdown(void) * clients but don't actually exit until they've gone. */ cmd_wait_for_flush(); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - if (ARRAY_ITEM(&clients, i) != NULL) - return (0); - } + if (!TAILQ_EMPTY(&clients)) + return (0); return (1); } @@ -242,55 +238,42 @@ server_should_shutdown(void) void server_send_shutdown(void) { - struct client *c; - struct session *s, *next_s; - u_int i; + struct client *c, *c1; + struct session *s, *s1; cmd_wait_for_flush(); - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c != NULL) { - if (c->flags & (CLIENT_BAD|CLIENT_SUSPENDED)) - server_client_lost(c); - else - server_write_client(c, MSG_SHUTDOWN, NULL, 0); - c->session = NULL; - } + TAILQ_FOREACH_SAFE(c, &clients, entry, c1) { + if (c->flags & (CLIENT_BAD|CLIENT_SUSPENDED)) + server_client_lost(c); + else + server_write_client(c, MSG_SHUTDOWN, NULL, 0); + c->session = NULL; } - s = RB_MIN(sessions, &sessions); - while (s != NULL) { - next_s = RB_NEXT(sessions, &sessions, s); + RB_FOREACH_SAFE(s, sessions, &sessions, s1) session_destroy(s); - s = next_s; - } } /* Free dead, unreferenced clients and sessions. */ void server_clean_dead(void) { - struct session *s, *next_s; - struct client *c; - u_int i; + struct session *s, *s1; + struct client *c, *c1; - s = RB_MIN(sessions, &dead_sessions); - while (s != NULL) { - next_s = RB_NEXT(sessions, &dead_sessions, s); - if (s->references == 0) { - RB_REMOVE(sessions, &dead_sessions, s); - free(s->name); - free(s); - } - s = next_s; + RB_FOREACH_SAFE(s, sessions, &dead_sessions, s1) { + if (s->references != 0) + continue; + RB_REMOVE(sessions, &dead_sessions, s); + free(s->name); + free(s); } - for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) { - c = ARRAY_ITEM(&dead_clients, i); - if (c == NULL || c->references != 0) + TAILQ_FOREACH_SAFE(c, &dead_clients, entry, c1) { + if (c->references != 0) continue; - ARRAY_SET(&dead_clients, i, NULL); + TAILQ_REMOVE(&dead_clients, c, entry); free(c); } } diff --git a/tmux.h b/tmux.h index 9a6e4c83..c38149ab 100644 --- a/tmux.h +++ b/tmux.h @@ -1349,8 +1349,10 @@ struct client { struct cmd_q *cmdq; int references; + + TAILQ_ENTRY(client) entry; }; -ARRAY_DECL(clients, struct client *); +TAILQ_HEAD(clients, client); /* Parsed arguments structures. */ struct args_entry { diff --git a/tty.c b/tty.c index a5067b12..aae7b893 100644 --- a/tty.c +++ b/tty.c @@ -708,7 +708,6 @@ tty_write( { struct window_pane *wp = ctx->wp; struct client *c; - u_int i; /* wp can be NULL if updating the screen but not the terminal. */ if (wp == NULL) @@ -719,9 +718,8 @@ tty_write( if (!window_pane_visible(wp) || wp->flags & PANE_DROP) return; - for (i = 0; i < ARRAY_LENGTH(&clients); i++) { - c = ARRAY_ITEM(&clients, i); - if (c == NULL || c->session == NULL || c->tty.term == NULL) + TAILQ_FOREACH(c, &clients, entry) { + if (c->session == NULL || c->tty.term == NULL) continue; if (c->flags & CLIENT_SUSPENDED) continue;