Skip to content

Commit a7b27e5

Browse files
author
tcunha
committed
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).
1 parent d151102 commit a7b27e5

6 files changed

+123
-57
lines changed

client.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: client.c,v 1.94 2010-06-06 00:30:34 tcunha Exp $ */
1+
/* $Id: client.c,v 1.95 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -100,8 +100,7 @@ client_init(char *path, int cmdflags, int flags)
100100

101101
if (cmdflags & CMD_SENDENVIRON)
102102
client_send_environ();
103-
if (isatty(STDIN_FILENO))
104-
client_send_identify(flags);
103+
client_send_identify(flags);
105104

106105
return (&client_ibuf);
107106

@@ -135,6 +134,14 @@ client_send_identify(int flags)
135134
fatal("dup failed");
136135
imsg_compose(&client_ibuf,
137136
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
137+
138+
if ((fd = dup(STDOUT_FILENO)) == -1)
139+
fatal("dup failed");
140+
imsg_compose(&client_ibuf, MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
141+
142+
if ((fd = dup(STDERR_FILENO)) == -1)
143+
fatal("dup failed");
144+
imsg_compose(&client_ibuf, MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
138145
}
139146

140147
void

cmd-load-buffer.c

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: cmd-load-buffer.c,v 1.15 2010-02-26 13:30:07 tcunha Exp $ */
1+
/* $Id: cmd-load-buffer.c,v 1.16 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2009 Tiago Cunha <[email protected]>
@@ -16,10 +16,13 @@
1616
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1717
*/
1818

19+
#include <sys/types.h>
20+
1921
#include <errno.h>
2022
#include <stdio.h>
2123
#include <stdlib.h>
2224
#include <string.h>
25+
#include <unistd.h>
2326

2427
#include "tmux.h"
2528

