diff --git a/channels.c b/channels.c index 61bc0ea..f5c3e8d 100644 --- a/channels.c +++ b/channels.c @@ -2459,6 +2459,8 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) if ( data[0] == '\033' ) { // escape char octal 33, decimal 27 if ( (data[1] == '[') && (data[2]== '2') && (data[3]== '0') && ( data[4]== 'h' )) { lftocrlf = 1; + data = data + 5 ; // we have processed the 5 bytes ESC sequence + data_len = data_len - 5; } } } @@ -2466,8 +2468,18 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) if (c->datagram) buffer_put_string(&c->output, data, data_len); - else + else { + #ifndef WIN32_FIXME buffer_append(&c->output, data, data_len); + #else + buffer_append(&c->output, data, data_len); + if ( c->isatty ) { + buffer_append(&c->input, data, data_len); // we echo the data if it is sshd server and pty interactive mode + if ( (data_len ==1) && (data[0] == '\b') ) + buffer_append(&c->input, " \b", 2); // for backspace, we need to send space and another backspace for visual erase + } + #endif + } packet_check_eom(); return 0; } diff --git a/contrib/win32/win32compat/socket.c b/contrib/win32/win32compat/socket.c index 4e0b250..eb660f7 100644 --- a/contrib/win32/win32compat/socket.c +++ b/contrib/win32/win32compat/socket.c @@ -2453,6 +2453,38 @@ int WSHELPread(int sfd, char *dst, unsigned int max) case SFD_TYPE_CONSOLE: { ret = _read(sfd_to_fd(sfd), dst, max); + + if (FD_ISSET(sfd_to_fd(sfd), &debug_sfds)) + { + if (ret > 0) + { + dst[ret] = '\0'; + + debug("read[%d] len %d: %s", sfd_to_fd(sfd), ret, dst); + } + } + + if (ret < 0) + { + error("read from pipe/console sfd [%d] failed with error code [%d]", + sfd, GetLastError()); + } + + break; + } + case 99: + { + ret = _getch(); + if ( ( ret == 0) || (ret == 0xE0) ) { + dst[0] = ret ; + ret = _getch(); // function key or arrow key needs 2 calls, the first returning a 0 or 0xE0 + dst[1] = ret; + ret = 2; + } + else { + dst[0] = ret; + ret = 1; + } if (FD_ISSET(sfd_to_fd(sfd), &debug_sfds)) { diff --git a/session.c b/session.c index f02631e..9919a1a 100644 --- a/session.c +++ b/session.c @@ -774,6 +774,21 @@ do_exec_no_pty(Session *s, const char *command) GetUserName(name, &size); + //if (!(s -> is_subsystem)) { + // Send to the remote client ANSI/VT Sequence so that they send us CRLF in place of LF + //Channel *c=channel_by_id ( s->chanid ); + //buffer_append(&c->input, "\033[20h", 5); + //channel_output_poll(); + //} + + //if (s ->ttyfd != -1) { + // set the channel to tty interactive type + // Channel *c=channel_by_id ( s->chanid ); + // c->isatty = 1; + //} + + if ( (s->term) && (s->term[0]) ) + SetEnvironmentVariable("TERM", s->term); /* * Create new process as other user using access token object. */ @@ -869,8 +884,11 @@ do_exec_no_pty(Session *s, const char *command) */ if (compat20) - { - session_set_fds(s, sockin[1], sockout[1], sockerr[1], s -> is_subsystem, 0); + { + if ( s->ttyfd == -1) + session_set_fds(s, sockin[1], sockout[1], sockerr[1], s -> is_subsystem, 0); + else + session_set_fds(s, sockin[1], sockout[1], sockerr[1], s -> is_subsystem, 1); // tty interctive session } else { diff --git a/sshpty.c b/sshpty.c index e794566..2fba470 100644 --- a/sshpty.c +++ b/sshpty.c @@ -91,10 +91,13 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) #else /* - * Not implemented on Win32. + * Simple console screen implementation in Win32 to give a Unix like pty for interactive sessions */ - - return 0; + *ttyfd = 0; // first ttyfd & ptyfd is indexed at 0 + *ptyfd = 0; + strlcpy(namebuf, "console", namebuflen); + return 1; + //return 0; #endif } diff --git a/ttymodes.c b/ttymodes.c index 363e78a..bdbf4cf 100644 --- a/ttymodes.c +++ b/ttymodes.c @@ -505,5 +505,141 @@ set: /* Set the new modes for the terminal. */ if (tcsetattr(fd, TCSANOW, &tio) == -1) logit("Setting tty modes failed: %.100s", strerror(errno)); +#else + //struct termios tio; + u_int tio[255]; // win32 dummy + u_int tioFIELD ; + int opcode, baud; + int n_bytes = 0; + int failure = 0; + u_int (*get_arg)(void); + int arg_size; + + if (compat20) { + *n_bytes_ptr = packet_get_int(); + if (*n_bytes_ptr == 0) + return; + get_arg = packet_get_int; + arg_size = 4; + } else { + get_arg = packet_get_char; + arg_size = 1; + } + + /* + * Get old attributes for the terminal. We will modify these + * flags. I am hoping that if there are any machine-specific + * modes, they will initially have reasonable values. + */ + //if (tcgetattr(fd, &tio) == -1) { + //logit("tcgetattr: %.100s", strerror(errno)); + //failure = -1; + //} + + for (;;) { + n_bytes += 1; + opcode = packet_get_char(); + switch (opcode) { + case TTY_OP_END: + goto set; + + /* XXX: future conflict possible */ + case TTY_OP_ISPEED_PROTO1: + case TTY_OP_ISPEED_PROTO2: + n_bytes += 4; + baud = packet_get_int(); + break; + + /* XXX: future conflict possible */ + case TTY_OP_OSPEED_PROTO1: + case TTY_OP_OSPEED_PROTO2: + n_bytes += 4; + baud = packet_get_int(); + break; + +#define TTYCHAR(NAME, OP) \ + case OP: \ + n_bytes += arg_size; \ + tio[NAME] = special_char_decode(get_arg()); \ + break; +#define TTYMODE(NAME, FIELD, OP) \ + case OP: \ + n_bytes += arg_size; \ + if (get_arg()) \ + tioFIELD |= NAME; \ + else \ + tioFIELD &= ~NAME; \ + break; + +//#include "ttymodes.h" + +#undef TTYCHAR +#undef TTYMODE + + default: + debug("Ignoring unsupported tty mode opcode %d (0x%x)", + opcode, opcode); + if (!compat20) { + /* + * SSH1: + * Opcodes 1 to 127 are defined to have + * a one-byte argument. + * Opcodes 128 to 159 are defined to have + * an integer argument. + */ + if (opcode > 0 && opcode < 128) { + n_bytes += 1; + (void) packet_get_char(); + break; + } else if (opcode >= 128 && opcode < 160) { + n_bytes += 4; + (void) packet_get_int(); + break; + } else { + /* + * It is a truly undefined opcode (160 to 255). + * We have no idea about its arguments. So we + * must stop parsing. Note that some data + * may be left in the packet; hopefully there + * is nothing more coming after the mode data. + */ + logit("parse_tty_modes: unknown opcode %d", + opcode); + goto set; + } + } else { + /* + * SSH2: + * Opcodes 1 to 159 are defined to have + * a uint32 argument. + * Opcodes 160 to 255 are undefined and + * cause parsing to stop. + */ + if (opcode > 0 && opcode < 160) { + n_bytes += 4; + (void) packet_get_int(); + break; + } else { + logit("parse_tty_modes: unknown opcode %d", + opcode); + goto set; + } + } + } + } + +set: + if (*n_bytes_ptr != n_bytes) { + *n_bytes_ptr = n_bytes; + logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", + *n_bytes_ptr, n_bytes); + return; /* Don't process bytes passed */ + } + if (failure == -1) + return; /* Packet parsed ok but tcgetattr() failed */ + + /* Set the new modes for the terminal. */ + //if (tcsetattr(fd, TCSANOW, &tio) == -1) + //logit("Setting tty modes failed: %.100s", strerror(errno)); #endif }