From f31eae1a41ddaf136190acfc040c0bdb720f3b7e Mon Sep 17 00:00:00 2001 From: mintty Date: Thu, 12 Nov 2020 00:00:00 +0100 Subject: [PATCH] add missing patch to repository --- 0001-notify-size-change-inband.patch | 257 +++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 0001-notify-size-change-inband.patch diff --git a/0001-notify-size-change-inband.patch b/0001-notify-size-change-inband.patch new file mode 100644 index 0000000..b93bea3 --- /dev/null +++ b/0001-notify-size-change-inband.patch @@ -0,0 +1,257 @@ +Date: Tue, 15 Sep 2020 06:15:34 +0200 +Subject: [PATCH] notify window size change via escaped inband information + (Biswa96/wslbridge2#21, mintty/wsltty#220) +Co-authored-by: Thomas Wolff + +--- + src/wslbridge2-backend.cpp | 87 +++++++++++++++++++++++++++++++++++++- + src/wslbridge2.cpp | 83 ++++++++++++++++++++++++++++++------ + 2 files changed, 155 insertions(+), 15 deletions(-) + +diff --git a/src/wslbridge2-backend.cpp b/src/wslbridge2-backend.cpp +index b50ee9c..ad429ae 100644 +--- a/src/wslbridge2-backend.cpp ++++ b/src/wslbridge2-backend.cpp +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include // PIPE_BUF + + #include + #include +@@ -315,6 +316,9 @@ int main(int argc, char *argv[]) + /* Use dupped master fd to read OR write */ + const int mfd_dp = dup(mfd); + assert(mfd_dp > 0); ++#ifdef debug_to_input ++ FILE * debug = fdopen(mfd_dp, "w"); // for fprintf ++#endif + + sigset_t set; + sigemptyset(&set); +@@ -333,6 +337,7 @@ int main(int argc, char *argv[]) + + ssize_t readRet = 0, writeRet = 0; + char data[1024]; /* Buffer to hold raw data from pty */ ++ assert(sizeof data <= PIPE_BUF); + + do + { +@@ -343,8 +348,86 @@ int main(int argc, char *argv[]) + if (fds[0].revents & POLLIN) + { + readRet = recv(ioSockets.inputSock, data, sizeof data, 0); +- if (readRet > 0) +- writeRet = write(mfd_dp, data, readRet); ++ ++ char * s = data; ++ int len = readRet; ++ writeRet = 1; ++ while (writeRet > 0 && len > 0) ++ { ++ if (!*s) ++ { ++ // dispatch NUL escaped inband information ++ s++; ++ len--; ++ ++ if (len < 9 && s + 9 >= data + sizeof data) ++ { ++ // make room for additional loading ++ memcpy(data, s, len); ++ s = data; ++ } ++ ++ // ensure 1 more byte is loaded to dispatch on ++ if (!len) ++ { ++ readRet = recv(ioSockets.inputSock, s, 1, 0); ++ if (readRet > 0) ++ { ++ len += readRet; ++ } ++ else ++ { ++ writeRet = -1; ++ break; ++ } ++ } ++ if (*s == 2) ++ { ++ // STX: escaped NUL ++ s++; ++ len--; ++ writeRet = write(mfd_dp, "", 1); ++ } ++ else if (*s == 16) ++ { ++ // DLE: terminal window size change ++ s++; ++ len--; ++ // ensure 8 more bytes are loaded for winsize ++ while (readRet > 0 && len < 8) ++ { ++ readRet = recv(ioSockets.inputSock, s + len, 8 - len, 0); ++ if (readRet > 0) ++ { ++ len += readRet; ++ } ++ } ++ if (readRet <= 0) ++ { ++ writeRet = -1; ++ break; ++ } ++ struct winsize * winsp = (struct winsize *)s; ++ s += 8; ++ len -= 8; ++ winsp->ws_xpixel = 0; ++ winsp->ws_ypixel = 0; ++ ret = ioctl(mfd, TIOCSWINSZ, winsp); ++ if (ret != 0) ++ perror("ioctl(TIOCSWINSZ)"); ++ } ++ } ++ else ++ { ++ int n = strnlen(s, len); ++ writeRet = write(mfd_dp, s, n); ++ if (writeRet > 0) ++ { ++ s += writeRet; ++ len -= writeRet; ++ } ++ } ++ } + } + + /* Resize window when buffer received in control socket */ +diff --git a/src/wslbridge2.cpp b/src/wslbridge2.cpp +index 75ccb1b..e9fbbf7 100644 +--- a/src/wslbridge2.cpp ++++ b/src/wslbridge2.cpp +@@ -56,32 +56,85 @@ union IoSockets + /* global variable */ + static union IoSockets g_ioSockets = { 0, 0, 0 }; + ++ ++#define dont_debug_inband ++#define dont_use_controlsocket ++ + static void resize_window(int signum) + { ++#ifdef use_controlsocket ++#warning this may crash for unknown reason, maybe terminate the backend + struct winsize winp; ++ ioctl(STDIN_FILENO, TIOCGWINSZ, &winp); + + /* Send terminal window size to control socket */ +- ioctl(STDIN_FILENO, TIOCGWINSZ, &winp); + send(g_ioSockets.controlSock, &winp, sizeof winp, 0); ++#else ++ static char wins[2 + sizeof(struct winsize)] = {0, 16}; ++ static struct winsize * winsp = (struct winsize *)&wins[2]; ++ ioctl(STDIN_FILENO, TIOCGWINSZ, winsp); ++ ++#ifdef debug_inband ++ /* Send terminal window size inband, visualized as ESC sequence */ ++ char resizesc[55]; ++ //sprintf(resizesc, "\e_8;%u;%u\a", winsp->ws_row, winsp->ws_col); ++ sprintf(resizesc, "^[_8;%u;%u^G", winsp->ws_row, winsp->ws_col); ++ send(g_ioSockets.inputSock, resizesc, strlen(resizesc), 0); ++#else ++ /* Send terminal window size inband, with NUL escape */ ++ send(g_ioSockets.inputSock, wins, sizeof wins, 0); ++#endif ++#endif + } + + static void* send_buffer(void *param) + { + int ret; + char data[1024]; +- +- struct pollfd fds = { STDIN_FILENO, POLLIN, 0 }; ++ assert(sizeof data <= PIPE_BUF); + + while (1) + { ++#ifdef use_poll ++ // we could poll on a single channel but we don't need to ++ static struct pollfd fds = { STDIN_FILENO, POLLIN, 0 }; + ret = poll(&fds, 1, -1); + + if (fds.revents & POLLIN) ++#else ++ if (1) ++#endif + { + ret = read(STDIN_FILENO, data, sizeof data); +- if (ret > 0) +- ret = send(g_ioSockets.inputSock, data, ret, 0); +- else ++ ++ char * s = data; ++ int len = ret; ++ while (ret > 0 && len > 0) ++ { ++ if (!*s) ++ { ++ // send NUL STX ++#ifdef debug_inband ++ ret = send(g_ioSockets.inputSock, (void*)"nul", 3, 0); ++#else ++ static char NUL_STX[] = {0, 2}; ++ ret = send(g_ioSockets.inputSock, NUL_STX, 2, 0); ++#endif ++ s++; ++ len--; ++ } ++ else ++ { ++ int n = strnlen(s, len); ++ ret = send(g_ioSockets.inputSock, s, n, 0); ++ if (ret > 0) ++ { ++ s += ret; ++ len -= ret; ++ } ++ } ++ } ++ if (ret <= 0) + break; + } + } +@@ -537,13 +590,6 @@ int main(int argc, char *argv[]) + closesocket(controlSocket); + } + +- /* Create thread to send window size through control socket */ +- struct sigaction act = {}; +- act.sa_handler = resize_window; +- act.sa_flags = SA_RESTART; +- ret = sigaction(SIGWINCH, &act, NULL); +- assert(ret == 0); +- + /* Create thread to send input buffer to input socket */ + pthread_t tidInput; + ret = pthread_create(&tidInput, nullptr, send_buffer, nullptr); +@@ -556,6 +602,17 @@ int main(int argc, char *argv[]) + + termState.enterRawMode(); + ++ /* Create thread to send window size through control socket */ ++ struct sigaction act = {}; ++ act.sa_handler = resize_window; ++ act.sa_flags = SA_RESTART; ++ ret = sigaction(SIGWINCH, &act, NULL); ++ assert(ret == 0); ++ ++ /* Notify initial size in case it's changed since starting */ ++ //resize_window(0); ++ kill(getpid(), SIGWINCH); ++ + /* + * wsltty#254: WORKAROUND: Terminates input thread forcefully + * when output thread exits. Need some inter-thread syncing.