From f24cdf1554a4481bf7c86eb167d62dc7c67f8026 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 19 Mar 2007 14:47:09 +0000 Subject: [PATCH] telnet: someone tried to do data optimization before me. Complete it. text data bss dec hex filename 2558 0 404 2962 b92 busybox.t2/networking/telnet.o 2542 0 0 2542 9ee busybox.t3/networking/telnet.o --- networking/telnet.c | 183 ++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 98 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index 134157273..82dbb588d 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -32,10 +32,10 @@ #define TRACE(x, y) #endif -#define DATABUFSIZE 128 -#define IACBUFSIZE 128 - enum { + DATABUFSIZE = 128, + IACBUFSIZE = 128, + CHM_TRY = 0, CHM_ON = 1, CHM_OFF = 2, @@ -50,40 +50,36 @@ enum { 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 */ -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[DATABUFSIZE]; /* allocating so static size is smaller */ + +struct globals { + int netfd; /* console fd:s are 0 and 1 (and 2) */ + short iaclen; /* could even use byte */ byte telstate; /* telnet negotiation state from network input */ byte telwish; /* DO, DONT, WILL, WONT */ byte charmode; byte telflags; byte gotsig; byte do_termios; - /* buffer to handle telnet negotiations */ +#if ENABLE_FEATURE_TELNET_TTYPE + char *ttype; +#endif +#if ENABLE_FEATURE_TELNET_AUTOLOGIN + const char *autologin; +#endif +#if ENABLE_FEATURE_AUTOWIDTH + int win_width, win_height; +#endif + /* same buffer used both for network and console read/write */ + char buf[DATABUFSIZE]; /* allocating so static size is smaller */ char iacbuf[IACBUFSIZE]; - short iaclen; /* could even use byte */ struct termios termios_def; struct termios termios_raw; -} G; +}; -#define xUSE_GLOBALVAR_PTR /* xUSE... -> don't use :D (makes smaller code) */ +#define G (*(struct globals*)bb_common_bufsiz1) -#ifdef USE_GLOBALVAR_PTR -struct Globalvars * Gptr; -#define G (*Gptr) -#endif - -static void iacflush(void) -{ - write(G.netfd, G.iacbuf, G.iaclen); - G.iaclen = 0; -} /* Function prototypes */ static void rawmode(void); @@ -93,20 +89,16 @@ static void will_charmode(void); static void telopt(byte c); static int subneg(byte c); -/* Some globals */ -#ifdef CONFIG_FEATURE_TELNET_TTYPE -static char *ttype; -#endif +static void iacflush(void) +{ + write(G.netfd, G.iacbuf, G.iaclen); + G.iaclen = 0; +} -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN -static const char *autologin; -#endif +#define write_str(fd, str) write(fd, str, sizeof(str) - 1) -#ifdef CONFIG_FEATURE_AUTOWIDTH -static int win_width, win_height; -#endif - -static void doexit(int ev) +static void /* buffer to handle telnet negotiations */ +doexit(int ev) { cookmode(); exit(ev); @@ -119,7 +111,7 @@ static void conescape(void) if (G.gotsig) /* came from line mode... go raw */ rawmode(); - WriteCS(1, "\r\nConsole escape. Commands are:\r\n\n" + write_str(1, "\r\nConsole escape. Commands are:\r\n\n" " l go to line mode\r\n" " c go to character mode\r\n" " z suspend telnet\r\n" @@ -128,18 +120,15 @@ static void conescape(void) if (read(0, &b, 1) <= 0) doexit(1); - switch (b) - { + switch (b) { case 'l': - if (!G.gotsig) - { + if (!G.gotsig) { do_linemode(); goto rrturn; } break; case 'c': - if (G.gotsig) - { + if (G.gotsig) { will_charmode(); goto rrturn; } @@ -153,7 +142,7 @@ static void conescape(void) doexit(0); } - WriteCS(1, "continuing...\r\n"); + write_str(1, "continuing...\r\n"); if (G.gotsig) cookmode(); @@ -296,7 +285,7 @@ static void putiac2(byte wwdd, byte c) putiac(c); } -#ifdef CONFIG_FEATURE_TELNET_TTYPE +#if ENABLE_FEATURE_TELNET_TTYPE static void putiac_subopt(byte c, char *str) { int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) @@ -317,10 +306,10 @@ static void putiac_subopt(byte c, char *str) } #endif -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN +#if ENABLE_FEATURE_TELNET_AUTOLOGIN static void putiac_subopt_autologin(void) { - int len = strlen(autologin) + 6; // (2 + 1 + 1 + strlen + 2) + int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2) const char *user = "USER"; if (G.iaclen + len > IACBUFSIZE) @@ -337,15 +326,15 @@ static void putiac_subopt_autologin(void) putiac(NEW_ENV_VALUE); - while (*autologin) - putiac(*autologin++); + while (*G.autologin) + putiac(*G.autologin++); putiac(IAC); putiac(SE); } #endif -#ifdef CONFIG_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_AUTOWIDTH static void putiac_naws(byte c, int x, int y) { if (G.iaclen + 9 > IACBUFSIZE) @@ -419,24 +408,27 @@ static void do_linemode(void) static void to_notsup(char c) { - if (G.telwish == WILL) putiac2(DONT, c); - else if (G.telwish == DO) putiac2(WONT, c); + if (G.telwish == WILL) + putiac2(DONT, c); + else if (G.telwish == DO) + putiac2(WONT, c); } static void to_echo(void) { /* if server requests ECHO, don't agree */ - if (G.telwish == DO) { putiac2(WONT, TELOPT_ECHO); return; } - else if (G.telwish == DONT) return; + if (G.telwish == DO) { + putiac2(WONT, TELOPT_ECHO); + return; + } + if (G.telwish == DONT) + return; - if (G.telflags & UF_ECHO) - { + if (G.telflags & UF_ECHO) { if (G.telwish == WILL) return; - } - else - if (G.telwish == WONT) - return; + } else if (G.telwish == WONT) + return; if (G.charmode != CHM_OFF) G.telflags ^= UF_ECHO; @@ -447,21 +439,18 @@ static void to_echo(void) putiac2(DONT, TELOPT_ECHO); setConMode(); - WriteCS(1, "\r\n"); /* sudden modec */ + write_str(1, "\r\n"); /* sudden modec */ } static void to_sga(void) { /* daemon always sends will/wont, client do/dont */ - if (G.telflags & UF_SGA) - { + if (G.telflags & UF_SGA) { if (G.telwish == WILL) return; - } - else - if (G.telwish == WONT) - return; + } else if (G.telwish == WONT) + return; if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */ putiac2(DO, TELOPT_SGA); @@ -469,31 +458,31 @@ static void to_sga(void) putiac2(DONT, TELOPT_SGA); } -#ifdef CONFIG_FEATURE_TELNET_TTYPE +#if ENABLE_FEATURE_TELNET_TTYPE static void to_ttype(void) { /* Tell server we will (or won't) do TTYPE */ - if(ttype) + if (G.ttype) putiac2(WILL, TELOPT_TTYPE); else putiac2(WONT, TELOPT_TTYPE); } #endif -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN +#if ENABLE_FEATURE_TELNET_AUTOLOGIN static void to_new_environ(void) { /* Tell server we will (or will not) do AUTOLOGIN */ - if (autologin) + if (G.autologin) putiac2(WILL, TELOPT_NEW_ENVIRON); else putiac2(WONT, TELOPT_NEW_ENVIRON); } #endif -#ifdef CONFIG_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_AUTOWIDTH static void to_naws(void) { /* Tell server we will do NAWS */ @@ -508,18 +497,18 @@ static void telopt(byte c) to_echo(); break; case TELOPT_SGA: to_sga(); break; -#ifdef CONFIG_FEATURE_TELNET_TTYPE +#if ENABLE_FEATURE_TELNET_TTYPE case TELOPT_TTYPE: to_ttype(); break; #endif -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN +#if ENABLE_FEATURE_TELNET_AUTOLOGIN case TELOPT_NEW_ENVIRON: to_new_environ(); break; #endif -#ifdef CONFIG_FEATURE_AUTOWIDTH +#if ENABLE_FEATURE_AUTOWIDTH case TELOPT_NAWS: to_naws(); - putiac_naws(c, win_width, win_height); + putiac_naws(c, G.win_width, G.win_height); break; #endif default: @@ -535,17 +524,16 @@ static void telopt(byte c) static int subneg(byte c) { - switch (G.telstate) - { + switch (G.telstate) { case TS_SUB1: if (c == IAC) G.telstate = TS_SUB2; -#ifdef CONFIG_FEATURE_TELNET_TTYPE +#if ENABLE_FEATURE_TELNET_TTYPE else if (c == TELOPT_TTYPE) - putiac_subopt(TELOPT_TTYPE,ttype); + putiac_subopt(TELOPT_TTYPE, G.ttype); #endif -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN +#if ENABLE_FEATURE_TELNET_AUTOLOGIN else if (c == TELOPT_NEW_ENVIRON) putiac_subopt_autologin(); @@ -578,6 +566,8 @@ static void cookmode(void) if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_def); } +void BUG_telnet_globals_too_big(void); + int telnet_main(int argc, char** argv); int telnet_main(int argc, char** argv) { @@ -591,16 +581,18 @@ int telnet_main(int argc, char** argv) int maxfd; #endif -#ifdef CONFIG_FEATURE_AUTOWIDTH - get_terminal_width_height(0, &win_width, &win_height); -#endif - -#ifdef CONFIG_FEATURE_TELNET_TTYPE - ttype = getenv("TERM"); -#endif - + if (sizeof(G) > sizeof(bb_common_bufsiz1)) + BUG_telnet_globals_too_big(); /* memset(&G, 0, sizeof G); - already is */ +#if ENABLE_FEATURE_AUTOWIDTH + get_terminal_width_height(0, &G.win_width, &G.win_height); +#endif + +#if ENABLE_FEATURE_TELNET_TTYPE + G.ttype = getenv("TERM"); +#endif + if (tcgetattr(0, &G.termios_def) >= 0) { G.do_termios = 1; G.termios_raw = G.termios_def; @@ -610,9 +602,9 @@ int telnet_main(int argc, char** argv) if (argc < 2) bb_show_usage(); -#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN - if (1 & getopt32(argc, argv, "al:", &autologin)) - autologin = getenv("USER"); +#if ENABLE_FEATURE_TELNET_AUTOLOGIN + if (1 & getopt32(argc, argv, "al:", &G.autologin)) + G.autologin = getenv("USER"); argv += optind; #else argv++; @@ -667,12 +659,9 @@ int telnet_main(int argc, char** argv) #endif { len = read(0, G.buf, DATABUFSIZE); - if (len <= 0) doexit(0); - TRACE(0, ("Read con: %d\n", len)); - handlenetoutput(len); } @@ -683,13 +672,11 @@ int telnet_main(int argc, char** argv) #endif { len = read(G.netfd, G.buf, DATABUFSIZE); - if (len <= 0) { - WriteCS(1, "Connection closed by foreign host.\r\n"); + write_str(1, "Connection closed by foreign host\r\n"); doexit(1); } TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len)); - handlenetinput(len); } }