From f260bbaacfa6b20aa0b2021441652fe27dcdec3f Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 7 Dec 2022 09:44:44 +0000 Subject: [PATCH] Process escape sequences in show-buffer, GitHub issue 3401. --- usr.bin/tmux/cmd-queue.c | 98 +++++++++++++++++++++++++--------- usr.bin/tmux/cmd-save-buffer.c | 15 +++--- usr.bin/tmux/tmux.h | 3 +- 3 files changed, 83 insertions(+), 33 deletions(-) diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c index b63d2a8d491..9f3b2ca4527 100644 --- a/usr.bin/tmux/cmd-queue.c +++ b/usr.bin/tmux/cmd-queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-queue.c,v 1.110 2022/05/30 13:00:18 nicm Exp $ */ +/* $OpenBSD: cmd-queue.c,v 1.111 2022/12/07 09:44:44 nicm Exp $ */ /* * Copyright (c) 2013 Nicholas Marriott @@ -24,6 +24,7 @@ #include #include #include +#include #include "tmux.h" @@ -823,43 +824,88 @@ cmdq_guard(struct cmdq_item *item, const char *guard, int flags) /* Show message from command. */ void -cmdq_print(struct cmdq_item *item, const char *fmt, ...) +cmdq_print_data(struct cmdq_item *item, int parse, struct evbuffer *evb) { struct client *c = item->client; + void *data = EVBUFFER_DATA(evb); + size_t size = EVBUFFER_LENGTH(evb); struct window_pane *wp; struct window_mode_entry *wme; - va_list ap; - char *tmp, *msg; - - va_start(ap, fmt); - xvasprintf(&msg, fmt, ap); - va_end(ap); + char *sanitized, *msg, *line; - log_debug("%s: %s", __func__, msg); + if (!parse) { + utf8_stravisx(&msg, data, size, VIS_OCTAL|VIS_CSTYLE|VIS_TAB); + log_debug("%s: %s", __func__, msg); + } else { + msg = EVBUFFER_DATA(evb); + if (msg[size - 1] != '\0') + evbuffer_add(evb, "", 1); + } if (c == NULL) - /* nothing */; - else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { + goto out; + + if (c->session == NULL || (c->flags & CLIENT_CONTROL)) { if (~c->flags & CLIENT_UTF8) { - tmp = msg; - msg = utf8_sanitize(tmp); - free(tmp); + sanitized = utf8_sanitize(msg); + if (c->flags & CLIENT_CONTROL) + control_write(c, "%s", sanitized); + else + file_print(c, "%s\n", sanitized); + free(sanitized); + } else { + if (c->flags & CLIENT_CONTROL) + control_write(c, "%s", msg); + else + file_print(c, "%s\n", msg); } - if (c->flags & CLIENT_CONTROL) - control_write(c, "%s", msg); - else - file_print(c, "%s\n", msg); - } else { - wp = server_client_get_pane(c); - wme = TAILQ_FIRST(&wp->modes); - if (wme == NULL || wme->mode != &window_view_mode) { - window_pane_set_mode(wp, NULL, &window_view_mode, NULL, - NULL); + goto out; + } + + wp = server_client_get_pane(c); + wme = TAILQ_FIRST(&wp->modes); + if (wme == NULL || wme->mode != &window_view_mode) + window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL); + if (parse) { + do { + line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF); + if (line != NULL) { + window_copy_add(wp, 1, "%s", line); + free(line); + } + } while (line != NULL); + + size = EVBUFFER_LENGTH(evb); + if (size != 0) { + line = EVBUFFER_DATA(evb); + window_copy_add(wp, 1, "%.*s", (int)size, line); } + } else window_copy_add(wp, 0, "%s", msg); - } - free(msg); +out: + if (!parse) + free(msg); + +} + +/* Show message from command. */ +void +cmdq_print(struct cmdq_item *item, const char *fmt, ...) +{ + va_list ap; + struct evbuffer *evb; + + evb = evbuffer_new(); + if (evb == NULL) + fatalx("out of memory"); + + va_start(ap, fmt); + evbuffer_add_vprintf(evb, fmt, ap); + va_end(ap); + + cmdq_print_data(item, 0, evb); + evbuffer_free(evb); } /* Show error from command. */ diff --git a/usr.bin/tmux/cmd-save-buffer.c b/usr.bin/tmux/cmd-save-buffer.c index 080555ec46c..17905128aad 100644 --- a/usr.bin/tmux/cmd-save-buffer.c +++ b/usr.bin/tmux/cmd-save-buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-save-buffer.c,v 1.54 2021/08/21 10:22:39 nicm Exp $ */ +/* $OpenBSD: cmd-save-buffer.c,v 1.55 2022/12/07 09:44:44 nicm Exp $ */ /* * Copyright (c) 2009 Tiago Cunha @@ -79,7 +79,8 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item) int flags; const char *bufname = args_get(args, 'b'), *bufdata; size_t bufsize; - char *path, *tmp; + char *path; + struct evbuffer *evb; if (bufname == NULL) { if ((pb = paste_get_top(NULL)) == NULL) { @@ -97,10 +98,12 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item) if (cmd_get_entry(self) == &cmd_show_buffer_entry) { if (c->session != NULL || (c->flags & CLIENT_CONTROL)) { - utf8_stravisx(&tmp, bufdata, bufsize, - VIS_OCTAL|VIS_CSTYLE|VIS_TAB); - cmdq_print(item, "%s", tmp); - free(tmp); + evb = evbuffer_new(); + if (evb == NULL) + fatalx("out of memory"); + evbuffer_add(evb, bufdata, bufsize); + cmdq_print_data(item, 1, evb); + evbuffer_free(evb); return (CMD_RETURN_NORMAL); } path = xstrdup("-"); diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 28e4451c7d3..bff6b2646a5 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1185 2022/11/11 08:37:55 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1186 2022/12/07 09:44:44 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2550,6 +2550,7 @@ u_int cmdq_next(struct client *); struct cmdq_item *cmdq_running(struct client *); void cmdq_guard(struct cmdq_item *, const char *, int); void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...); +void cmdq_print_data(struct cmdq_item *, int, struct evbuffer *); void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...); /* cmd-wait-for.c */ -- 2.20.1