diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-19 14:47:09 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-19 14:47:09 +0000 |
commit | f24cdf1554a4481bf7c86eb167d62dc7c67f8026 (patch) | |
tree | 62b01303513103b1525d7fd3f284203ac65fc74f | |
parent | dfce08f281c9fbe2595413bbc36f905222a6f9b6 (diff) | |
download | busybox-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.c | 179 |
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 | |||
38 | enum { | 35 | enum { |
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 | |||
55 | typedef unsigned char byte; | 53 | typedef unsigned char byte; |
56 | 54 | ||
57 | /* use globals to reduce size ??? */ /* test this hypothesis later */ | 55 | |
58 | static struct Globalvars { | 56 | struct 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) |
78 | struct Globalvars * Gptr; | ||
79 | #define G (*Gptr) | ||
80 | #endif | ||
81 | 82 | ||
82 | static 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 */ |
89 | static void rawmode(void); | 85 | static void rawmode(void); |
@@ -93,20 +89,16 @@ static void will_charmode(void); | |||
93 | static void telopt(byte c); | 89 | static void telopt(byte c); |
94 | static int subneg(byte c); | 90 | static int subneg(byte c); |
95 | 91 | ||
96 | /* Some globals */ | 92 | static void iacflush(void) |
97 | #ifdef CONFIG_FEATURE_TELNET_TTYPE | 93 | { |
98 | static char *ttype; | 94 | write(G.netfd, G.iacbuf, G.iaclen); |
99 | #endif | 95 | G.iaclen = 0; |
100 | 96 | } | |
101 | #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN | ||
102 | static const char *autologin; | ||
103 | #endif | ||
104 | 97 | ||
105 | #ifdef CONFIG_FEATURE_AUTOWIDTH | 98 | #define write_str(fd, str) write(fd, str, sizeof(str) - 1) |
106 | static int win_width, win_height; | ||
107 | #endif | ||
108 | 99 | ||
109 | static void doexit(int ev) | 100 | static void /* buffer to handle telnet negotiations */ |
101 | doexit(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 |
300 | static void putiac_subopt(byte c, char *str) | 289 | static 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 |
321 | static void putiac_subopt_autologin(void) | 310 | static 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 |
349 | static void putiac_naws(byte c, int x, int y) | 338 | static 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 | ||
420 | static void to_notsup(char c) | 409 | static 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 | ||
426 | static void to_echo(void) | 417 | static 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 | ||
453 | static void to_sga(void) | 445 | static 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 |
473 | static void to_ttype(void) | 462 | static 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 |
485 | static void to_new_environ(void) | 474 | static 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 |
497 | static void to_naws(void) | 486 | static 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 | ||
536 | static int subneg(byte c) | 525 | static 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 | ||
569 | void BUG_telnet_globals_too_big(void); | ||
570 | |||
581 | int telnet_main(int argc, char** argv); | 571 | int telnet_main(int argc, char** argv); |
582 | int telnet_main(int argc, char** argv) | 572 | int 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 | } |