various telnet-client updates making it capable of real use for vim/nethack/etc. on a real telnet server

This commit is contained in:
Sean Middleditch 2009-03-15 20:41:24 -04:00
parent 5cf66661e5
commit a7896d1117
1 changed files with 87 additions and 4 deletions

View File

@ -19,6 +19,7 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <termios.h>
#include <unistd.h>
#ifdef HAVE_ZLIB
@ -27,6 +28,13 @@
#include "libtelnet.h"
static struct termios orig_tios;
static int do_echo;
static void _cleanup(void) {
tcsetattr(STDOUT_FILENO, TCSADRAIN, &orig_tios);
}
static void _send(int sock, unsigned char *buffer, unsigned int size) {
int rs;
@ -61,10 +69,67 @@ static void _event_handler(struct libtelnet_t *telnet,
break;
/* accept any options we want */
case LIBTELNET_EV_NEGOTIATE:
/* enable COMPRESS2 */
if (ev->command == LIBTELNET_WILL &&
ev->telopt == LIBTELNET_TELOPT_COMPRESS2)
libtelnet_send_negotiate(telnet, LIBTELNET_DO, ev->telopt);
switch (ev->command) {
case LIBTELNET_WILL:
switch (ev->telopt) {
/* accept request to enable compression */
case LIBTELNET_TELOPT_COMPRESS2:
libtelnet_send_negotiate(telnet, LIBTELNET_DO, ev->telopt);
break;
/* server "promises" to echo, so turn off local echo */
case LIBTELNET_TELOPT_ECHO:
do_echo = 0;
libtelnet_send_negotiate(telnet, LIBTELNET_DO, ev->telopt);
break;
/* unknown -- reject */
default:
libtelnet_send_negotiate(telnet, LIBTELNET_DONT, ev->telopt);
break;
}
break;
case LIBTELNET_WONT:
switch (ev->telopt) {
/* server wants us to do echoing, by telling us it won't */
case LIBTELNET_TELOPT_ECHO:
do_echo = 1;
libtelnet_send_negotiate(telnet, LIBTELNET_DONT, ev->telopt);
break;
}
break;
case LIBTELNET_DO:
switch (ev->telopt) {
/* accept request to enable terminal-type requests */
case LIBTELNET_TELOPT_TTYPE:
libtelnet_send_negotiate(telnet, LIBTELNET_WILL, ev->telopt);
break;
/* unknown - reject */
default:
libtelnet_send_negotiate(telnet, LIBTELNET_WONT, ev->telopt);
break;
}
break;
case LIBTELNET_DONT:
/* ignore for now */
break;
}
break;
/* respond to particular subnegotiations */
case LIBTELNET_EV_SUBNEGOTIATION:
/* respond with our terminal type */
if (ev->telopt == LIBTELNET_TELOPT_TTYPE) {
/* NOTE: we just assume the server sent a legitimate
* sub-negotiation, as there really isn't anything else
* it's allowed to send
*/
char buffer[64];
buffer[0] = 0; /* IS code for RFC 1091 */
snprintf(buffer + 1, sizeof(buffer) - 1, "%s", getenv("TERM"));
libtelnet_send_subnegotiation(telnet, LIBTELNET_TELOPT_TTYPE,
(unsigned char *)buffer, 1 + strlen(buffer + 1));
}
break;
/* error */
case LIBTELNET_EV_ERROR:
@ -85,6 +150,7 @@ int main(int argc, char **argv) {
struct libtelnet_t telnet;
struct addrinfo *ai;
struct addrinfo hints;
struct termios tios;
/* check usage */
if (argc != 3) {
@ -125,6 +191,18 @@ int main(int argc, char **argv) {
/* free address lookup info */
freeaddrinfo(ai);
/* get current terminal settings, set raw mode, make sure we
* register atexit handler to restore terminal settings
*/
tcgetattr(STDOUT_FILENO, &orig_tios);
atexit(_cleanup);
tios = orig_tios;
cfmakeraw(&tios);
tcsetattr(STDOUT_FILENO, TCSADRAIN, &tios);
/* set input echoing on by default */
do_echo = 1;
/* initialize telnet box */
libtelnet_init(&telnet, _event_handler, LIBTELNET_MODE_CLIENT, &sock);
@ -140,6 +218,11 @@ int main(int argc, char **argv) {
/* read from stdin */
if (pfd[0].revents & POLLIN) {
if ((rs = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) {
/* local echo */
if (do_echo)
write(STDOUT_FILENO, buffer, rs);
/* send over the wire */
libtelnet_send_data(&telnet, buffer, rs);
} else if (rs == 0) {
break;