mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 14:04:59 +02:00
Added PTY support to account for client TTY window size changes
This commit is contained in:
parent
d6a1ff42ae
commit
f5226a3b70
37
channels.c
37
channels.c
@ -3895,7 +3895,6 @@ channel_connect_to_path(const char *path, char *ctype, char *rname)
|
|||||||
return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
|
return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef WIN32_FIXME//N
|
|
||||||
void
|
void
|
||||||
channel_send_window_changes(void)
|
channel_send_window_changes(void)
|
||||||
{
|
{
|
||||||
@ -3907,8 +3906,21 @@ channel_send_window_changes(void)
|
|||||||
if (channels[i] == NULL || !channels[i]->client_tty ||
|
if (channels[i] == NULL || !channels[i]->client_tty ||
|
||||||
channels[i]->type != SSH_CHANNEL_OPEN)
|
channels[i]->type != SSH_CHANNEL_OPEN)
|
||||||
continue;
|
continue;
|
||||||
|
#ifndef WIN32_FIXME
|
||||||
if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
|
if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
|
||||||
continue;
|
continue
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO c_info;
|
||||||
|
/* TODO - Fix this for multiple channels*/
|
||||||
|
if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &c_info))
|
||||||
|
continue;
|
||||||
|
ws.ws_col = c_info.dwSize.X;
|
||||||
|
ws.ws_row = c_info.dwSize.Y;
|
||||||
|
ws.ws_xpixel = 640;
|
||||||
|
ws.ws_ypixel = 480;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
channel_request_start(i, "window-change", 0);
|
channel_request_start(i, "window-change", 0);
|
||||||
packet_put_int((u_int)ws.ws_col);
|
packet_put_int((u_int)ws.ws_col);
|
||||||
packet_put_int((u_int)ws.ws_row);
|
packet_put_int((u_int)ws.ws_row);
|
||||||
@ -3918,27 +3930,6 @@ channel_send_window_changes(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // WIN32_FIXME
|
|
||||||
void
|
|
||||||
channel_send_window_changes(int col, int row, int xpixel, int ypixel)
|
|
||||||
{
|
|
||||||
u_int i;
|
|
||||||
struct winsize ws;
|
|
||||||
|
|
||||||
for (i = 0; i < channels_alloc; i++) {
|
|
||||||
if (channels[i] == NULL || !channels[i]->client_tty ||
|
|
||||||
channels[i]->type != SSH_CHANNEL_OPEN)
|
|
||||||
continue;
|
|
||||||
channel_request_start(i, "window-change", 0);
|
|
||||||
packet_put_int((u_int)col);
|
|
||||||
packet_put_int((u_int)row);
|
|
||||||
packet_put_int((u_int)xpixel);
|
|
||||||
packet_put_int((u_int)ypixel);
|
|
||||||
packet_send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* -- X11 forwarding */
|
/* -- X11 forwarding */
|
||||||
|
|
||||||
|
@ -226,11 +226,7 @@ void channel_register_status_confirm(int, channel_confirm_cb *,
|
|||||||
channel_confirm_abandon_cb *, void *);
|
channel_confirm_abandon_cb *, void *);
|
||||||
void channel_cancel_cleanup(int);
|
void channel_cancel_cleanup(int);
|
||||||
int channel_close_fd(int *);
|
int channel_close_fd(int *);
|
||||||
#ifndef WIN32_FIXME
|
|
||||||
void channel_send_window_changes(void);
|
void channel_send_window_changes(void);
|
||||||
#else
|
|
||||||
void channel_send_window_changes(int, int, int, int);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* protocol handler */
|
/* protocol handler */
|
||||||
|
24
clientloop.c
24
clientloop.c
@ -537,7 +537,7 @@ client_make_packets_from_stdin_data(void)
|
|||||||
static void
|
static void
|
||||||
client_check_window_change(void)
|
client_check_window_change(void)
|
||||||
{
|
{
|
||||||
#ifndef WIN32_FIXME
|
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
|
|
||||||
if (! received_window_change_signal)
|
if (! received_window_change_signal)
|
||||||
@ -550,6 +550,7 @@ client_check_window_change(void)
|
|||||||
if (compat20) {
|
if (compat20) {
|
||||||
channel_send_window_changes();
|
channel_send_window_changes();
|
||||||
} else {
|
} else {
|
||||||
|
#ifndef WIN32_FIXME
|
||||||
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
|
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
|
||||||
return;
|
return;
|
||||||
packet_start(SSH_CMSG_WINDOW_SIZE);
|
packet_start(SSH_CMSG_WINDOW_SIZE);
|
||||||
@ -558,27 +559,8 @@ client_check_window_change(void)
|
|||||||
packet_put_int((u_int)ws.ws_xpixel);
|
packet_put_int((u_int)ws.ws_xpixel);
|
||||||
packet_put_int((u_int)ws.ws_ypixel);
|
packet_put_int((u_int)ws.ws_ypixel);
|
||||||
packet_send();
|
packet_send();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
|
||||||
if (! win_received_window_change_signal)
|
|
||||||
return;
|
|
||||||
/** XXX race */
|
|
||||||
win_received_window_change_signal = 0;
|
|
||||||
|
|
||||||
debug2("client_check_window_change: changed");
|
|
||||||
|
|
||||||
if (compat20) {
|
|
||||||
channel_send_window_changes(ScreenX, ScrollBottom, 640, 480);
|
|
||||||
} else {
|
|
||||||
packet_start(SSH_CMSG_WINDOW_SIZE);
|
|
||||||
packet_put_int((u_int)ScreenX);
|
|
||||||
packet_put_int((u_int)ScrollBottom);
|
|
||||||
packet_put_int((u_int)640);
|
|
||||||
packet_put_int((u_int)480);
|
|
||||||
packet_send();
|
|
||||||
}
|
|
||||||
#endif /* !WIN32_FIXME */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -86,6 +86,20 @@ native_sig_handler(DWORD dwCtrlType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID CALLBACK
|
||||||
|
sigwinch_APCProc(
|
||||||
|
_In_ ULONG_PTR dwParam
|
||||||
|
) {
|
||||||
|
debug3("SIGTERM APCProc()");
|
||||||
|
sigaddset(&pending_signals, W32_SIGWINCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
queue_terminal_window_change_event() {
|
||||||
|
QueueUserAPC(sigwinch_APCProc, main_thread, (ULONG_PTR)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sw_init_signal_handler_table() {
|
sw_init_signal_handler_table() {
|
||||||
int i;
|
int i;
|
||||||
@ -163,7 +177,7 @@ sw_process_pending_signals() {
|
|||||||
BOOL sig_int = FALSE; /* has any signal actually interrupted */
|
BOOL sig_int = FALSE; /* has any signal actually interrupted */
|
||||||
|
|
||||||
debug3("process_signals()");
|
debug3("process_signals()");
|
||||||
int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP };
|
int i, exp[] = { W32_SIGCHLD , W32_SIGINT , W32_SIGALRM, W32_SIGTERM, W32_SIGTSTP, W32_SIGWINCH };
|
||||||
|
|
||||||
/* check for expected signals*/
|
/* check for expected signals*/
|
||||||
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
|
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
|
||||||
|
@ -116,6 +116,8 @@ BOOL DataAvailable(HANDLE h)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void queue_terminal_window_change_event();
|
||||||
|
|
||||||
int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
|
int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
|
||||||
{
|
{
|
||||||
HANDLE hHandle[] = { hInput, NULL };
|
HANDLE hHandle[] = { hInput, NULL };
|
||||||
@ -148,11 +150,7 @@ int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
|
|||||||
switch (InputRecord.EventType)
|
switch (InputRecord.EventType)
|
||||||
{
|
{
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
memcpy(szResponse, NAWSSTR, 9);
|
queue_terminal_window_change_event();
|
||||||
szResponse[4] = ConScreenSizeX();
|
|
||||||
szResponse[6] = ConWindowSizeY();
|
|
||||||
ScreenX = ConScreenSizeX();
|
|
||||||
ScreenY = ConWindowSizeY();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FOCUS_EVENT:
|
case FOCUS_EVENT:
|
||||||
|
49
session.c
49
session.c
@ -497,6 +497,10 @@ do_authenticated1(Authctxt *authctxt)
|
|||||||
#define USE_PIPES 1
|
#define USE_PIPES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32_FIXME
|
||||||
|
extern int debug_flag;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called to fork and execute a command when we have no tty. This
|
* This is called to fork and execute a command when we have no tty. This
|
||||||
* will call do_child from the child, and server_loop from the parent after
|
* will call do_child from the child, and server_loop from the parent after
|
||||||
@ -548,8 +552,6 @@ do_exec_no_pty(Session *s, const char *command)
|
|||||||
char *exec_command;
|
char *exec_command;
|
||||||
char *laddr;
|
char *laddr;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int prot_scr_width = 80;
|
|
||||||
int prot_scr_height = 25;
|
|
||||||
#ifdef WIN32_PRAGMA_REMCON
|
#ifdef WIN32_PRAGMA_REMCON
|
||||||
char exec_command_str[512];
|
char exec_command_str[512];
|
||||||
#endif
|
#endif
|
||||||
@ -590,8 +592,6 @@ do_exec_no_pty(Session *s, const char *command)
|
|||||||
int retcode = -1;
|
int retcode = -1;
|
||||||
if ( (!s -> is_subsystem) && (s ->ttyfd != -1))
|
if ( (!s -> is_subsystem) && (s ->ttyfd != -1))
|
||||||
{
|
{
|
||||||
prot_scr_width = s->col;
|
|
||||||
prot_scr_height = s->row;
|
|
||||||
extern HANDLE hInputConsole;
|
extern HANDLE hInputConsole;
|
||||||
extern HANDLE hOutputConsole ;
|
extern HANDLE hOutputConsole ;
|
||||||
hInputConsole = GetConsoleInputHandle();
|
hInputConsole = GetConsoleInputHandle();
|
||||||
@ -620,10 +620,10 @@ do_exec_no_pty(Session *s, const char *command)
|
|||||||
si.lpTitle = NULL; /* NULL means use exe name as title */
|
si.lpTitle = NULL; /* NULL means use exe name as title */
|
||||||
si.dwX = 0;
|
si.dwX = 0;
|
||||||
si.dwY = 0;
|
si.dwY = 0;
|
||||||
si.dwXSize = 640;
|
si.dwXSize = 5;
|
||||||
si.dwYSize = 480;
|
si.dwYSize = 5;
|
||||||
si.dwXCountChars = prot_scr_width;
|
si.dwXCountChars = s->col;
|
||||||
si.dwYCountChars = prot_scr_height;
|
si.dwYCountChars = s->row;
|
||||||
si.dwFillAttribute = 0;
|
si.dwFillAttribute = 0;
|
||||||
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
|
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
|
||||||
si.wShowWindow = 0; // FALSE ;
|
si.wShowWindow = 0; // FALSE ;
|
||||||
@ -794,32 +794,35 @@ do_exec_no_pty(Session *s, const char *command)
|
|||||||
wchar_t exec_command_w[MAX_PATH];
|
wchar_t exec_command_w[MAX_PATH];
|
||||||
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, exec_command, -1, exec_command_w, MAX_PATH);
|
MultiByteToWideChar(CP_UTF8, 0, exec_command, -1, exec_command_w, MAX_PATH);
|
||||||
DWORD dwStartupFlags = 0;// CREATE_SUSPENDED; // 0
|
DWORD dwStartupFlags = DETACHED_PROCESS;// CREATE_SUSPENDED; // 0
|
||||||
|
|
||||||
SetConsoleCtrlHandler(NULL, FALSE);
|
SetConsoleCtrlHandler(NULL, FALSE);
|
||||||
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
|
if (debug_flag)
|
||||||
|
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
|
||||||
|
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s->pw->pw_dir,
|
||||||
|
&si, &pi);
|
||||||
|
else
|
||||||
|
b = CreateProcessAsUserW(hToken, NULL, exec_command_w, NULL, NULL, TRUE,
|
||||||
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s -> pw -> pw_dir,
|
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s -> pw -> pw_dir,
|
||||||
&si, &pi);
|
&si, &pi);
|
||||||
/*
|
|
||||||
* If CreateProcessAsUser() fails we will try CreateProcess()
|
|
||||||
* but only if current user and login user are the same.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((!b) && (strcmp(name, s -> pw -> pw_name) == 0))
|
|
||||||
{
|
|
||||||
b = CreateProcessW(NULL, exec_command_w, NULL, NULL, TRUE,
|
|
||||||
/*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags, NULL, s -> pw -> pw_dir,
|
|
||||||
&si, &pi);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!b)
|
if (!b)
|
||||||
{
|
{
|
||||||
debug("ERROR. Cannot create process as new user (%u).\n", GetLastError());
|
debug("ERROR. Cannot create process (%u).\n", GetLastError());
|
||||||
|
|
||||||
CloseHandle(hToken);
|
CloseHandle(hToken);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
FreeConsole();
|
||||||
|
if (!debug_flag)
|
||||||
|
ImpersonateLoggedOnUser(hToken);
|
||||||
|
while (AttachConsole(pi.dwProcessId) == FALSE) {
|
||||||
|
Sleep(200);
|
||||||
|
}
|
||||||
|
if (!debug_flag)
|
||||||
|
RevertToSelf();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save token used for create child process. We'll need it on cleanup
|
* Save token used for create child process. We'll need it on cleanup
|
||||||
|
39
sshpty.c
39
sshpty.c
@ -197,32 +197,6 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32_PRAGMA_REMCON
|
|
||||||
/* Changes the window size associated with the pty. */
|
|
||||||
|
|
||||||
void pty_change_window_size_oob(int ptyfd, u_int row, u_int col, u_int xpixel, u_int ypixel)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
char unsigned data[16];
|
|
||||||
size_t data_len;
|
|
||||||
|
|
||||||
// IAC SB NAWS <16-bit value width> <16-bit value height> IAC
|
|
||||||
//sprintf (data,"%c%c%c%c%c%c%c%c", 255, 250, 31, 0, col, 0, row, 255 );
|
|
||||||
data[0] = 255; // IAC;
|
|
||||||
data[1] = 250; // SB
|
|
||||||
data[2] = 31; // NAWS
|
|
||||||
data[3] = 0;
|
|
||||||
data[4] = (unsigned char)col;
|
|
||||||
data[5] = 0;
|
|
||||||
data[6] = (unsigned char)row;
|
|
||||||
data[7] = 255; // IAC
|
|
||||||
data[8] = 240; // iac end
|
|
||||||
data_len = 9; //strlen (data);
|
|
||||||
rc = write(ptyfd, data, (DWORD)data_len);
|
|
||||||
//rc = AsyncWrite(c->hInputHandle, (char *)data, (DWORD)data_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* Changes the window size associated with the pty. */
|
/* Changes the window size associated with the pty. */
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -239,15 +213,10 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
|
|||||||
w.ws_ypixel = ypixel;
|
w.ws_ypixel = ypixel;
|
||||||
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
|
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
|
||||||
#else
|
#else
|
||||||
extern HANDLE hOutputConsole ;
|
COORD coord;
|
||||||
#ifndef WIN32_PRAGMA_REMCON
|
coord.X = col;
|
||||||
if (hOutputConsole != NULL) {
|
coord.Y = row;
|
||||||
ConSetScreenSize(col, row);
|
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (ptyfd > 0 )
|
|
||||||
pty_change_window_size_oob(ptyfd, row, col, xpixel, ypixel);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user