* initial revision
* Modified 2000/06/13 for inclusion into BusyBox by Erik Andersen
* <andersen@lineo.com>
+ * Modified 2001/05/07 to add ability to pass TTYPE to remote host by Jim McQuillan
+ * <jam@ltsp.org>
*
*/
-
-#include "internal.h"
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
+#include "busybox.h"
#if 0
-#define DOTRACE 1
+static const int DOTRACE = 1;
#endif
#ifdef DOTRACE
#include <sys/time.h>
#endif
-#define DATABUFSIZE 128
-#define IACBUFSIZE 128
+static const int DATABUFSIZE = 128;
+static const int IACBUFSIZE = 128;
-#define CHM_TRY 0
-#define CHM_ON 1
-#define CHM_OFF 2
+static const int CHM_TRY = 0;
+static const int CHM_ON = 1;
+static const int CHM_OFF = 2;
-#define UF_ECHO 0x01
-#define UF_SGA 0x02
+static const int UF_ECHO = 0x01;
+static const int UF_SGA = 0x02;
-#define TS_0 1
-#define TS_IAC 2
-#define TS_OPT 3
-#define TS_SUB1 4
-#define TS_SUB2 5
+enum {
+ TS_0 = 1,
+ TS_IAC = 2,
+ TS_OPT = 3,
+ TS_SUB1 = 4,
+ TS_SUB2 = 5,
+};
#define WriteCS(fd, str) write(fd, str, sizeof str -1)
typedef unsigned char byte;
/* use globals to reduce size ??? */ /* test this hypothesis later */
-struct Globalvars {
+static struct Globalvars {
int netfd; /* console fd:s are 0 and 1 (and 2) */
/* same buffer used both for network and console read/write */
char * buf; /* allocating so static size is smaller */
struct Globalvars * Gptr;
#define G (*Gptr)
#else
-struct Globalvars G;
+static struct Globalvars G;
#endif
static inline void iacflush()
/* Some globals */
static int one = 1;
+#ifdef BB_FEATURE_TELNET_TTYPE
+static char *ttype;
+#endif
+
static void doexit(int ev)
{
cookmode();
}
#endif
+#ifdef BB_FEATURE_TELNET_TTYPE
+static void putiac_subopt(byte c, char *str)
+{
+ int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 )
+
+ if (G.iaclen + len > IACBUFSIZE)
+ iacflush();
+
+ putiac(IAC);
+ putiac(SB);
+ putiac(c);
+ putiac(0);
+
+ while(*str)
+ putiac(*str++);
+
+ putiac(IAC);
+ putiac(SE);
+}
+#endif
+
/* void putiacstring (subneg strings) */
/* ******************************* */
-char const escapecharis[] = "\r\nEscape character is ";
+static char const escapecharis[] = "\r\nEscape character is ";
static void setConMode()
{
{
if (G.charmode == CHM_TRY) {
G.charmode = CHM_ON;
- fprintf(stdout, "\r\nEntering character mode%s'^]'.\r\n", escapecharis);
+ printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis);
rawmode();
}
}
{
if (G.charmode != CHM_OFF) {
G.charmode = CHM_OFF;
- fprintf(stdout, "\r\nEntering line mode%s'^C'.\r\n", escapecharis);
+ printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis);
cookmode();
}
}
return;
}
+#ifdef BB_FEATURE_TELNET_TTYPE
+static inline void to_ttype()
+{
+ /* Tell server we will (or won't) do TTYPE */
+
+ if(ttype)
+ putiac2(WILL, TELOPT_TTYPE);
+ else
+ putiac2(WONT, TELOPT_TTYPE);
+
+ return;
+}
+#endif
+
static void telopt(byte c)
{
switch (c)
{
case TELOPT_ECHO: to_echo(c); break;
case TELOPT_SGA: to_sga(c); break;
+#ifdef BB_FEATURE_TELNET_TTYPE
+ case TELOPT_TTYPE: to_ttype(c); break;
+#endif
default: to_notsup(c); break;
}
}
/* ******************************* */
-/* subnegotiation -- ignore all */
+/* subnegotiation -- ignore all (except TTYPE) */
static int subneg(byte c)
{
case TS_SUB1:
if (c == IAC)
G.telstate = TS_SUB2;
+#ifdef BB_FEATURE_TELNET_TTYPE
+ else
+ if (c == TELOPT_TTYPE)
+ putiac_subopt(TELOPT_TTYPE,ttype);
+#endif
break;
case TS_SUB2:
if (c == SE)
int maxfd;
#endif
+#ifdef BB_FEATURE_TELNET_TTYPE
+ ttype = getenv("TERM");
+#endif
memset(&G, 0, sizeof G);
cfmakeraw(&G.termios_raw);
- if (argc < 2) usage(telnet_usage);
+ if (argc < 2) show_usage();
port = (argc > 2)? getport(argv[2]): 23;
G.buf = xmalloc(DATABUFSIZE);
if ((unsigned)(port - 1 ) > 65534)
{
- fatalError("%s: bad port number\n", p);
+ error_msg_and_die("%s: bad port number", p);
}
return port;
}
static struct in_addr getserver(char * host)
{
struct in_addr addr;
-
+
struct hostent * he;
- if ((he = gethostbyname(host)) == NULL)
- {
- fatalError("%s: Unknown host\n", host);
- }
+ he = xgethostbyname(host);
memcpy(&addr, he->h_addr, sizeof addr);
TRACE(1, ("addr: %s\n", inet_ntoa(addr)));
-
+
return addr;
-}
+}
static int create_socket()
{
static void setup_sockaddr_in(struct sockaddr_in * addr, int port)
{
- memset(addr, 0, sizeof addr);
+ memset(addr, 0, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_port = htons(port);
}
if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0)
{
- fatalError("Unable to connect to remote host: %s\n", strerror(errno));
+ perror_msg_and_die("Unable to connect to remote host");
}
return s;
}