diff options
author | Thomas Adam <thomas@xteddy.org> | 2020-05-26 14:02:15 +0100 |
---|---|---|
committer | Thomas Adam <thomas@xteddy.org> | 2020-05-26 14:02:15 +0100 |
commit | a4cb700269e033b5ad429275d7c61d3c3c2f1af3 (patch) | |
tree | f469586f1cffa3569385d88efa4305c2c83c18ef | |
parent | bc2e0cf7ff51c2ab13c7dcc792d25e11ba7a3ef4 (diff) | |
parent | 392b381d1cec6d63c4baaa709243f760ff6c3403 (diff) | |
download | rtmux-a4cb700269e033b5ad429275d7c61d3c3c2f1af3.tar.gz rtmux-a4cb700269e033b5ad429275d7c61d3c3c2f1af3.tar.bz2 rtmux-a4cb700269e033b5ad429275d7c61d3c3c2f1af3.zip |
Merge branch 'obsd-master'
-rw-r--r-- | client.c | 5 | ||||
-rw-r--r-- | cmd-break-pane.c | 4 | ||||
-rw-r--r-- | cmd-select-pane.c | 5 | ||||
-rw-r--r-- | control.c | 81 | ||||
-rw-r--r-- | file.c | 8 | ||||
-rw-r--r-- | grid.c | 1 | ||||
-rw-r--r-- | server-client.c | 29 | ||||
-rw-r--r-- | status.c | 5 | ||||
-rw-r--r-- | tmux.h | 3 |
9 files changed, 103 insertions, 38 deletions
@@ -404,6 +404,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags, int feat) } else if (client_exitreason != CLIENT_EXIT_NONE) fprintf(stderr, "%s\n", client_exit_message()); setblocking(STDIN_FILENO, 1); + setblocking(STDOUT_FILENO, 1); + setblocking(STDERR_FILENO, 1); return (client_exitval); } @@ -431,6 +433,9 @@ client_send_identify(const char *ttynam, const char *cwd, int feat) if ((fd = dup(STDIN_FILENO)) == -1) fatal("dup failed"); proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0); + if ((fd = dup(STDOUT_FILENO)) == -1) + fatal("dup failed"); + proc_send(client_peer, MSG_IDENTIFY_STDOUT, fd, NULL, 0); pid = getpid(); proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid); diff --git a/cmd-break-pane.c b/cmd-break-pane.c index 9483aa7e..6d5041e8 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -80,6 +80,10 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item) free(cause); return (CMD_RETURN_ERROR); } + if (args_has(args, 'n')) { + window_set_name(w, args_get(args, 'n')); + options_set_number(w->options, "automatic-rename", 0); + } server_unlink_window(src_s, wl); return (CMD_RETURN_NORMAL); } diff --git a/cmd-select-pane.c b/cmd-select-pane.c index 3b639e06..313deefe 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -129,7 +129,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) if (args_has(args, 'm') || args_has(args, 'M')) { if (args_has(args, 'm') && !window_pane_visible(wp)) return (CMD_RETURN_NORMAL); - lastwp = marked_pane.wp; + if (server_check_marked()) + lastwp = marked_pane.wp; + else + lastwp = NULL; if (args_has(args, 'M') || server_is_marked(s, wl, wp)) server_clear_marked(); @@ -23,10 +23,11 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <unistd.h> #include "tmux.h" -/* Control offsets. */ +/* Control client offset. */ struct control_offset { u_int pane; @@ -34,13 +35,16 @@ struct control_offset { int flags; #define CONTROL_OFFSET_OFF 0x1 - RB_ENTRY(control_offset) entry; + RB_ENTRY(control_offset) entry; }; RB_HEAD(control_offsets, control_offset); -/* Control state. */ +/* Control client state. */ struct control_state { - struct control_offsets offsets; + struct control_offsets offsets; + + struct bufferevent *read_event; + struct bufferevent *write_event; }; /* Compare client offsets. */ @@ -146,18 +150,24 @@ control_set_pane_off(struct client *c, struct window_pane *wp) void control_write(struct client *c, const char *fmt, ...) { - va_list ap; + struct control_state *cs = c->control_state; + va_list ap; + char *s; va_start(ap, fmt); - file_vprint(c, fmt, ap); - file_print(c, "\n"); + xvasprintf(&s, fmt, ap); va_end(ap); + + bufferevent_write(cs->write_event, s, strlen(s)); + bufferevent_write(cs->write_event, "\n", 1); + free(s); } /* Write output from a pane. */ void control_write_output(struct client *c, struct window_pane *wp) { + struct control_state *cs = c->control_state; struct control_offset *co; struct evbuffer *message; u_char *new_data; @@ -165,11 +175,6 @@ control_write_output(struct client *c, struct window_pane *wp) if (c->flags & CLIENT_CONTROL_NOOUTPUT) return; - - /* - * Only write input if the window pane is linked to a window belonging - * to the client's session. - */ if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) return; @@ -193,15 +198,15 @@ control_write_output(struct client *c, struct window_pane *wp) else evbuffer_add_printf(message, "%c", new_data[i]); } - evbuffer_add(message, "", 1); + evbuffer_add(message, "\n", 1); - control_write(c, "%s", EVBUFFER_DATA(message)); + bufferevent_write_buffer(cs->write_event, message); evbuffer_free(message); window_pane_update_used_data(wp, &co->offset, new_size, 1); } -/* Control error callback. */ +/* Control client error callback. */ static enum cmd_retval control_error(struct cmdq_item *item, void *data) { @@ -216,18 +221,27 @@ control_error(struct cmdq_item *item, void *data) return (CMD_RETURN_NORMAL); } -/* Control input callback. Read lines and fire commands. */ +/* Control client error callback. */ static void -control_callback(__unused struct client *c, __unused const char *path, - int read_error, int closed, struct evbuffer *buffer, __unused void *data) +control_error_callback(__unused struct bufferevent *bufev, + __unused short what, void *data) { + struct client *c = data; + + c->flags |= CLIENT_EXIT; +} + +/* Control client input callback. Read lines and fire commands. */ +static void +control_read_callback(__unused struct bufferevent *bufev, void *data) +{ + struct client *c = data; + struct control_state *cs = c->control_state; + struct evbuffer *buffer = cs->read_event->input; char *line, *error; struct cmdq_state *state; enum cmd_parse_status status; - if (closed || read_error != 0) - c->flags |= CLIENT_EXIT; - for (;;) { line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF); if (line == NULL) @@ -255,13 +269,30 @@ control_start(struct client *c) { struct control_state *cs; + if (c->flags & CLIENT_CONTROLCONTROL) { + close(c->out_fd); + c->out_fd = -1; + } else + setblocking(c->out_fd, 0); + setblocking(c->fd, 0); + cs = c->control_state = xcalloc(1, sizeof *cs); RB_INIT(&cs->offsets); - file_read(c, "-", control_callback, c); + cs->read_event = bufferevent_new(c->fd, control_read_callback, NULL, + control_error_callback, c); + bufferevent_enable(cs->read_event, EV_READ); if (c->flags & CLIENT_CONTROLCONTROL) - file_print(c, "\033P1000p"); + cs->write_event = cs->read_event; + else { + cs->write_event = bufferevent_new(c->out_fd, NULL, NULL, + control_error_callback, c); + } + bufferevent_enable(cs->write_event, EV_WRITE); + + if (c->flags & CLIENT_CONTROLCONTROL) + control_write(c, "\033P1000p"); } /* Stop control mode. */ @@ -270,6 +301,10 @@ control_stop(struct client *c) { struct control_state *cs = c->control_state; + if (~c->flags & CLIENT_CONTROLCONTROL) + bufferevent_free(cs->write_event); + bufferevent_free(cs->read_event); + control_free_offsets(c); free(cs); } @@ -239,7 +239,9 @@ file_write(struct client *c, const char *path, int flags, const void *bdata, cf->path = xstrdup("-"); fd = STDOUT_FILENO; - if (c == NULL || c->flags & CLIENT_ATTACHED) { + if (c == NULL || + (c->flags & CLIENT_ATTACHED) || + (c->flags & CLIENT_CONTROL)) { cf->error = EBADF; goto done; } @@ -308,7 +310,9 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata) cf->path = xstrdup("-"); fd = STDIN_FILENO; - if (c == NULL || c->flags & CLIENT_ATTACHED) { + if (c == NULL || + (c->flags & CLIENT_ATTACHED) || + (c->flags & CLIENT_CONTROL)) { cf->error = EBADF; goto done; } @@ -496,7 +496,6 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc) gc->fg = gee->fg; gc->bg = gee->bg; gc->us = gee->us; - log_debug("!!! %x", gc->flags); utf8_to_data(gee->data, &gc->data); } return; diff --git a/server-client.c b/server-client.c index 3aae9eaa..ac2272fc 100644 --- a/server-client.c +++ b/server-client.c @@ -221,7 +221,7 @@ server_client_create(int fd) c->environ = environ_create(); c->fd = -1; - c->cwd = NULL; + c->out_fd = -1; c->queue = cmdq_new(); RB_INIT(&c->windows); @@ -336,6 +336,8 @@ server_client_lost(struct client *c) proc_remove_peer(c->peer); c->peer = NULL; + if (c->out_fd != -1) + close(c->out_fd); if (c->fd != -1) { close(c->fd); c->fd = -1; @@ -1571,10 +1573,9 @@ server_client_check_pane_buffer(struct window_pane *wp) out: /* * If there is data remaining, and there are no clients able to consume - * it, do not read any more. This is true when 1) there are attached - * clients 2) all the clients are control clients 3) all of them have - * either the OFF flag set, or are otherwise not able to accept any - * more data for this pane. + * it, do not read any more. This is true when there are attached + * clients, all of which are control clients which are not able to + * accept any more data. */ if (off) bufferevent_disable(wp->event, EV_READ); @@ -1967,6 +1968,7 @@ server_client_dispatch(struct imsg *imsg, void *arg) case MSG_IDENTIFY_TTYNAME: case MSG_IDENTIFY_CWD: case MSG_IDENTIFY_STDIN: + case MSG_IDENTIFY_STDOUT: case MSG_IDENTIFY_ENVIRON: case MSG_IDENTIFY_CLIENTPID: case MSG_IDENTIFY_DONE: @@ -2177,6 +2179,12 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) c->fd = imsg->fd; log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd); break; + case MSG_IDENTIFY_STDOUT: + if (datalen != 0) + fatalx("bad MSG_IDENTIFY_STDOUT size"); + c->out_fd = imsg->fd; + log_debug("client %p IDENTIFY_STDOUT %d", c, imsg->fd); + break; case MSG_IDENTIFY_ENVIRON: if (datalen == 0 || data[datalen - 1] != '\0') fatalx("bad MSG_IDENTIFY_ENVIRON string"); @@ -2209,11 +2217,9 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) c->fd = open(c->ttyname, O_RDWR|O_NOCTTY); #endif - if (c->flags & CLIENT_CONTROL) { - close(c->fd); - c->fd = -1; + if (c->flags & CLIENT_CONTROL) control_start(c); - } else if (c->fd != -1) { + else if (c->fd != -1) { if (tty_init(&c->tty, c) != 0) { close(c->fd); c->fd = -1; @@ -2221,6 +2227,8 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg) tty_resize(&c->tty); c->flags |= CLIENT_TERMINAL; } + close(c->out_fd); + c->out_fd = -1; } /* @@ -2337,7 +2345,8 @@ void server_client_set_flags(struct client *c, const char *flags) { char *s, *copy, *next; - int flag, not; + uint64_t flag; + int not; s = copy = xstrdup (flags); while ((next = strsep(&s, ",")) != NULL) { @@ -1275,7 +1275,10 @@ process_key: append_key: if (key <= 0x1f || key >= KEYC_BASE) return (0); - utf8_to_data(key, &tmp); + if (key <= 0x7f) + utf8_set(&tmp, key); + else + utf8_to_data(key, &tmp); c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, sizeof *c->prompt_buffer); @@ -500,6 +500,7 @@ enum msgtype { MSG_IDENTIFY_CLIENTPID, MSG_IDENTIFY_CWD, MSG_IDENTIFY_FEATURES, + MSG_IDENTIFY_STDOUT, MSG_COMMAND = 200, MSG_DETACH, @@ -969,6 +970,7 @@ struct window_pane { int fd; struct bufferevent *event; + struct window_pane_offset offset; size_t base_offset; @@ -1583,6 +1585,7 @@ struct client { pid_t pid; int fd; + int out_fd; struct event event; int retval; |