version 1.2, 1999/09/30 05:03:05 |
version 1.3, 1999/11/23 22:25:56 |
|
|
#include "ssh.h" |
#include "ssh.h" |
|
|
#define TTY_OP_END 0 |
#define TTY_OP_END 0 |
#define TTY_OP_ISPEED 192 /* int follows */ |
#define TTY_OP_ISPEED 192 /* int follows */ |
#define TTY_OP_OSPEED 193 /* int follows */ |
#define TTY_OP_OSPEED 193 /* int follows */ |
|
|
/* Converts POSIX speed_t to a baud rate. The values of the constants |
/* Converts POSIX speed_t to a baud rate. The values of the constants |
for speed_t are not themselves portable. */ |
for speed_t are not themselves portable. */ |
|
|
static int speed_to_baud(speed_t speed) |
static int |
|
speed_to_baud(speed_t speed) |
{ |
{ |
switch (speed) |
switch (speed) { |
{ |
case B0: |
case B0: |
return 0; |
return 0; |
case B50: |
case B50: |
return 50; |
return 50; |
case B75: |
case B75: |
return 75; |
return 75; |
case B110: |
case B110: |
return 110; |
return 110; |
case B134: |
case B134: |
return 134; |
return 134; |
case B150: |
case B150: |
return 150; |
return 150; |
case B200: |
case B200: |
return 200; |
return 200; |
case B300: |
case B300: |
return 300; |
return 300; |
case B600: |
case B600: |
return 600; |
return 600; |
case B1200: |
case B1200: |
return 1200; |
return 1200; |
case B1800: |
case B1800: |
return 1800; |
return 1800; |
case B2400: |
case B2400: |
return 2400; |
return 2400; |
case B4800: |
case B4800: |
return 4800; |
return 4800; |
case B9600: |
case B9600: |
return 9600; |
return 9600; |
|
|
|
#ifdef B19200 |
#ifdef B19200 |
case B19200: |
case B19200: |
return 19200; |
return 19200; |
#else /* B19200 */ |
#else /* B19200 */ |
#ifdef EXTA |
#ifdef EXTA |
case EXTA: |
case EXTA: |
return 19200; |
return 19200; |
#endif /* EXTA */ |
#endif /* EXTA */ |
#endif /* B19200 */ |
#endif /* B19200 */ |
|
|
#ifdef B38400 |
#ifdef B38400 |
case B38400: |
case B38400: |
return 38400; |
return 38400; |
#else /* B38400 */ |
#else /* B38400 */ |
#ifdef EXTB |
#ifdef EXTB |
case EXTB: |
case EXTB: |
return 38400; |
return 38400; |
#endif /* EXTB */ |
#endif /* EXTB */ |
#endif /* B38400 */ |
#endif /* B38400 */ |
|
|
#ifdef B7200 |
#ifdef B7200 |
case B7200: |
case B7200: |
return 7200; |
return 7200; |
#endif /* B7200 */ |
#endif /* B7200 */ |
#ifdef B14400 |
#ifdef B14400 |
case B14400: |
case B14400: |
return 14400; |
return 14400; |
#endif /* B14400 */ |
#endif /* B14400 */ |
#ifdef B28800 |
#ifdef B28800 |
case B28800: |
case B28800: |
return 28800; |
return 28800; |
#endif /* B28800 */ |
#endif /* B28800 */ |
#ifdef B57600 |
#ifdef B57600 |
case B57600: |
case B57600: |
return 57600; |
return 57600; |
#endif /* B57600 */ |
#endif /* B57600 */ |
#ifdef B76800 |
#ifdef B76800 |
case B76800: |
case B76800: |
return 76800; |
return 76800; |
#endif /* B76800 */ |
#endif /* B76800 */ |
#ifdef B115200 |
#ifdef B115200 |
case B115200: |
case B115200: |
return 115200; |
return 115200; |
#endif /* B115200 */ |
#endif /* B115200 */ |
#ifdef B230400 |
#ifdef B230400 |
case B230400: |
case B230400: |
return 230400; |
return 230400; |
#endif /* B230400 */ |
#endif /* B230400 */ |
default: |
default: |
return 9600; |
return 9600; |
} |
} |
} |
} |
|
|
/* Converts a numeric baud rate to a POSIX speed_t. */ |
/* Converts a numeric baud rate to a POSIX speed_t. */ |
|
|
static speed_t baud_to_speed(int baud) |
static speed_t |
|
baud_to_speed(int baud) |
{ |
{ |
switch (baud) |
switch (baud) { |
{ |
case 0: |
case 0: |
return B0; |
return B0; |
case 50: |
case 50: |
return B50; |
return B50; |
case 75: |
case 75: |
return B75; |
return B75; |
case 110: |
case 110: |
return B110; |
return B110; |
case 134: |
case 134: |
return B134; |
return B134; |
case 150: |
case 150: |
return B150; |
return B150; |
case 200: |
case 200: |
return B200; |
return B200; |
case 300: |
case 300: |
return B300; |
return B300; |
case 600: |
case 600: |
return B600; |
return B600; |
case 1200: |
case 1200: |
return B1200; |
return B1200; |
case 1800: |
case 1800: |
return B1800; |
return B1800; |
case 2400: |
case 2400: |
return B2400; |
return B2400; |
case 4800: |
case 4800: |
return B4800; |
return B4800; |
case 9600: |
case 9600: |
return B9600; |
return B9600; |
|
|
|
#ifdef B19200 |
#ifdef B19200 |
case 19200: |
case 19200: |
return B19200; |
return B19200; |
#else /* B19200 */ |
#else /* B19200 */ |
#ifdef EXTA |
#ifdef EXTA |
case 19200: |
case 19200: |
return EXTA; |
return EXTA; |
#endif /* EXTA */ |
#endif /* EXTA */ |
#endif /* B19200 */ |
#endif /* B19200 */ |
|
|
#ifdef B38400 |
#ifdef B38400 |
case 38400: |
case 38400: |
return B38400; |
return B38400; |
#else /* B38400 */ |
#else /* B38400 */ |
#ifdef EXTB |
#ifdef EXTB |
case 38400: |
case 38400: |
return EXTB; |
return EXTB; |
#endif /* EXTB */ |
#endif /* EXTB */ |
#endif /* B38400 */ |
#endif /* B38400 */ |
|
|
#ifdef B7200 |
#ifdef B7200 |
case 7200: |
case 7200: |
return B7200; |
return B7200; |
#endif /* B7200 */ |
#endif /* B7200 */ |
#ifdef B14400 |
#ifdef B14400 |
case 14400: |
case 14400: |
return B14400; |
return B14400; |
#endif /* B14400 */ |
#endif /* B14400 */ |
#ifdef B28800 |
#ifdef B28800 |
case 28800: |
case 28800: |
return B28800; |
return B28800; |
#endif /* B28800 */ |
#endif /* B28800 */ |
#ifdef B57600 |
#ifdef B57600 |
case 57600: |
case 57600: |
return B57600; |
return B57600; |
#endif /* B57600 */ |
#endif /* B57600 */ |
#ifdef B76800 |
#ifdef B76800 |
case 76800: |
case 76800: |
return B76800; |
return B76800; |
#endif /* B76800 */ |
#endif /* B76800 */ |
#ifdef B115200 |
#ifdef B115200 |
case 115200: |
case 115200: |
return B115200; |
return B115200; |
#endif /* B115200 */ |
#endif /* B115200 */ |
#ifdef B230400 |
#ifdef B230400 |
case 230400: |
case 230400: |
return B230400; |
return B230400; |
#endif /* B230400 */ |
#endif /* B230400 */ |
default: |
default: |
return B9600; |
return B9600; |
} |
} |
} |
} |
|
|
/* Encodes terminal modes for the terminal referenced by fd in a portable |
/* Encodes terminal modes for the terminal referenced by fd in a portable |
manner, and appends the modes to a packet being constructed. */ |
manner, and appends the modes to a packet being constructed. */ |
|
|
void tty_make_modes(int fd) |
void |
|
tty_make_modes(int fd) |
{ |
{ |
struct termios tio; |
struct termios tio; |
int baud; |
int baud; |
|
|
/* Get the modes. */ |
/* Get the modes. */ |
if (tcgetattr(fd, &tio) < 0) |
if (tcgetattr(fd, &tio) < 0) { |
{ |
packet_put_char(TTY_OP_END); |
packet_put_char(TTY_OP_END); |
log("tcgetattr: %.100s", strerror(errno)); |
log("tcgetattr: %.100s", strerror(errno)); |
return; |
return; |
} |
} |
/* Store input and output baud rates. */ |
|
baud = speed_to_baud(cfgetospeed(&tio)); |
|
packet_put_char(TTY_OP_OSPEED); |
|
packet_put_int(baud); |
|
baud = speed_to_baud(cfgetispeed(&tio)); |
|
packet_put_char(TTY_OP_ISPEED); |
|
packet_put_int(baud); |
|
|
/* Store input and output baud rates. */ |
/* Store values of mode flags. */ |
baud = speed_to_baud(cfgetospeed(&tio)); |
|
packet_put_char(TTY_OP_OSPEED); |
|
packet_put_int(baud); |
|
baud = speed_to_baud(cfgetispeed(&tio)); |
|
packet_put_char(TTY_OP_ISPEED); |
|
packet_put_int(baud); |
|
|
|
/* Store values of mode flags. */ |
|
#define TTYCHAR(NAME, OP) \ |
#define TTYCHAR(NAME, OP) \ |
packet_put_char(OP); packet_put_char(tio.c_cc[NAME]); |
packet_put_char(OP); packet_put_char(tio.c_cc[NAME]); |
#define TTYMODE(NAME, FIELD, OP) \ |
#define TTYMODE(NAME, FIELD, OP) \ |
|
|
#undef SGTTYMODE |
#undef SGTTYMODE |
#undef SGTTYMODEN |
#undef SGTTYMODEN |
|
|
/* Mark end of mode data. */ |
/* Mark end of mode data. */ |
packet_put_char(TTY_OP_END); |
packet_put_char(TTY_OP_END); |
} |
} |
|
|
/* Decodes terminal modes for the terminal referenced by fd in a portable |
/* Decodes terminal modes for the terminal referenced by fd in a portable |
manner from a packet being read. */ |
manner from a packet being read. */ |
|
|
void tty_parse_modes(int fd, int *n_bytes_ptr) |
void |
|
tty_parse_modes(int fd, int *n_bytes_ptr) |
{ |
{ |
struct termios tio; |
struct termios tio; |
int opcode, baud; |
int opcode, baud; |
int n_bytes = 0; |
int n_bytes = 0; |
int failure = 0; |
int failure = 0; |
|
|
/* Get old attributes for the terminal. We will modify these flags. |
/* Get old attributes for the terminal. We will modify these |
I am hoping that if there are any machine-specific modes, they will |
flags. I am hoping that if there are any machine-specific |
initially have reasonable values. */ |
modes, they will initially have reasonable values. */ |
if (tcgetattr(fd, &tio) < 0) |
if (tcgetattr(fd, &tio) < 0) |
failure = -1; |
failure = -1; |
|
|
for (;;) |
for (;;) { |
{ |
n_bytes += 1; |
n_bytes += 1; |
opcode = packet_get_char(); |
opcode = packet_get_char(); |
switch (opcode) { |
switch (opcode) |
case TTY_OP_END: |
{ |
goto set; |
case TTY_OP_END: |
|
goto set; |
|
|
|
case TTY_OP_ISPEED: |
case TTY_OP_ISPEED: |
n_bytes += 4; |
n_bytes += 4; |
baud = packet_get_int(); |
baud = packet_get_int(); |
if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0) |
if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0) |
error("cfsetispeed failed for %d", baud); |
error("cfsetispeed failed for %d", baud); |
break; |
break; |
|
|
case TTY_OP_OSPEED: |
case TTY_OP_OSPEED: |
n_bytes += 4; |
n_bytes += 4; |
baud = packet_get_int(); |
baud = packet_get_int(); |
if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0) |
if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0) |
error("cfsetospeed failed for %d", baud); |
error("cfsetospeed failed for %d", baud); |
break; |
break; |
|
|
#define TTYCHAR(NAME, OP) \ |
#define TTYCHAR(NAME, OP) \ |
case OP: \ |
case OP: \ |
|
|
#undef SGTTYMODE |
#undef SGTTYMODE |
#undef SGTTYMODEN |
#undef SGTTYMODEN |
|
|
default: |
default: |
debug("Ignoring unsupported tty mode opcode %d (0x%x)", |
debug("Ignoring unsupported tty mode opcode %d (0x%x)", |
opcode, opcode); |
opcode, opcode); |
/* Opcodes 0 to 127 are defined to have a one-byte argument. */ |
/* Opcodes 0 to 127 are defined to have a one-byte argument. */ |
if (opcode >= 0 && opcode < 128) |
if (opcode >= 0 && opcode < 128) { |
{ |
n_bytes += 1; |
n_bytes += 1; |
(void) packet_get_char(); |
(void)packet_get_char(); |
break; |
break; |
} else { |
} |
/* Opcodes 128 to 159 are defined to have an integer argument. */ |
else |
if (opcode >= 128 && opcode < 160) { |
{ |
n_bytes += 4; |
/* Opcodes 128 to 159 are defined to have an integer argument. */ |
(void) packet_get_int(); |
if (opcode >= 128 && opcode < 160) |
break; |
{ |
} |
n_bytes += 4; |
} |
(void)packet_get_int(); |
/* It is a truly undefined opcode (160 to 255). |
break; |
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. */ |
|
log("parse_tty_modes: unknown opcode %d", opcode); |
|
packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY); |
|
goto set; |
} |
} |
} |
|
/* 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. */ |
|
log("parse_tty_modes: unknown opcode %d", opcode); |
|
packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY); |
|
goto set; |
|
} |
} |
} |
|
|
|
set: |
set: |
if (*n_bytes_ptr != n_bytes) |
if (*n_bytes_ptr != n_bytes) { |
{ |
*n_bytes_ptr = n_bytes; |
*n_bytes_ptr = n_bytes; |
return; /* Don't process bytes passed */ |
return; /* Don't process bytes passed */ |
} |
} |
if (failure == -1) |
|
return; /* Packet parsed ok but tty stuff failed */ |
|
|
if (failure == -1) |
/* Set the new modes for the terminal. */ |
return; /* Packet parsed ok but tty stuff failed */ |
if (tcsetattr(fd, TCSANOW, &tio) < 0) |
|
log("Setting tty modes failed: %.100s", strerror(errno)); |
/* Set the new modes for the terminal. */ |
return; |
if (tcsetattr(fd, TCSANOW, &tio) < 0) |
|
log("Setting tty modes failed: %.100s", strerror(errno)); |
|
return; |
|
} |
} |