diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-06-28 22:10:43 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-06-28 22:10:43 +0000 |
commit | e2546c0ed9de9f453c28d13893e7cab5f97e212b (patch) | |
tree | 05e2c0153fb03a1137f4c1df6e27e61e2c0c45cb | |
parent | d2110dd96b54c8e81d65079f4e4d10ceebf630c5 (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.c | 13 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-load-buffer.c | 33 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-save-buffer.c | 35 | ||||
-rw-r--r-- | usr.bin/tmux/server-client.c | 68 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.c | 14 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 17 |
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; |