-
Notifications
You must be signed in to change notification settings - Fork 872
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add -I to pipe-pane to connect pane stdin as well as stdout, suggested
by Kristof Kovacs in GitHub issue 1186.
- Loading branch information
Showing
2 changed files
with
82 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/* $OpenBSD: cmd-pipe-pane.c,v 1.46 2017/07/14 18:49:07 nicm Exp $ */ | ||
/* $OpenBSD: cmd-pipe-pane.c,v 1.47 2018/01/16 09:00:38 nicm Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2009 Nicholas Marriott <[email protected]> | ||
|
@@ -36,15 +36,16 @@ | |
|
||
static enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmdq_item *); | ||
|
||
static void cmd_pipe_pane_read_callback(struct bufferevent *, void *); | ||
static void cmd_pipe_pane_write_callback(struct bufferevent *, void *); | ||
static void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *); | ||
|
||
const struct cmd_entry cmd_pipe_pane_entry = { | ||
.name = "pipe-pane", | ||
.alias = "pipep", | ||
|
||
.args = { "ot:", 0, 1 }, | ||
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]", | ||
.args = { "IOot:", 0, 1 }, | ||
.usage = "[-IOo] " CMD_TARGET_PANE_USAGE " [command]", | ||
|
||
.target = { 't', CMD_FIND_PANE, 0 }, | ||
|
||
|
@@ -61,7 +62,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |
struct session *s = item->target.s; | ||
struct winlink *wl = item->target.wl; | ||
char *cmd; | ||
int old_fd, pipe_fd[2], null_fd; | ||
int old_fd, pipe_fd[2], null_fd, in, out; | ||
struct format_tree *ft; | ||
sigset_t set, oldset; | ||
|
||
|
@@ -91,6 +92,15 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |
if (args_has(self->args, 'o') && old_fd != -1) | ||
return (CMD_RETURN_NORMAL); | ||
|
||
/* What do we want to do? Neither -I or -O is -O. */ | ||
if (args_has(self->args, 'I')) { | ||
in = 1; | ||
out = args_has(self->args, 'O'); | ||
} else { | ||
in = 0; | ||
out = 1; | ||
} | ||
|
||
/* Open the new pipe. */ | ||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { | ||
cmdq_error(item, "socketpair error: %s", strerror(errno)); | ||
|
@@ -119,19 +129,25 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |
sigprocmask(SIG_SETMASK, &oldset, NULL); | ||
close(pipe_fd[0]); | ||
|
||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1) | ||
_exit(1); | ||
if (pipe_fd[1] != STDIN_FILENO) | ||
close(pipe_fd[1]); | ||
|
||
null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); | ||
if (dup2(null_fd, STDOUT_FILENO) == -1) | ||
_exit(1); | ||
if (out) { | ||
if (dup2(pipe_fd[1], STDIN_FILENO) == -1) | ||
_exit(1); | ||
} else { | ||
if (dup2(null_fd, STDIN_FILENO) == -1) | ||
_exit(1); | ||
} | ||
if (in) { | ||
if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) | ||
_exit(1); | ||
if (pipe_fd[1] != STDOUT_FILENO) | ||
close(pipe_fd[1]); | ||
} else { | ||
if (dup2(null_fd, STDOUT_FILENO) == -1) | ||
_exit(1); | ||
} | ||
if (dup2(null_fd, STDERR_FILENO) == -1) | ||
_exit(1); | ||
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO) | ||
close(null_fd); | ||
|
||
closefrom(STDERR_FILENO + 1); | ||
|
||
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); | ||
|
@@ -144,24 +160,46 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) | |
wp->pipe_fd = pipe_fd[0]; | ||
wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); | ||
|
||
wp->pipe_event = bufferevent_new(wp->pipe_fd, NULL, | ||
cmd_pipe_pane_write_callback, cmd_pipe_pane_error_callback, | ||
wp); | ||
bufferevent_enable(wp->pipe_event, EV_WRITE); | ||
|
||
setblocking(wp->pipe_fd, 0); | ||
wp->pipe_event = bufferevent_new(wp->pipe_fd, | ||
cmd_pipe_pane_read_callback, | ||
cmd_pipe_pane_write_callback, | ||
cmd_pipe_pane_error_callback, | ||
wp); | ||
if (out) | ||
bufferevent_enable(wp->pipe_event, EV_WRITE); | ||
if (in) | ||
bufferevent_enable(wp->pipe_event, EV_READ); | ||
|
||
free(cmd); | ||
return (CMD_RETURN_NORMAL); | ||
} | ||
} | ||
|
||
static void | ||
cmd_pipe_pane_read_callback(__unused struct bufferevent *bufev, void *data) | ||
{ | ||
struct window_pane *wp = data; | ||
struct evbuffer *evb = wp->pipe_event->input; | ||
size_t available; | ||
|
||
available = EVBUFFER_LENGTH(evb); | ||
log_debug("%%%u pipe read %zu", wp->id, available); | ||
|
||
bufferevent_write(wp->event, EVBUFFER_DATA(evb), available); | ||
evbuffer_drain(evb, available); | ||
|
||
if (window_pane_destroy_ready(wp)) | ||
server_destroy_pane(wp, 1); | ||
} | ||
|
||
static void | ||
cmd_pipe_pane_write_callback(__unused struct bufferevent *bufev, void *data) | ||
{ | ||
struct window_pane *wp = data; | ||
|
||
log_debug("%%%u pipe empty", wp->id); | ||
|
||
if (window_pane_destroy_ready(wp)) | ||
server_destroy_pane(wp, 1); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
.\" $OpenBSD: tmux.1,v 1.590 2017/12/22 10:16:36 nicm Exp $ | ||
.\" $OpenBSD: tmux.1,v 1.591 2018/01/16 09:00:38 nicm Exp $ | ||
.\" | ||
.\" Copyright (c) 2007 Nicholas Marriott <[email protected]> | ||
.\" | ||
|
@@ -14,7 +14,7 @@ | |
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | ||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
.\" | ||
.Dd $Mdocdate: December 22 2017 $ | ||
.Dd $Mdocdate: January 16 2018 $ | ||
.Dt TMUX 1 | ||
.Os | ||
.Sh NAME | ||
|
@@ -1800,15 +1800,15 @@ If | |
.Fl a | ||
is used, move to the next window with an alert. | ||
.It Xo Ic pipe-pane | ||
.Op Fl o | ||
.Op Fl IOo | ||
.Op Fl t Ar target-pane | ||
.Op Ar shell-command | ||
.Xc | ||
.D1 (alias: Ic pipep ) | ||
Pipe any output sent by the program in | ||
Pipe output sent by the program in | ||
.Ar target-pane | ||
to a shell command. | ||
A pane may only be piped to one command at a time, any existing pipe is | ||
to a shell command or vice versa. | ||
A pane may only be connected to one command at a time, any existing pipe is | ||
closed before | ||
.Ar shell-command | ||
is executed. | ||
|
@@ -1821,6 +1821,25 @@ If no | |
.Ar shell-command | ||
is given, the current pipe (if any) is closed. | ||
.Pp | ||
.Fl I | ||
and | ||
.Fl O | ||
specify which of the | ||
.Ar shell-command | ||
output streams are connected to the pane: | ||
with | ||
.Fl I | ||
stdout is connected (so anything | ||
.Ar shell-command | ||
prints is written to the pane as if it were typed); | ||
with | ||
.Fl O | ||
stdin is connected (so any output in the pane is piped to | ||
.Ar shell-command ) . | ||
Both may be used together and if neither are specified, | ||
.Fl O | ||
is used. | ||
.Pp | ||
The | ||
.Fl o | ||
option only opens a new pipe if no previous pipe exists, allowing a pipe to | ||
|