Sync OpenBSD patchset 731:

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).
This commit is contained in:
Tiago Cunha 2010-07-02 02:52:13 +00:00
parent 63e76b555d
commit e4573de97b
6 changed files with 123 additions and 57 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)

14
tmux.c
View File

@ -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");

17
tmux.h
View File

@ -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;