@@ -45,7 +48,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
4548
{
4649
struct cmd_buffer_data *data = self->data;
4750
struct session *s;
48-
FILE *f;
51+
FILE *f, *close_f;
4952
char *pdata, *new_pdata;
5053
size_t psize;
5154
u_int limit;
@@ -54,9 +57,23 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
5457
if ((s = cmd_find_session(ctx, data->target)) == NULL)
5558
return (-1);
5659

57-
if ((f = fopen(data->arg, "rb")) == NULL) {
58-
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
59-
return (-1);
60+
if (strcmp(data->arg, "-") == 0 ) {
61+
if (ctx->cmdclient == NULL) {
62+
ctx->error(ctx, "%s: can't read from stdin", data->arg);
63+
return (-1);
64+
}
65+
f = ctx->cmdclient->stdin_file;
66+
if (isatty(fileno(ctx->cmdclient->stdin_file))) {
67+
ctx->error(ctx, "%s: stdin is a tty", data->arg);
68+
return (-1);
69+
}
70+
close_f = NULL;
71+
} else {
72+
if ((f = fopen(data->arg, "rb")) == NULL) {
73+
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
74+
return (-1);
75+
}
76+
close_f = f;
6077
}
6178

6279
pdata = NULL;
@@ -77,7 +94,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
7794
if (pdata != NULL)
7895
pdata[psize] = '\0';
7996

80-
fclose(f);
97+
if (close_f != NULL)
98+
fclose(close_f);
8199

82100
limit = options_get_number(&s->options, "buffer-limit");
83101
if (data->buffer == -1) {
@@ -94,6 +112,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
94112
error:
95113
if (pdata != NULL)
96114
xfree(pdata);
97-
fclose(f);
115+
if (close_f != NULL)
116+
fclose(close_f);
98117
return (-1);
99118
}

cmd-save-buffer.c

+23-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: cmd-save-buffer.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */
1+
/* $Id: cmd-save-buffer.c,v 1.11 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2009 Tiago Cunha <[email protected]>
@@ -48,7 +48,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
4848
struct session *s;
4949
struct paste_buffer *pb;
5050
mode_t mask;
51-
FILE *f;
51+
FILE *f, *close_f;
5252

5353
if ((s = cmd_find_session(ctx, data->target)) == NULL)
5454
return (-1);
@@ -65,15 +65,25 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
6565
}
6666
}
6767

68-
mask = umask(S_IRWXG | S_IRWXO);
69-
if (cmd_check_flag(data->chflags, 'a'))
70-
f = fopen(data->arg, "ab");
71-
else
72-
f = fopen(data->arg, "wb");
73-
umask(mask);
74-
if (f == NULL) {
75-
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
76-
return (-1);
68+
if (strcmp(data->arg, "-") == 0) {
69+
if (ctx->cmdclient == NULL) {
70+
ctx->error(ctx, "%s: can't write to stdout", data->arg);
71+
return (-1);
72+
}
73+
f = ctx->cmdclient->stdout_file;
74+
close_f = NULL;
75+
} else {
76+
mask = umask(S_IRWXG | S_IRWXO);
77+
if (cmd_check_flag(data->chflags, 'a'))
78+
f = fopen(data->arg, "ab");
79+
else
80+
f = fopen(data->arg, "wb");
81+
umask(mask);
82+
if (f == NULL) {
83+
ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
84+
return (-1);
85+
}
86+
close_f = f;
7787
}
7888

7989
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)
8292
return (-1);
8393
}
8494

85-
fclose(f);
95+
if (close_f != NULL)
96+
fclose(close_f);
8697

8798
return (0);
8899
}

server-client.c

+54-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: server-client.c,v 1.33 2010-06-06 00:30:34 tcunha Exp $ */
1+
/* $Id: server-client.c,v 1.34 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2009 Nicholas Marriott <[email protected]>
@@ -68,6 +68,10 @@ server_client_create(int fd)
6868

6969
ARRAY_INIT(&c->prompt_hdata);
7070

71+
c->stdin_file = NULL;
72+
c->stdout_file = NULL;
73+
c->stderr_file = NULL;
74+
7175
c->tty.fd = -1;
7276
c->title = NULL;
7377

@@ -117,6 +121,13 @@ server_client_lost(struct client *c)
117121
if (c->flags & CLIENT_TERMINAL)
118122
tty_free(&c->tty);
119123

124+
if (c->stdin_file != NULL)
125+
fclose(c->stdin_file);
126+
if (c->stdout_file != NULL)
127+
fclose(c->stdout_file);
128+
if (c->stderr_file != NULL)
129+
fclose(c->stderr_file);
130+
120131
screen_free(&c->status);
121132
job_tree_free(&c->status_jobs);
122133

@@ -554,8 +565,31 @@ server_client_msg_dispatch(struct client *c)
554565
fatalx("MSG_IDENTIFY missing fd");
555566
memcpy(&identifydata, imsg.data, sizeof identifydata);
556567

568+
c->stdin_file = fdopen(imsg.fd, "r");
569+
if (c->stdin_file == NULL)
570+
fatal("fdopen(stdin) failed");
557571
server_client_msg_identify(c, &identifydata, imsg.fd);
558572
break;
573+
case MSG_STDOUT:
574+
if (datalen != 0)
575+
fatalx("bad MSG_STDOUT size");
576+
if (imsg.fd == -1)
577+
fatalx("MSG_STDOUT missing fd");
578+
579+
c->stdout_file = fdopen(imsg.fd, "w");
580+
if (c->stdout_file == NULL)
581+
fatal("fdopen(stdout) failed");
582+
break;
583+
case MSG_STDERR:
584+
if (datalen != 0)
585+
fatalx("bad MSG_STDERR size");
586+
if (imsg.fd == -1)
587+
fatalx("MSG_STDERR missing fd");
588+
589+
c->stderr_file = fdopen(imsg.fd, "w");
590+
if (c->stderr_file == NULL)
591+
fatal("fdopen(stderr) failed");
592+
break;
559593
case MSG_RESIZE:
560594
if (datalen != 0)
561595
fatalx("bad MSG_RESIZE size");
@@ -621,45 +655,45 @@ server_client_msg_dispatch(struct client *c)
621655
void printflike2
622656
server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...)
623657
{
624-
struct msg_print_data data;
625-
va_list ap;
658+
va_list ap;
626659

627660
va_start(ap, fmt);
628-
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
661+
vfprintf(ctx->cmdclient->stderr_file, fmt, ap);
629662
va_end(ap);
630663

631-
server_write_client(ctx->cmdclient, MSG_ERROR, &data, sizeof data);
664+
fputc('\n', ctx->cmdclient->stderr_file);
665+
fflush(ctx->cmdclient->stderr_file);
632666
}
633667

634668
/* Callback to send print message to client. */
635669
void printflike2
636670
server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...)
637671
{
638-
struct msg_print_data data;
639-
va_list ap;
672+
va_list ap;
640673

641674
va_start(ap, fmt);
642-
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
675+
vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
643676
va_end(ap);
644677

645-
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
678+
fputc('\n', ctx->cmdclient->stdout_file);
679+
fflush(ctx->cmdclient->stdout_file);
646680
}
647681

648682
/* Callback to send print message to client, if not quiet. */
649683
void printflike2
650684
server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...)
651685
{
652-
struct msg_print_data data;
653-
va_list ap;
686+
va_list ap;
654687

655688
if (options_get_number(&global_options, "quiet"))
656689
return;
657690

658691
va_start(ap, fmt);
659-
xvsnprintf(data.msg, sizeof data.msg, fmt, ap);
692+
vfprintf(ctx->cmdclient->stdout_file, fmt, ap);
660693
va_end(ap);
661694

662-
server_write_client(ctx->cmdclient, MSG_PRINT, &data, sizeof data);
695+
fputc('\n', ctx->cmdclient->stderr_file);
696+
fflush(ctx->cmdclient->stdout_file);
663697
}
664698

