diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2013-03-25 10:09:08 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2013-03-25 10:09:08 +0000 |
commit | 516170a1184d33b875899c66a0113a856ec7ea77 (patch) | |
tree | d35ddd15ff98e66968326911d04a47f00708b855 | |
parent | fefe4f7b4ec439afa7d3637dc9967f7788433dd1 (diff) |
Add a wait-for command which blocks a client on a named channel until it
is woken up again (with wait-for -S). From Thiago Padilha.
-rw-r--r-- | usr.bin/tmux/Makefile | 3 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-wait-for.c | 124 | ||||
-rw-r--r-- | usr.bin/tmux/cmd.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 15 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 5 |
5 files changed, 146 insertions, 4 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile index 222442cc7fe..bf42499003b 100644 --- a/usr.bin/tmux/Makefile +++ b/usr.bin/tmux/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.65 2013/03/24 09:54:10 nicm Exp $ +# $OpenBSD: Makefile,v 1.66 2013/03/25 10:09:05 nicm Exp $ PROG= tmux SRCS= arguments.c \ @@ -77,6 +77,7 @@ SRCS= arguments.c \ cmd-switch-client.c \ cmd-unbind-key.c \ cmd-unlink-window.c \ + cmd-wait-for.c \ cmd.c \ cmd-queue.c \ colour.c \ diff --git a/usr.bin/tmux/cmd-wait-for.c b/usr.bin/tmux/cmd-wait-for.c new file mode 100644 index 00000000000..216775f66db --- /dev/null +++ b/usr.bin/tmux/cmd-wait-for.c @@ -0,0 +1,124 @@ +/* $OpenBSD: cmd-wait-for.c,v 1.1 2013/03/25 10:09:05 nicm Exp $ */ + +/* + * Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net> + * Copyright (c) 2013 Thiago de Arruda <tpadilha84@gmail.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <stdlib.h> +#include <string.h> + +#include "tmux.h" + +/* + * Block or wake a client on a named wait channel. + */ + +enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *); + +const struct cmd_entry cmd_wait_for_entry = { + "wait-for", "wait", + "S", 1, 1, + "[-S] channel", + 0, + NULL, + NULL, + cmd_wait_for_exec +}; + +struct wait_channel { + const char *name; + TAILQ_HEAD(, cmd_q) waiters; + + RB_ENTRY(wait_channel) entry; +}; +RB_HEAD(wait_channels, wait_channel); +struct wait_channels wait_channels = RB_INITIALIZER(wait_channels); + +int wait_channel_cmp(struct wait_channel *, struct wait_channel *); +RB_PROTOTYPE(wait_channels, wait_channel, entry, wait_channel_cmp); +RB_GENERATE(wait_channels, wait_channel, entry, wait_channel_cmp); + +int +wait_channel_cmp(struct wait_channel *wc1, struct wait_channel *wc2) +{ + return (strcmp(wc1->name, wc2->name)); +} + +enum cmd_retval cmd_wait_for_signal(struct cmd_q *, const char *, + struct wait_channel *); +enum cmd_retval cmd_wait_for_wait(struct cmd_q *, const char *, + struct wait_channel *); + +enum cmd_retval +cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq) +{ + struct args *args = self->args; + const char *name = args->argv[0]; + struct wait_channel *wc, wc0; + + wc0.name = name; + wc = RB_FIND(wait_channels, &wait_channels, &wc0); + + if (args_has(args, 'S')) + return (cmd_wait_for_signal(cmdq, name, wc)); + return (cmd_wait_for_wait(cmdq, name, wc)); +} + +enum cmd_retval +cmd_wait_for_signal(struct cmd_q *cmdq, const char *name, + struct wait_channel *wc) +{ + struct cmd_q *wq, *wq1; + + if (wc == NULL || TAILQ_EMPTY(&wc->waiters)) { + cmdq_error(cmdq, "no waiting clients on %s", name); + return (CMD_RETURN_ERROR); + } + + TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) { + TAILQ_REMOVE(&wc->waiters, wq, waitentry); + if (!cmdq_free(wq)) + cmdq_continue(wq); + } + RB_REMOVE(wait_channels, &wait_channels, wc); + free((void*) wc->name); + free(wc); + + return (CMD_RETURN_NORMAL); +} + +enum cmd_retval +cmd_wait_for_wait(struct cmd_q *cmdq, const char *name, + struct wait_channel *wc) +{ + if (cmdq->client == NULL || cmdq->client->session != NULL) { + cmdq_error(cmdq, "not able to wait"); + return (CMD_RETURN_ERROR); + } + + if (wc == NULL) { + wc = xmalloc(sizeof *wc); + wc->name = xstrdup(name); + TAILQ_INIT(&wc->waiters); + RB_INSERT(wait_channels, &wait_channels, wc); + } + TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry); + cmdq->references++; + + return (CMD_RETURN_WAIT); +} diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index ba1dd65abc6..569728a58a8 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.81 2013/03/25 10:04:44 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.82 2013/03/25 10:09:05 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -113,6 +113,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_switch_client_entry, &cmd_unbind_key_entry, &cmd_unlink_window_entry, + &cmd_wait_for_entry, NULL }; diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index a65234f921a..8f359580a30 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.341 2013/03/25 10:05:35 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.342 2013/03/25 10:09:05 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -3549,6 +3549,19 @@ If the command doesn't return success, the exit status is also displayed. .It Ic server-info .D1 (alias: Ic info ) Show server information and terminal details. +.It Xo Ic wait-for +.Fl S +.Ar channel +.Xc +.D1 (alias: Ic wait ) +When used without +.Fl S , +prevents the client from exiting until woken using +.Ic wait-for +.Fl S +with the same channel. +This command only works from outside +.Nm . .El .Sh TERMINFO EXTENSIONS .Nm diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index e287d2d9ac7..4893f62730b 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.400 2013/03/25 10:05:35 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.401 2013/03/25 10:09:07 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -1420,6 +1420,8 @@ struct cmd_q { void *data; struct msg_command_data *msgdata; + + TAILQ_ENTRY(cmd_q) waitentry; }; /* Command definition. */ @@ -1839,6 +1841,7 @@ extern const struct cmd_entry cmd_switch_client_entry; extern const struct cmd_entry cmd_unbind_key_entry; extern const struct cmd_entry cmd_unlink_window_entry; extern const struct cmd_entry cmd_up_pane_entry; +extern const struct cmd_entry cmd_wait_for_entry; /* cmd-attach-session.c */ enum cmd_retval cmd_attach_session(struct cmd_q *, const char*, int, int); |