Added PTY support to account for client TTY window size changes

This commit is contained in:
Manoj Ampalam 2016-09-29 17:27:21 -07:00
parent d6a1ff42ae
commit f5226a3b70
7 changed files with 65 additions and 112 deletions

View File

@ -3895,7 +3895,6 @@ channel_connect_to_path(const char *path, char *ctype, char *rname)
return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
}
#ifndef WIN32_FIXME//N
void
channel_send_window_changes(void)
{
@ -3907,8 +3906,21 @@ channel_send_window_changes(void)
if (channels[i] == NULL || !channels[i]->client_tty ||
channels[i]->type != SSH_CHANNEL_OPEN)
continue;
#ifndef WIN32_FIXME
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);
packet_put_int((u_int)ws.ws_col);
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 */

View File

@ -226,11 +226,7 @@ void channel_register_status_confirm(int, channel_confirm_cb *,
channel_confirm_abandon_cb *, void *);
void channel_cancel_cleanup(int);
int channel_close_fd(int *);
#ifndef WIN32_FIXME
void channel_send_window_changes(void);
#else
void channel_send_window_changes(int, int, int, int);
#endif
/* protocol handler */

View File

@ -537,7 +537,7 @@ client_make_packets_from_stdin_data(void)
static void
client_check_window_change(void)
{
#ifndef WIN32_FIXME
struct winsize ws;
if (! received_window_change_signal)
@ -550,6 +550,7 @@ client_check_window_change(void)
if (compat20) {
channel_send_window_changes();
} else {
#ifndef WIN32_FIXME
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
return;
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_ypixel);
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

View File

@ -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
sw_init_signal_handler_table() {
int i;
@ -163,7 +177,7 @@ sw_process_pending_signals() {
BOOL sig_int = FALSE; /* has any signal actually interrupted */
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*/
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)

View File

@ -116,6 +116,8 @@ BOOL DataAvailable(HANDLE h)
return FALSE;
}
void queue_terminal_window_change_event();
int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
{
HANDLE hHandle[] = { hInput, NULL };
@ -148,11 +150,7 @@ int ReadConsoleForTermEmul(HANDLE hInput, char *destin, int destinlen)
switch (InputRecord.EventType)
{
case WINDOW_BUFFER_SIZE_EVENT:
memcpy(szResponse, NAWSSTR, 9);
szResponse[4] = ConScreenSizeX();
szResponse[6] = ConWindowSizeY();
ScreenX = ConScreenSizeX();
ScreenY = ConWindowSizeY();
queue_terminal_window_change_event();
break;
case FOCUS_EVENT:

View File

@ -497,6 +497,10 @@ do_authenticated1(Authctxt *authctxt)
#define USE_PIPES 1
#endif
#ifdef WIN32_FIXME
extern int debug_flag;
#endif
/*
* 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
@ -548,8 +552,6 @@ do_exec_no_pty(Session *s, const char *command)
char *exec_command;
char *laddr;
char buf[256];
int prot_scr_width = 80;
int prot_scr_height = 25;
#ifdef WIN32_PRAGMA_REMCON
char exec_command_str[512];
#endif
@ -590,8 +592,6 @@ do_exec_no_pty(Session *s, const char *command)
int retcode = -1;
if ( (!s -> is_subsystem) && (s ->ttyfd != -1))
{
prot_scr_width = s->col;
prot_scr_height = s->row;
extern HANDLE hInputConsole;
extern HANDLE hOutputConsole ;
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.dwX = 0;
si.dwY = 0;
si.dwXSize = 640;
si.dwYSize = 480;
si.dwXCountChars = prot_scr_width;
si.dwYCountChars = prot_scr_height;
si.dwXSize = 5;
si.dwYSize = 5;
si.dwXCountChars = s->col;
si.dwYCountChars = s->row;
si.dwFillAttribute = 0;
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESIZE | STARTF_USECOUNTCHARS;
si.wShowWindow = 0; // FALSE ;
@ -794,32 +794,35 @@ do_exec_no_pty(Session *s, const char *command)
wchar_t 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);
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,
&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)
{
debug("ERROR. Cannot create process as new user (%u).\n", GetLastError());
debug("ERROR. Cannot create process (%u).\n", GetLastError());
CloseHandle(hToken);
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

View File

@ -197,32 +197,6 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
#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. */
void
@ -239,15 +213,10 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
w.ws_ypixel = ypixel;
(void) ioctl(ptyfd, TIOCSWINSZ, &w);
#else
extern HANDLE hOutputConsole ;
#ifndef WIN32_PRAGMA_REMCON
if (hOutputConsole != NULL) {
ConSetScreenSize(col, row);
}
#else
if (ptyfd > 0 )
pty_change_window_size_oob(ptyfd, row, col, xpixel, ypixel);
#endif
COORD coord;
coord.X = col;
coord.Y = row;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coord);
#endif
}