OpenBSD patchset 1114 (pass stdin/stdout/stderr buffers, not fds)
made the clients a bit too eager to read stdin. Defer reading from
stdin (and sending buffers to an indifferent server via MSG_STDIN)
until the server explicitly requests such processing.

Without something like this, pasting a series of commands into
a shell would only execute the commands through the first tmux
command: the first tmux client would drain the remaining commands
from its stdin (shared with the shell) and send the data to the
server (where the it would simply be ignored).

A new server-to-client message is added, so the tmux protocol
version is bumped, making new clients/servers incompatible with old
servers/clients.

---

Similar to the mention above, I found this problem while pasting
commands into a shell inside tmux. An alternate way to reproduce
this situation is to feed a shell from stdin (this works outside
a tmux session and without paste functionality from the external
terminal emulator):

    echo '
    l=test-stdin-control
    t=stdin-control
    #tmux() { </dev/null command tmux "$@"; }
    tmux -L "$l" new-session -ds "$t"
    echo "buffer from $$" |
    command tmux -L "$l" load-buffer -
    tmux -L "$l" new-window  -dt "$t"
    tmux -L "$l" list-buffers
    tmux -L "$l" list-windows -t "$t"
    tmux -L "$l" save-buffer - | xxd
    tmux -L "$l" kill-session -t "$t"
    ' |
    sh -x

Without this change, only the first successful tmux command
(new-session) is ever executed. The rest of the input is slurped up
by that first client and sent as MSG_STDIN messages that are simply
ignored by the server (since kill-session does not set a stdin
callback).

Uncommenting the commented line can be used as a workaround, but it
seems a unnecessary for every tmux command to always drain stdin
unless it is explicitly restrained from doing so.

My initial encounter with this problem was a bit more subtle and
disconcerting. I have zsh configured to issue some tmux commands as
a "precmd" (i.e. prior to printing PS1). This caused general
multi-line pastes into the shell to fail (not just those including
a tmux command) because the precmd tmux commands would (invisibly)
drain stdin immediately after the first pasted command (before the
second prompt was printed). Thus, the shell would only execute the
first command, despite the rest of the commands being successfully
echoed by the tty.
---
 trunk/client.c    |    7 ++++++-
 trunk/server-fn.c |    3 +++
 trunk/tmux.h      |    5 +++--
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/trunk/client.c b/trunk/client.c
index ed182db..5522e15 100644
--- a/trunk/client.c
+++ b/trunk/client.c
@@ -264,7 +264,6 @@ client_main(int argc, char **argv, int flags)
 
        /* Set the event and dispatch. */
        client_update_event();
-       event_add (&client_stdin, NULL);
        event_dispatch();
 
        /* Print the exit message, if any, and exit. */
@@ -480,6 +479,12 @@ client_dispatch_wait(void *data)
                        event_del(&client_stdin);
                        client_attached = 1;
                        break;
+               case MSG_ENABLE_STDIN:
+                       if (datalen != 0)
+                               fatalx("bad MSG_ENABLE_STDIN size");
+
+                       event_add(&client_stdin, NULL);
+                       break;
                case MSG_STDOUT:
                        if (datalen != sizeof stdoutdata)
                                fatalx("bad MSG_STDOUT");
diff --git a/trunk/server-fn.c b/trunk/server-fn.c
index d95c498..b66179a 100644
--- a/trunk/server-fn.c
+++ b/trunk/server-fn.c
@@ -578,5 +578,8 @@ server_set_stdin_callback(struct client *c, void 
(*cb)(struct client *, int,
 
        if (c->stdin_closed)
                c->stdin_callback (c, 1, c->stdin_callback_data);
+
+       server_write_client(c, MSG_ENABLE_STDIN, NULL, 0);
+
        return (0);
 }
diff --git a/trunk/tmux.h b/trunk/tmux.h
index 76c3033..61ee47c 100644
--- a/trunk/tmux.h
+++ b/trunk/tmux.h
@@ -19,7 +19,7 @@
 #ifndef TMUX_H
 #define TMUX_H
 
-#define PROTOCOL_VERSION 7
+#define PROTOCOL_VERSION 8
 
 #include <sys/param.h>
 #include <sys/time.h>
@@ -407,7 +407,8 @@ enum msgtype {
        MSG_SHELL,
        MSG_STDERR,
        MSG_STDOUT,
-       MSG_DETACHKILL
+       MSG_DETACHKILL,
+       MSG_ENABLE_STDIN
 };
 
 /*
-- 
1.7.10.2


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to