Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-07-10 18:20:43 +01:00
3 changed files with 61 additions and 17 deletions

View File

@@ -239,9 +239,8 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
pid_t ppid;
enum msgtype msg;
struct termios tio, saved_tio;
size_t size, linesize = 0;
ssize_t linelen;
char *line = NULL, **caps = NULL, *cause;
size_t size;
char **caps = NULL, *cause;
u_int ncaps = 0;
struct args_value *values;
@@ -407,11 +406,6 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
client_exec(client_execshell, client_execcmd);
}
/* Restore streams to blocking. */
setblocking(STDIN_FILENO, 1);
setblocking(STDOUT_FILENO, 1);
setblocking(STDERR_FILENO, 1);
/* Print the exit message, if any, and exit. */
if (client_attached) {
if (client_exitreason != CLIENT_EXIT_NONE)
@@ -426,15 +420,8 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
else
printf("%%exit\n");
fflush(stdout);
if (client_flags & CLIENT_CONTROL_WAITEXIT) {
setvbuf(stdin, NULL, _IOLBF, 0);
for (;;) {
linelen = getline(&line, &linesize, stdin);
if (linelen <= 1)
break;
}
free(line);
}
if (client_flags & CLIENT_CONTROL_WAITEXIT)
control_wait_exit(STDIN_FILENO);
if (client_flags & CLIENT_CONTROLCONTROL) {
printf("\033\\");
fflush(stdout);
@@ -442,6 +429,12 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
}
} else if (client_exitreason != CLIENT_EXIT_NONE)
fprintf(stderr, "%s\n", client_exit_message());
/* Restore the streams to blocking. */
setblocking(STDIN_FILENO, 1);
setblocking(STDOUT_FILENO, 1);
setblocking(STDERR_FILENO, 1);
return (client_exitval);
}

View File

@@ -19,6 +19,9 @@
#include <sys/types.h>
#include <errno.h>
#include <event.h>
#include <poll.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -485,6 +488,53 @@ control_all_done(struct client *c)
return (EVBUFFER_LENGTH(cs->write_event->output) == 0);
}
/*
* Wait for the terminal to send an empty line or close, used by a control
* client after printing %exit so a wrapping terminal (such as iTerm2) can
* finish reading.
*/
void
control_wait_exit(int fd)
{
struct pollfd pfd;
struct evbuffer *evb;
char *line;
int n;
evb = evbuffer_new();
if (evb == NULL)
fatalx("out of memory");
for (;;) {
line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF);
if (line != NULL) {
if (*line == '\0') { /* empty line, stop */
free(line);
break;
}
free(line);
continue; /* drain buffered lines first */
}
memset(&pfd, 0, sizeof pfd);
pfd.fd = fd;
pfd.events = POLLIN;
if (poll(&pfd, 1, INFTIM) == -1) {
if (errno == EINTR)
continue;
break;
}
n = evbuffer_read(evb, fd, -1);
if (n == 0)
break;
if (n == -1 && errno != EAGAIN && errno != EINTR)
break;
}
evbuffer_free(evb);
}
/* Flush all blocks until output. */
static void
control_flush_all_blocks(struct client *c)

1
tmux.h
View File

@@ -3967,6 +3967,7 @@ void control_discard(struct client *);
void control_start(struct client *);
void control_ready(struct client *);
void control_stop(struct client *);
void control_wait_exit(int);
void control_set_pane_on(struct client *, struct window_pane *);
void control_set_pane_off(struct client *, struct window_pane *);
void control_continue_pane(struct client *, struct window_pane *);