665699
/* Handle command message. */
@@ -716,13 +750,19 @@ void
716750
server_client_msg_identify(
717751
struct client *c, struct msg_identify_data *data, int fd)
718752
{
753+
int tty_fd;
754+
719755
c->cwd = NULL;
720756
data->cwd[(sizeof data->cwd) - 1] = '\0';
721757
if (*data->cwd != '\0')
722758
c->cwd = xstrdup(data->cwd);
723759

760+
if (!isatty(fd))
761+
return;
762+
if ((tty_fd = dup(fd)) == -1)
763+
fatal("dup failed");
724764
data->term[(sizeof data->term) - 1] = '\0';
725-
tty_init(&c->tty, fd, data->term);
765+
tty_init(&c->tty, tty_fd, data->term);
726766
if (data->flags & IDENTIFY_UTF8)
727767
c->tty.flags |= TTY_UTF8;
728768
if (data->flags & IDENTIFY_256COLOURS)

tmux.c

+1-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: tmux.c,v 1.212 2010-07-02 02:49:19 tcunha Exp $ */
1+
/* $Id: tmux.c,v 1.213 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -613,7 +613,6 @@ main_dispatch(const char *shellcmd)
613613
{
614614
struct imsg imsg;
615615
ssize_t n, datalen;
616-
struct msg_print_data printdata;
617616
struct msg_shell_data shelldata;
618617

619618
if ((n = imsg_read(main_ibuf)) == -1 || n == 0)
@@ -633,17 +632,6 @@ main_dispatch(const char *shellcmd)
633632
fatalx("bad MSG_EXIT size");
634633

635634
exit(main_exitval);
636-
case MSG_ERROR:
637-
case MSG_PRINT:
638-
if (datalen != sizeof printdata)
639-
fatalx("bad MSG_PRINT size");
640-
memcpy(&printdata, imsg.data, sizeof printdata);
641-
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
642-
643-
log_info("%s", printdata.msg);
644-
if (imsg.hdr.type == MSG_ERROR)
645-
main_exitval = 1;
646-
break;
647635
case MSG_READY:
648636
if (datalen != 0)
649637
fatalx("bad MSG_READY size");

tmux.h

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: tmux.h,v 1.566 2010-07-02 02:49:19 tcunha Exp $ */
1+
/* $Id: tmux.h,v 1.567 2010-07-02 02:52:13 tcunha Exp $ */
22

33
/*
44
* Copyright (c) 2007 Nicholas Marriott <[email protected]>
@@ -21,7 +21,7 @@
2121

2222
#include "config.h"
2323

24-
#define PROTOCOL_VERSION 5
24+
#define PROTOCOL_VERSION 6
2525

2626
#include <sys/param.h>
2727
#include <sys/time.h>
@@ -67,7 +67,6 @@ extern char **environ;
6767
*/
6868
#define COMMAND_LENGTH 2048 /* packed argv size */
6969
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
70-
#define PRINT_LENGTH 512 /* printed error/message size */
7170
#define ENVIRON_LENGTH 1024 /* environment variable length */
7271

7372
/*
@@ -372,18 +371,16 @@ enum msgtype {
372371
MSG_ENVIRON,
373372
MSG_UNLOCK,
374373
MSG_LOCK,
375-
MSG_SHELL
374+
MSG_SHELL,
375+
MSG_STDERR,
376+
MSG_STDOUT,
376377
};
377378

378379
/*
379380
* Message data.
380381
*
381382
* Don't forget to bump PROTOCOL_VERSION if any of these change!
382383
*/
383-
struct msg_print_data {
384-
char msg[PRINT_LENGTH];
385-
};
386-
387384
struct msg_command_data {
388385
pid_t pid; /* pid from $TMUX or -1 */
389386
u_int idx; /* index from $TMUX */
@@ -1079,6 +1076,10 @@ struct client {
10791076
char *cwd;
10801077

10811078
struct tty tty;
1079+
FILE *stdin_file;
1080+
FILE *stdout_file;
1081+
FILE *stderr_file;
1082+
10821083
struct event repeat_timer;
10831084

10841085
struct timeval status_timer;

0 commit comments

Comments
 (0)