Pass in the terminal size when creating a WSLA process

This commit is contained in:
Blue 2025-11-25 18:20:41 -08:00
parent 6d388c19eb
commit 5fe8aaa6f5
6 changed files with 27 additions and 17 deletions

View File

@ -1666,10 +1666,8 @@ struct WSLA_TTY_RELAY
int32_t TtyInput;
int32_t TtyOutput;
int32_t TtyControl;
uint32_t Rows;
uint32_t Columns;
PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl), FIELD(Rows), FIELD(Columns));
PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl));
};
struct WSLA_ACCEPT

View File

@ -48,6 +48,12 @@ void WSLAProcessLauncher::AddFd(WSLA_PROCESS_FD Fd)
m_fds.push_back(Fd);
}
void WSLAProcessLauncher::SetTtySize(ULONG Rows, ULONG Columns)
{
m_rows = Rows;
m_columns = Columns;
}
std::tuple<WSLA_PROCESS_OPTIONS, std::vector<const char*>, std::vector<const char*>> WSLAProcessLauncher::CreateProcessOptions()
{
std::vector<const char*> commandLine;
@ -64,6 +70,8 @@ std::tuple<WSLA_PROCESS_OPTIONS, std::vector<const char*>, std::vector<const cha
options.FdsCount = static_cast<DWORD>(m_fds.size());
options.Environment = environment.data();
options.EnvironmentCount = static_cast<DWORD>(environment.size());
options.TtyColumns = m_columns;
options.TtyRows = m_rows;
return std::make_tuple(options, std::move(commandLine), std::move(environment));
}

View File

@ -96,6 +96,8 @@ protected:
std::string m_executable;
std::vector<std::string> m_arguments;
std::vector<std::string> m_environment;
DWORD m_rows = 0;
DWORD m_columns = 0;
};
} // namespace wsl::windows::common

View File

@ -1606,21 +1606,23 @@ int WslaShell(_In_ std::wstring_view commandLine)
THROW_HR_IF(E_FAIL, initProcess.WaitAndCaptureOutput().Code != 0);
}
// Get the terminal size.
HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFOEX Info{};
Info.cbSize = sizeof(Info);
THROW_IF_WIN32_BOOL_FALSE(::GetConsoleScreenBufferInfoEx(Stdout, &Info));
wsl::windows::common::WSLAProcessLauncher launcher{shell, {shell}, {"TERM=xterm-256color"}, ProcessFlags::None};
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 0, .Type = WSLAFdTypeTerminalInput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 1, .Type = WSLAFdTypeTerminalOutput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 2, .Type = WSLAFdTypeTerminalControl});
// Add the terminal size.
CONSOLE_SCREEN_BUFFER_INFOEX Info{};
Info.cbSize = sizeof(Info);
launcher.SetTtySize(Info.srWindow.Bottom - Info.srWindow.Top + 1, Info.srWindow.Right - Info.srWindow.Left + 1);
auto process = launcher.Launch(*session);
// Configure console for interactive usage.
HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
{
DWORD OutputMode{};
THROW_LAST_ERROR_IF(!::GetConsoleMode(Stdout, &OutputMode));

View File

@ -727,7 +727,8 @@ std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::For
return Fork(m_initChannel, Type);
}
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::Fork(wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type)
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::Fork(
wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type, ULONG TtyRows, ULONG TtyColumns)
{
uint32_t port{};
int32_t pid{};
@ -737,8 +738,8 @@ std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> WSLAVirtualMachine::For
WSLA_FORK message;
message.ForkType = Type;
message.TtyColumns = 80;
message.TtyRows = 80;
message.TtyColumns = static_cast<uint16_t>(TtyColumns);
message.TtyRows = static_cast<uint16_t>(TtyRows);
const auto& response = Channel.Transaction(message);
port = response.Port;
pid = response.Pid;
@ -857,14 +858,12 @@ Microsoft::WRL::ComPtr<WSLAProcess> WSLAVirtualMachine::CreateLinuxProcess(_In_
// If this is an interactive tty, we need a relay process
if (interactiveTty)
{
auto [grandChildPid, ptyMaster, grandChildChannel] = Fork(childChannel, WSLA_FORK::Pty);
auto [grandChildPid, ptyMaster, grandChildChannel] = Fork(childChannel, WSLA_FORK::Pty, Options.TtyRows, Options.TtyColumns);
WSLA_TTY_RELAY relayMessage{};
relayMessage.TtyMaster = ptyMaster;
relayMessage.TtyInput = ttyInput->Fd;
relayMessage.TtyOutput = ttyOutput->Fd;
relayMessage.TtyControl = ttyControl == nullptr ? -1 : ttyControl->Fd;
relayMessage.Rows = Options.TtyRows;
relayMessage.Columns = Options.TtyColumns;
childChannel.SendMessage(relayMessage);
auto result = ExpectClosedChannelOrError(childChannel);

View File

@ -82,7 +82,8 @@ private:
void OnCrash(_In_ const HCS_EVENT* Event);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(enum WSLA_FORK::ForkType Type);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type);
std::tuple<int32_t, int32_t, wsl::shared::SocketChannel> Fork(
wsl::shared::SocketChannel& Channel, enum WSLA_FORK::ForkType Type, ULONG TtyRows = 0, ULONG TtyColumns = 0);
int32_t ExpectClosedChannelOrError(wsl::shared::SocketChannel& Channel);
ConnectedSocket ConnectSocket(wsl::shared::SocketChannel& Channel, int32_t Fd);