aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-03-19 14:47:09 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-03-19 14:47:09 +0000
commitf24cdf1554a4481bf7c86eb167d62dc7c67f8026 (patch)
tree62b01303513103b1525d7fd3f284203ac65fc74f
parentdfce08f281c9fbe2595413bbc36f905222a6f9b6 (diff)
downloadbusybox-w32-f24cdf1554a4481bf7c86eb167d62dc7c67f8026.tar.gz
busybox-w32-f24cdf1554a4481bf7c86eb167d62dc7c67f8026.tar.bz2
busybox-w32-f24cdf1554a4481bf7c86eb167d62dc7c67f8026.zip
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
-rw-r--r--networking/telnet.c179
1 files changed, 83 insertions, 96 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 @@
32#define TRACE(x, y) 32#define TRACE(x, y)
33#endif 33#endif
34 34
35#define DATABUFSIZE 128
36#define IACBUFSIZE 128
37
38enum { 35enum {
36 DATABUFSIZE = 128,
37 IACBUFSIZE = 128,
38
39 CHM_TRY = 0, 39 CHM_TRY = 0,
40 CHM_ON = 1, 40 CHM_ON = 1,
41 CHM_OFF = 2, 41 CHM_OFF = 2,
@@ -50,40 +50,36 @@ enum {
50 TS_SUB2 = 5, 50 TS_SUB2 = 5,
51}; 51};
52 52
53#define WriteCS(fd, str) write(fd, str, sizeof str -1)
54
55typedef unsigned char byte; 53typedef unsigned char byte;
56 54
57/* use globals to reduce size ??? */ /* test this hypothesis later */ 55
58static struct Globalvars { 56struct globals {
59 int netfd; /* console fd:s are 0 and 1 (and 2) */ 57 int netfd; /* console fd:s are 0 and 1 (and 2) */
60 /* same buffer used both for network and console read/write */ 58 short iaclen; /* could even use byte */
61 char buf[DATABUFSIZE]; /* allocating so static size is smaller */
62 byte telstate; /* telnet negotiation state from network input */ 59 byte telstate; /* telnet negotiation state from network input */
63 byte telwish; /* DO, DONT, WILL, WONT */ 60 byte telwish; /* DO, DONT, WILL, WONT */
64 byte charmode; 61 byte charmode;
65 byte telflags; 62 byte telflags;
66 byte gotsig; 63 byte gotsig;
67 byte do_termios; 64 byte do_termios;
68 /* buffer to handle telnet negotiations */ 65#if ENABLE_FEATURE_TELNET_TTYPE
66 char *ttype;
67#endif
68#if ENABLE_FEATURE_TELNET_AUTOLOGIN
69 const char *autologin;
70#endif
71#if ENABLE_FEATURE_AUTOWIDTH
72 int win_width, win_height;
73#endif
74 /* same buffer used both for network and console read/write */
75 char buf[DATABUFSIZE]; /* allocating so static size is smaller */
69 char iacbuf[IACBUFSIZE]; 76 char iacbuf[IACBUFSIZE];
70 short iaclen; /* could even use byte */
71 struct termios termios_def; 77 struct termios termios_def;
72 struct termios termios_raw; 78 struct termios termios_raw;
73} G; 79};
74
75#define xUSE_GLOBALVAR_PTR /* xUSE... -> don't use :D (makes smaller code) */
76 80
77#ifdef USE_GLOBALVAR_PTR 81#define G (*(struct globals*)bb_common_bufsiz1)
78struct Globalvars * Gptr;
79#define G (*Gptr)
80#endif
81 82
82static void iacflush(void)
83{
84 write(G.netfd, G.iacbuf, G.iaclen);
85 G.iaclen = 0;
86}
87 83
88/* Function prototypes */ 84/* Function prototypes */
89static void rawmode(void); 85static void rawmode(void);
@@ -93,20 +89,16 @@ static void will_charmode(void);
93static void telopt(byte c); 89static void telopt(byte c);
94static int subneg(byte c); 90static int subneg(byte c);
95 91
96/* Some globals */ 92static void iacflush(void)
97#ifdef CONFIG_FEATURE_TELNET_TTYPE 93{
98static char *ttype; 94 write(G.netfd, G.iacbuf, G.iaclen);
99#endif 95 G.iaclen = 0;
100 96}
101#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
102static const char *autologin;
103#endif
104 97
105#ifdef CONFIG_FEATURE_AUTOWIDTH 98#define write_str(fd, str) write(fd, str, sizeof(str) - 1)
106static int win_width, win_height;
107#endif
108 99
109static void doexit(int ev) 100static void /* buffer to handle telnet negotiations */
101doexit(int ev)
110{ 102{
111 cookmode(); 103 cookmode();
112 exit(ev); 104 exit(ev);
@@ -119,7 +111,7 @@ static void conescape(void)
119 if (G.gotsig) /* came from line mode... go raw */ 111 if (G.gotsig) /* came from line mode... go raw */
120 rawmode(); 112 rawmode();
121 113
122 WriteCS(1, "\r\nConsole escape. Commands are:\r\n\n" 114 write_str(1, "\r\nConsole escape. Commands are:\r\n\n"
123 " l go to line mode\r\n" 115 " l go to line mode\r\n"
124 " c go to character mode\r\n" 116 " c go to character mode\r\n"
125 " z suspend telnet\r\n" 117 " z suspend telnet\r\n"
@@ -128,18 +120,15 @@ static void conescape(void)
128 if (read(0, &b, 1) <= 0) 120 if (read(0, &b, 1) <= 0)
129 doexit(1); 121 doexit(1);
130 122
131 switch (b) 123 switch (b) {
132 {
133 case 'l': 124 case 'l':
134 if (!G.gotsig) 125 if (!G.gotsig) {
135 {
136 do_linemode(); 126 do_linemode();
137 goto rrturn; 127 goto rrturn;
138 } 128 }
139 break; 129 break;
140 case 'c': 130 case 'c':
141 if (G.gotsig) 131 if (G.gotsig) {
142 {
143 will_charmode(); 132 will_charmode();
144 goto rrturn; 133 goto rrturn;
145 } 134 }
@@ -153,7 +142,7 @@ static void conescape(void)
153 doexit(0); 142 doexit(0);
154 } 143 }
155 144
156 WriteCS(1, "continuing...\r\n"); 145 write_str(1, "continuing...\r\n");
157 146
158 if (G.gotsig) 147 if (G.gotsig)
159 cookmode(); 148 cookmode();
@@ -296,7 +285,7 @@ static void putiac2(byte wwdd, byte c)
296 putiac(c); 285 putiac(c);
297} 286}
298 287
299#ifdef CONFIG_FEATURE_TELNET_TTYPE 288#if ENABLE_FEATURE_TELNET_TTYPE
300static void putiac_subopt(byte c, char *str) 289static void putiac_subopt(byte c, char *str)
301{ 290{
302 int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) 291 int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 )
@@ -317,10 +306,10 @@ static void putiac_subopt(byte c, char *str)
317} 306}
318#endif 307#endif
319 308
320#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN 309#if ENABLE_FEATURE_TELNET_AUTOLOGIN
321static void putiac_subopt_autologin(void) 310static void putiac_subopt_autologin(void)
322{ 311{
323 int len = strlen(autologin) + 6; // (2 + 1 + 1 + strlen + 2) 312 int len = strlen(G.autologin) + 6; // (2 + 1 + 1 + strlen + 2)
324 const char *user = "USER"; 313 const char *user = "USER";
325 314
326 if (G.iaclen + len > IACBUFSIZE) 315 if (G.iaclen + len > IACBUFSIZE)
@@ -337,15 +326,15 @@ static void putiac_subopt_autologin(void)
337 326
338 putiac(NEW_ENV_VALUE); 327 putiac(NEW_ENV_VALUE);
339 328
340 while (*autologin) 329 while (*G.autologin)
341 putiac(*autologin++); 330 putiac(*G.autologin++);
342 331
343 putiac(IAC); 332 putiac(IAC);
344 putiac(SE); 333 putiac(SE);
345} 334}
346#endif 335#endif
347 336
348#ifdef CONFIG_FEATURE_AUTOWIDTH 337#if ENABLE_FEATURE_AUTOWIDTH
349static void putiac_naws(byte c, int x, int y) 338static void putiac_naws(byte c, int x, int y)
350{ 339{
351 if (G.iaclen + 9 > IACBUFSIZE) 340 if (G.iaclen + 9 > IACBUFSIZE)
@@ -419,24 +408,27 @@ static void do_linemode(void)
419 408
420static void to_notsup(char c) 409static void to_notsup(char c)
421{ 410{
422 if (G.telwish == WILL) putiac2(DONT, c); 411 if (G.telwish == WILL)
423 else if (G.telwish == DO) putiac2(WONT, c); 412 putiac2(DONT, c);
413 else if (G.telwish == DO)
414 putiac2(WONT, c);
424} 415}
425 416
426static void to_echo(void) 417static void to_echo(void)
427{ 418{
428 /* if server requests ECHO, don't agree */ 419 /* if server requests ECHO, don't agree */
429 if (G.telwish == DO) { putiac2(WONT, TELOPT_ECHO); return; } 420 if (G.telwish == DO) {
430 else if (G.telwish == DONT) return; 421 putiac2(WONT, TELOPT_ECHO);
422 return;
423 }
424 if (G.telwish == DONT)
425 return;
431 426
432 if (G.telflags & UF_ECHO) 427 if (G.telflags & UF_ECHO) {
433 {
434 if (G.telwish == WILL) 428 if (G.telwish == WILL)
435 return; 429 return;
436 } 430 } else if (G.telwish == WONT)
437 else 431 return;
438 if (G.telwish == WONT)
439 return;
440 432
441 if (G.charmode != CHM_OFF) 433 if (G.charmode != CHM_OFF)
442 G.telflags ^= UF_ECHO; 434 G.telflags ^= UF_ECHO;
@@ -447,21 +439,18 @@ static void to_echo(void)
447 putiac2(DONT, TELOPT_ECHO); 439 putiac2(DONT, TELOPT_ECHO);
448 440
449 setConMode(); 441 setConMode();
450 WriteCS(1, "\r\n"); /* sudden modec */ 442 write_str(1, "\r\n"); /* sudden modec */
451} 443}
452 444
453static void to_sga(void) 445static void to_sga(void)
454{ 446{
455 /* daemon always sends will/wont, client do/dont */ 447 /* daemon always sends will/wont, client do/dont */
456 448
457 if (G.telflags & UF_SGA) 449 if (G.telflags & UF_SGA) {
458 {
459 if (G.telwish == WILL) 450 if (G.telwish == WILL)
460 return; 451 return;
461 } 452 } else if (G.telwish == WONT)
462 else 453 return;
463 if (G.telwish == WONT)
464 return;
465 454
466 if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */ 455 if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */
467 putiac2(DO, TELOPT_SGA); 456 putiac2(DO, TELOPT_SGA);
@@ -469,31 +458,31 @@ static void to_sga(void)
469 putiac2(DONT, TELOPT_SGA); 458 putiac2(DONT, TELOPT_SGA);
470} 459}
471 460
472#ifdef CONFIG_FEATURE_TELNET_TTYPE 461#if ENABLE_FEATURE_TELNET_TTYPE
473static void to_ttype(void) 462static void to_ttype(void)
474{ 463{
475 /* Tell server we will (or won't) do TTYPE */ 464 /* Tell server we will (or won't) do TTYPE */
476 465
477 if(ttype) 466 if (G.ttype)
478 putiac2(WILL, TELOPT_TTYPE); 467 putiac2(WILL, TELOPT_TTYPE);
479 else 468 else
480 putiac2(WONT, TELOPT_TTYPE); 469 putiac2(WONT, TELOPT_TTYPE);
481} 470}
482#endif 471#endif
483 472
484#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN 473#if ENABLE_FEATURE_TELNET_AUTOLOGIN
485static void to_new_environ(void) 474static void to_new_environ(void)
486{ 475{
487 /* Tell server we will (or will not) do AUTOLOGIN */ 476 /* Tell server we will (or will not) do AUTOLOGIN */
488 477
489 if (autologin) 478 if (G.autologin)
490 putiac2(WILL, TELOPT_NEW_ENVIRON); 479 putiac2(WILL, TELOPT_NEW_ENVIRON);
491 else 480 else
492 putiac2(WONT, TELOPT_NEW_ENVIRON); 481 putiac2(WONT, TELOPT_NEW_ENVIRON);
493} 482}
494#endif 483#endif
495 484
496#ifdef CONFIG_FEATURE_AUTOWIDTH 485#if ENABLE_FEATURE_AUTOWIDTH
497static void to_naws(void) 486static void to_naws(void)
498{ 487{
499 /* Tell server we will do NAWS */ 488 /* Tell server we will do NAWS */
@@ -508,18 +497,18 @@ static void telopt(byte c)
508 to_echo(); break; 497 to_echo(); break;
509 case TELOPT_SGA: 498 case TELOPT_SGA:
510 to_sga(); break; 499 to_sga(); break;
511#ifdef CONFIG_FEATURE_TELNET_TTYPE 500#if ENABLE_FEATURE_TELNET_TTYPE
512 case TELOPT_TTYPE: 501 case TELOPT_TTYPE:
513 to_ttype(); break; 502 to_ttype(); break;
514#endif 503#endif
515#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN 504#if ENABLE_FEATURE_TELNET_AUTOLOGIN
516 case TELOPT_NEW_ENVIRON: 505 case TELOPT_NEW_ENVIRON:
517 to_new_environ(); break; 506 to_new_environ(); break;
518#endif 507#endif
519#ifdef CONFIG_FEATURE_AUTOWIDTH 508#if ENABLE_FEATURE_AUTOWIDTH
520 case TELOPT_NAWS: 509 case TELOPT_NAWS:
521 to_naws(); 510 to_naws();
522 putiac_naws(c, win_width, win_height); 511 putiac_naws(c, G.win_width, G.win_height);
523 break; 512 break;
524#endif 513#endif
525 default: 514 default:
@@ -535,17 +524,16 @@ static void telopt(byte c)
535 524
536static int subneg(byte c) 525static int subneg(byte c)
537{ 526{
538 switch (G.telstate) 527 switch (G.telstate) {
539 {
540 case TS_SUB1: 528 case TS_SUB1:
541 if (c == IAC) 529 if (c == IAC)
542 G.telstate = TS_SUB2; 530 G.telstate = TS_SUB2;
543#ifdef CONFIG_FEATURE_TELNET_TTYPE 531#if ENABLE_FEATURE_TELNET_TTYPE
544 else 532 else
545 if (c == TELOPT_TTYPE) 533 if (c == TELOPT_TTYPE)
546 putiac_subopt(TELOPT_TTYPE,ttype); 534 putiac_subopt(TELOPT_TTYPE, G.ttype);
547#endif 535#endif
548#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN 536#if ENABLE_FEATURE_TELNET_AUTOLOGIN
549 else 537 else
550 if (c == TELOPT_NEW_ENVIRON) 538 if (c == TELOPT_NEW_ENVIRON)
551 putiac_subopt_autologin(); 539 putiac_subopt_autologin();
@@ -578,6 +566,8 @@ static void cookmode(void)
578 if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_def); 566 if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_def);
579} 567}
580 568
569void BUG_telnet_globals_too_big(void);
570
581int telnet_main(int argc, char** argv); 571int telnet_main(int argc, char** argv);
582int telnet_main(int argc, char** argv) 572int telnet_main(int argc, char** argv)
583{ 573{
@@ -591,15 +581,17 @@ int telnet_main(int argc, char** argv)
591 int maxfd; 581 int maxfd;
592#endif 582#endif
593 583
594#ifdef CONFIG_FEATURE_AUTOWIDTH 584 if (sizeof(G) > sizeof(bb_common_bufsiz1))
595 get_terminal_width_height(0, &win_width, &win_height); 585 BUG_telnet_globals_too_big();
596#endif 586 /* memset(&G, 0, sizeof G); - already is */
597 587
598#ifdef CONFIG_FEATURE_TELNET_TTYPE 588#if ENABLE_FEATURE_AUTOWIDTH
599 ttype = getenv("TERM"); 589 get_terminal_width_height(0, &G.win_width, &G.win_height);
600#endif 590#endif
601 591
602 /* memset(&G, 0, sizeof G); - already is */ 592#if ENABLE_FEATURE_TELNET_TTYPE
593 G.ttype = getenv("TERM");
594#endif
603 595
604 if (tcgetattr(0, &G.termios_def) >= 0) { 596 if (tcgetattr(0, &G.termios_def) >= 0) {
605 G.do_termios = 1; 597 G.do_termios = 1;
@@ -610,9 +602,9 @@ int telnet_main(int argc, char** argv)
610 if (argc < 2) 602 if (argc < 2)
611 bb_show_usage(); 603 bb_show_usage();
612 604
613#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN 605#if ENABLE_FEATURE_TELNET_AUTOLOGIN
614 if (1 & getopt32(argc, argv, "al:", &autologin)) 606 if (1 & getopt32(argc, argv, "al:", &G.autologin))
615 autologin = getenv("USER"); 607 G.autologin = getenv("USER");
616 argv += optind; 608 argv += optind;
617#else 609#else
618 argv++; 610 argv++;
@@ -667,12 +659,9 @@ int telnet_main(int argc, char** argv)
667#endif 659#endif
668 { 660 {
669 len = read(0, G.buf, DATABUFSIZE); 661 len = read(0, G.buf, DATABUFSIZE);
670
671 if (len <= 0) 662 if (len <= 0)
672 doexit(0); 663 doexit(0);
673
674 TRACE(0, ("Read con: %d\n", len)); 664 TRACE(0, ("Read con: %d\n", len));
675
676 handlenetoutput(len); 665 handlenetoutput(len);
677 } 666 }
678 667
@@ -683,13 +672,11 @@ int telnet_main(int argc, char** argv)
683#endif 672#endif
684 { 673 {
685 len = read(G.netfd, G.buf, DATABUFSIZE); 674 len = read(G.netfd, G.buf, DATABUFSIZE);
686
687 if (len <= 0) { 675 if (len <= 0) {
688 WriteCS(1, "Connection closed by foreign host.\r\n"); 676 write_str(1, "Connection closed by foreign host\r\n");
689 doexit(1); 677 doexit(1);
690 } 678 }
691 TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len)); 679 TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
692
693 handlenetinput(len); 680 handlenetinput(len);
694 } 681 }
695 } 682 }