summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client.c13
-rw-r--r--cmd-load-buffer.c33
-rw-r--r--cmd-save-buffer.c35
-rw-r--r--server-client.c68
-rw-r--r--tmux.c14
-rw-r--r--tmux.h17
6 files changed, 123 insertions, 57 deletions
diff --git a/client.c b/client.c
index 54932d43..335fdfab 100644
--- a/client.c
+++ b/client.c
@@ -1,4 +1,4 @@
-/* $Id: client.c,v 1.94 2010-06-06 00:30:34 tcunha Exp $ */
+/* $Id: client.c,v 1.95 2010-07-02 02:52:13 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -100,8 +100,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);
@@ -135,6 +134,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/cmd-load-buffer.c b/cmd-load-buffer.c
index d94ac6d9..2a0e4d1d 100644
--- a/cmd-load-buffer.c
+++ b/cmd-load-buffer.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-load-buffer.c,v 1.15 2010-02-26 13:30:07 tcunha Exp $ */
+/* $Id: cmd-load-buffer.c,v 1.16 2010-07-02 02:52:13 tcunha 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/cmd-save-buffer.c b/cmd-save-buffer.c
index 3ced3309..f6c53821 100644
--- a/cmd-save-buffer.c
+++ b/cmd-save-buffer.c
@@ -1,4 +1,4 @@
-/* $Id: cmd-save-buffer.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */
+/* $Id: cmd-save-buffer.c,v 1.11 2010-07-02 02:52:13 tcunha 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/server-client.c b/server-client.c
index f738e86e..9af40994 100644
--- a/server-client.c
+++ b/server-client.c
@@ -1,4 +1,4 @@
-/* $Id: server-client.c,v 1.33 2010-06-06 00:30:34 tcunha Exp $ */
+/* $Id: server-client.c,v 1.34 2010-07-02 02:52:13 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -68,6 +68,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;
@@ -117,6 +121,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);
@@ -554,8 +565,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");
@@ -621,45 +655,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. */
@@ -716,13 +750,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/tmux.c b/tmux.c
index d10ca0e0..571ef070 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.212 2010-07-02 02:49:19 tcunha Exp $ */
+/* $Id: tmux.c,v 1.213 2010-07-02 02:52:13 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -613,7 +613,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)
@@ -633,17 +632,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/tmux.h b/tmux.h
index 5b377ea4..e2c1c0aa 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.566 2010-07-02 02:49:19 tcunha Exp $ */
+/* $Id: tmux.h,v 1.567 2010-07-02 02:52:13 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,7 +21,7 @@
#include "config.h"
-#define PROTOCOL_VERSION 5
+#define PROTOCOL_VERSION 6
#include <sys/param.h>
#include <sys/time.h>
@@ -67,7 +67,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 */
/*
@@ -372,7 +371,9 @@ enum msgtype {
MSG_ENVIRON,
MSG_UNLOCK,
MSG_LOCK,
- MSG_SHELL
+ MSG_SHELL,
+ MSG_STDERR,
+ MSG_STDOUT,
};
/*
@@ -380,10 +381,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 */
@@ -1079,6 +1076,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;