This patch from Adam Heath <doogie@debian.org>, makes print_file
[oweals/busybox.git] / telnet.c
index ac6813e29e83214c64af152ecb3a789d9a9f0dd5..207732b72562a6c09d45f7240d7428e16eb3d00e 100644 (file)
--- a/telnet.c
+++ b/telnet.c
  * 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>
  *
  */
 
-#warning This applet has moved to netkit-tiny.  After BusyBox 0.49, this
-#warning applet will be removed from BusyBox.  All maintainence efforts
-#warning should be done in the netkit-tiny source tree.
-
-
-#include "busybox.h"
 #include <termios.h>
 #include <unistd.h>
 #include <errno.h>
@@ -48,6 +44,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include "busybox.h"
 
 #if 0
 static const int DOTRACE = 1;
@@ -90,7 +87,7 @@ enum {
 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 */
@@ -113,7 +110,7 @@ struct Globalvars {
 struct Globalvars * Gptr;
 #define G (*Gptr)
 #else
-struct Globalvars G;
+static struct Globalvars G;
 #endif
 
 static inline void iacflush()
@@ -141,6 +138,10 @@ static int local_bind(int port);
 /* Some globals */
 static int one = 1;
 
+#ifdef BB_FEATURE_TELNET_TTYPE
+static char *ttype;
+#endif
+
 static void doexit(int ev)
 {
        cookmode();
@@ -326,11 +327,32 @@ static void putiac1(byte c)
 }
 #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()
 {
@@ -432,12 +454,29 @@ static inline void to_sga()
        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;
        }
 }
@@ -445,7 +484,7 @@ static void telopt(byte c)
 
 /* ******************************* */
 
-/* subnegotiation -- ignore all */
+/* subnegotiation -- ignore all (except TTYPE) */
 
 static int subneg(byte c)
 {
@@ -454,6 +493,11 @@ 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)
@@ -493,6 +537,9 @@ extern int telnet_main(int argc, char** argv)
        int maxfd;
 #endif 
 
+#ifdef BB_FEATURE_TELNET_TTYPE
+    ttype = getenv("TERM");
+#endif
 
        memset(&G, 0, sizeof G);
 
@@ -503,7 +550,7 @@ extern int telnet_main(int argc, char** argv)
 
        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);
@@ -589,7 +636,7 @@ static int getport(char * p)
 
        if ((unsigned)(port - 1 ) > 65534)
        {
-               error_msg_and_die("%s: bad port number\n", p);
+               error_msg_and_die("%s: bad port number", p);
        }
        return port;
 }
@@ -601,7 +648,7 @@ static struct in_addr getserver(char * host)
        struct hostent * he;
        if ((he = gethostbyname(host)) == NULL)
        {
-               error_msg_and_die("%s: Unknown host\n", host);
+               error_msg_and_die("%s: Unknown host", host);
        }
        memcpy(&addr, he->h_addr, sizeof addr);
 
@@ -617,7 +664,7 @@ 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);
 }