summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2010-06-28 22:10:43 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2010-06-28 22:10:43 +0000
commite2546c0ed9de9f453c28d13893e7cab5f97e212b (patch)
tree05e2c0153fb03a1137f4c1df6e27e61e2c0c45cb
parentd2110dd96b54c8e81d65079f4e4d10ceebf630c5 (diff)
Send all three of stdin, stdout, stderr from the client to the server, so that
commands can directly make use of them. This means that load-buffer and save-buffer can have "-" as the file to read from stdin or write to stdout. This is a protocol version bump so the tmux server will need to be restarted after upgrade (or an older client used).
-rw-r--r--usr.bin/tmux/client.c13
-rw-r--r--usr.bin/tmux/cmd-load-buffer.c33
-rw-r--r--usr.bin/tmux/cmd-save-buffer.c35
-rw-r--r--usr.bin/tmux/server-client.c68
-rw-r--r--usr.bin/tmux/tmux.c14
-rw-r--r--usr.bin/tmux/tmux.h17
6 files changed, 123 insertions, 57 deletions
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c
index 66a85dcd8f8..943f5bbac61 100644
--- a/usr.bin/tmux/client.c
+++ b/usr.bin/tmux/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.41 2010/06/05 16:47:11 nicm Exp $ */
+/* $OpenBSD: client.c,v 1.42 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -96,8 +96,7 @@ server_started:
if (cmdflags & CMD_SENDENVIRON)
client_send_environ();
- if (isatty(STDIN_FILENO))
- client_send_identify(flags);
+ client_send_identify(flags);
return (&client_ibuf);
@@ -131,6 +130,14 @@ client_send_identify(int flags)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
+
+ if ((fd = dup(STDOUT_FILENO)) == -1)
+ fatal("dup failed");
+ imsg_compose(&client_ibuf, MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
+
+ if ((fd = dup(STDERR_FILENO)) == -1)
+ fatal("dup failed");
+ imsg_compose(&client_ibuf, MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
}
void
diff --git a/usr.bin/tmux/cmd-load-buffer.c b/usr.bin/tmux/cmd-load-buffer.c
index 47f7d441886..745ebbe5ce2 100644
--- a/usr.bin/tmux/cmd-load-buffer.c
+++ b/usr.bin/tmux/cmd-load-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-load-buffer.c,v 1.11 2010/02/22 20:33:12 nicm Exp $ */
+/* $OpenBSD: cmd-load-buffer.c,v 1.12 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -16,10 +16,13 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "tmux.h"
@@ -45,7 +48,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_buffer_data *data = self->data;
struct session *s;
- FILE *f;
+ FILE *f, *close_f;
char *pdata, *new_pdata;
size_t psize;
u_int limit;
@@ -54,9 +57,23 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
- if ((f = fopen(data->arg, "rb")) == NULL) {
- ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
- return (-1);
+ if (strcmp(data->arg, "-") == 0 ) {
+ if (ctx->cmdclient == NULL) {
+ ctx->error(ctx, "%s: can't read from stdin", data->arg);
+ return (-1);
+ }
+ f = ctx->cmdclient->stdin_file;
+ if (isatty(fileno(ctx->cmdclient->stdin_file))) {
+ ctx->error(ctx, "%s: stdin is a tty", data->arg);
+ return (-1);
+ }
+ close_f = NULL;
+ } else {
+ if ((f = fopen(data->arg, "rb")) == NULL) {
+ ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
+ return (-1);
+ }
+ close_f = f;
}
pdata = NULL;
@@ -77,7 +94,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
if (pdata != NULL)
pdata[psize] = '\0';
- fclose(f);
+ if (close_f != NULL)
+ fclose(close_f);
limit = options_get_number(&s->options, "buffer-limit");
if (data->buffer == -1) {
@@ -94,6 +112,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
error:
if (pdata != NULL)
xfree(pdata);
- fclose(f);
+ if (close_f != NULL)
+ fclose(close_f);
return (-1);
}
diff --git a/usr.bin/tmux/cmd-save-buffer.c b/usr.bin/tmux/cmd-save-buffer.c
index 3d6fbbedc5d..d25f1402f12 100644
--- a/usr.bin/tmux/cmd-save-buffer.c
+++ b/usr.bin/tmux/cmd-save-buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-save-buffer.c,v 1.6 2009/11/13 19:53:29 nicm Exp $ */
+/* $OpenBSD: cmd-save-buffer.c,v 1.7 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -48,7 +48,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
struct session *s;
struct paste_buffer *pb;
mode_t mask;
- FILE *f;
+ FILE *f, *close_f;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
@@ -65,15 +65,25 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
}
}
- mask = umask(S_IRWXG | S_IRWXO);
- if (cmd_check_flag(data->chflags, 'a'))
- f = fopen(data->arg, "ab");
- else
- f = fopen(data->arg, "wb");
- umask(mask);
- if (f == NULL) {
- ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
- return (-1);
+ if (strcmp(data->arg, "-") == 0) {
+ if (ctx->cmdclient == NULL) {
+ ctx->error(ctx, "%s: can't write to stdout", data->arg);
+ return (-1);
+ }
+ f = ctx->cmdclient->stdout_file;
+ close_f = NULL;
+ } else {
+ mask = umask(S_IRWXG | S_IRWXO);
+ if (cmd_check_flag(data->chflags, 'a'))
+ f = fopen(data->arg, "ab");
+ else
+ f = fopen(data->arg, "wb");
+ umask(mask);
+ if (f == NULL) {
+ ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
+ return (-1);
+ }
+ close_f = f;
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
@@ -82,7 +92,8 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1);
}
- fclose(f);
+ if (close_f != NULL)
+ fclose(close_f);
return (0);
}
diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c
index 3271d9f37bb..d1abbf5dad8 100644
--- a/usr.bin/tmux/server-client.c
+++ b/usr.bin/tmux/server-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.32 2010/06/05 16:47:11 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.33 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -69,6 +69,10 @@ server_client_create(int fd)
ARRAY_INIT(&c->prompt_hdata);
+ c->stdin_file = NULL;
+ c->stdout_file = NULL;
+ c->stderr_file = NULL;
+
c->tty.fd = -1;
c->title = NULL;
@@ -118,6 +122,13 @@ server_client_lost(struct client *c)
if (c->flags & CLIENT_TERMINAL)
tty_free(&c->tty);
+ if (c->stdin_file != NULL)
+ fclose(c->stdin_file);
+ if (c->stdout_file != NULL)
+ fclose(c->stdout_file);
+ if (c->stderr_file != NULL)
+ fclose(c->stderr_file);
+
screen_free(&c->status);
job_tree_free(&c->status_jobs);
@@ -555,8 +566,31 @@ server_client_msg_dispatch(struct client *c)
fatalx("MSG_IDENTIFY missing fd");
memcpy(&identifydata, imsg.data, sizeof identifydata);
+ c->stdin_file = fdopen(imsg.fd, "r");
+ if (c->stdin_file == NULL)
+ fatal("fdopen(stdin) failed");
server_client_msg_identify(c, &identifydata, imsg.fd);
break;
+ case MSG_STDOUT:
+ if (datalen != 0)
+ fatalx("bad MSG_STDOUT size");
+ if (imsg.fd == -1)
+ fatalx("MSG_STDOUT missing fd");
+
+ c->stdout_file = fdopen(imsg.fd, "w");
+ if (c->stdout_file == NULL)
+ fatal("fdopen(stdout) failed");
+ break;
+ case MSG_STDERR:
+ if (datalen != 0)
+ fatalx("bad MSG_STDERR size");
+ if (imsg.fd == -1)
+ fatalx("MSG_STDERR missing fd");
+
+ c->stderr_file = fdopen(imsg.fd, "w");
+ if (c->stderr_file == NULL)
+ fatal("fdopen(stderr) failed");
+ break;
case MSG_RESIZE:
if (datalen != 0)
fatalx("bad MSG_RESIZE size");
@@ -622,45 +656,45 @@ server_client_msg_dispatch(struct client *c)
void printflike2
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
{
- struct msg_print_data data;
- va_list ap;
+ va_list ap;
va_start(ap, fmt);
- xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
+ vfprintf(ctx->cmdclient->stderr_file, fmt, ap);
va_end(ap);
- server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
+ fputc('\n', ctx->cmdclient->stderr_file);
+ fflush(ctx->cmdclient->stderr_file);
}
/* Callback to send print message to client. */
void printflike2
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
{
- struct msg_print_data data;
- va_list ap;
+ va_list ap;
va_start(ap, fmt);
- xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
+ vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
va_end(ap);
- server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
+ fputc('\n', ctx->cmdclient->stdout_file);
+ fflush(ctx->cmdclient->stdout_file);
}
/* Callback to send print message to client, if not quiet. */
void printflike2
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
{
- struct msg_print_data data;
- va_list ap;
+ va_list ap;
if (options_get_number(&global_options, "quiet"))
return;
va_start(ap, fmt);
- xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
+ vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
va_end(ap);
- server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
+ fputc('\n', ctx->cmdclient->stderr_file);
+ fflush(ctx->cmdclient->stdout_file);
}
/* Handle command message. */
@@ -717,13 +751,19 @@ void
server_client_msg_identify(
struct client *c, struct msg_identify_data *data, int fd)
{
+ int tty_fd;
+
c->cwd = NULL;
data->cwd[(sizeof data->cwd) - 1] = '\0';
if (*data->cwd != '\0')
c->cwd = xstrdup(data->cwd);
+ if (!isatty(fd))
+ return;
+ if ((tty_fd = dup(fd)) == -1)
+ fatal("dup failed");
data->term[(sizeof data->term) - 1] = '\0';
- tty_init(&c->tty, fd, data->term);
+ tty_init(&c->tty, tty_fd, data->term);
if (data->flags & IDENTIFY_UTF8)
c->tty.flags |= TTY_UTF8;
if (data->flags & IDENTIFY_256COLOURS)
diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c
index c72be02927b..9f80e5a0b7d 100644
--- a/usr.bin/tmux/tmux.c
+++ b/usr.bin/tmux/tmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.c,v 1.82 2010/06/27 02:56:59 nicm Exp $ */
+/* $OpenBSD: tmux.c,v 1.83 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -596,7 +596,6 @@ main_dispatch(const char *shellcmd)
{
struct imsg imsg;
ssize_t n, datalen;
- struct msg_print_data printdata;
struct msg_shell_data shelldata;
if ((n = imsg_read(main_ibuf)) == -1 || n == 0)
@@ -616,17 +615,6 @@ main_dispatch(const char *shellcmd)
fatalx("bad MSG_EXIT size");
exit(main_exitval);
- case MSG_ERROR:
- case MSG_PRINT:
- if (datalen != sizeof printdata)
- fatalx("bad MSG_PRINT size");
- memcpy(&printdata, imsg.data, sizeof printdata);
- printdata.msg[(sizeof printdata.msg) - 1] = '\0';
-
- log_info("%s", printdata.msg);
- if (imsg.hdr.type == MSG_ERROR)
- main_exitval = 1;
- break;
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 0767b4acf6d..fae4023fe27 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.230 2010/06/27 02:56:59 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.231 2010/06/28 22:10:42 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,7 +19,7 @@
#ifndef TMUX_H
#define TMUX_H
-#define PROTOCOL_VERSION 5
+#define PROTOCOL_VERSION 6
#include <sys/param.h>
#include <sys/time.h>
@@ -68,7 +68,6 @@ extern char **environ;
*/
#define COMMAND_LENGTH 2048 /* packed argv size */
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
-#define PRINT_LENGTH 512 /* printed error/message size */
#define ENVIRON_LENGTH 1024 /* environment variable length */
/*
@@ -373,7 +372,9 @@ enum msgtype {
MSG_ENVIRON,
MSG_UNLOCK,
MSG_LOCK,
- MSG_SHELL
+ MSG_SHELL,
+ MSG_STDERR,
+ MSG_STDOUT,
};
/*
@@ -381,10 +382,6 @@ enum msgtype {
*
* Don't forget to bump PROTOCOL_VERSION if any of these change!
*/
-struct msg_print_data {
- char msg[PRINT_LENGTH];
-};
-
struct msg_command_data {
pid_t pid; /* pid from $TMUX or -1 */
u_int idx; /* index from $TMUX */
@@ -1080,6 +1077,10 @@ struct client {
char *cwd;
struct tty tty;
+ FILE *stdin_file;
+ FILE *stdout_file;
+ FILE *stderr_file;
+
struct event repeat_timer;
struct timeval status_timer;