Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (17 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/networking/telnet.c

    r821 r1765  
    2323
    2424#include <termios.h>
    25 #include <unistd.h>
    26 #include <errno.h>
    27 #include <stdlib.h>
    28 #include <stdarg.h>
    29 #include <string.h>
    30 #include <signal.h>
    3125#include <arpa/telnet.h>
    32 #include <sys/types.h>
    33 #include <sys/socket.h>
    3426#include <netinet/in.h>
    35 #include "busybox.h"
    36 
    37 #if 0
    38 enum { DOTRACE = 1 };
    39 #endif
     27#include "libbb.h"
    4028
    4129#ifdef DOTRACE
    42 #include <arpa/inet.h> /* for inet_ntoa()... */
    4330#define TRACE(x, y) do { if (x) printf y; } while (0)
    4431#else
     
    4633#endif
    4734
    48 #define DATABUFSIZE  128
    49 #define IACBUFSIZE   128
    50 
    5135enum {
     36    DATABUFSIZE = 128,
     37    IACBUFSIZE  = 128,
     38
    5239    CHM_TRY = 0,
    5340    CHM_ON = 1,
     
    6451};
    6552
    66 #define WriteCS(fd, str) write(fd, str, sizeof str -1)
    67 
    6853typedef unsigned char byte;
    6954
    70 /* use globals to reduce size ??? */ /* test this hypothesis later */
    71 static struct Globalvars {
    72     int     netfd; /* console fd:s are 0 and 1 (and 2) */
    73     /* same buffer used both for network and console read/write */
    74     char    buf[DATABUFSIZE]; /* allocating so static size is smaller */
     55struct globals {
     56    int netfd; /* console fd:s are 0 and 1 (and 2) */
     57    short   iaclen; /* could even use byte */
    7558    byte    telstate; /* telnet negotiation state from network input */
    7659    byte    telwish;  /* DO, DONT, WILL, WONT */
     
    7962    byte    gotsig;
    8063    byte    do_termios;
     64#if ENABLE_FEATURE_TELNET_TTYPE
     65    char    *ttype;
     66#endif
     67#if ENABLE_FEATURE_TELNET_AUTOLOGIN
     68    const char *autologin;
     69#endif
     70#if ENABLE_FEATURE_AUTOWIDTH
     71    int win_width, win_height;
     72#endif
     73    /* same buffer used both for network and console read/write */
     74    char    buf[DATABUFSIZE];
    8175    /* buffer to handle telnet negotiations */
    8276    char    iacbuf[IACBUFSIZE];
    83     short   iaclen; /* could even use byte */
    8477    struct termios termios_def;
    8578    struct termios termios_raw;
    86 } G;
    87 
    88 #define xUSE_GLOBALVAR_PTR /* xUSE... -> don't use :D (makes smaller code) */
    89 
    90 #ifdef USE_GLOBALVAR_PTR
    91 struct Globalvars * Gptr;
    92 #define G (*Gptr)
    93 #endif
    94 
    95 static inline void iacflush(void)
    96 {
    97     write(G.netfd, G.iacbuf, G.iaclen);
    98     G.iaclen = 0;
    99 }
     79};
     80#define G (*(struct globals*)&bb_common_bufsiz1)
     81void BUG_telnet_globals_too_big(void);
     82#define INIT_G() do { \
     83    if (sizeof(G) > COMMON_BUFSIZE) \
     84        BUG_telnet_globals_too_big(); \
     85    /* memset(&G, 0, sizeof G); - already is */ \
     86} while (0)
    10087
    10188/* Function prototypes */
     
    10794static int subneg(byte c);
    10895
    109 /* Some globals */
    110 static int one = 1;
    111 
    112 #ifdef CONFIG_FEATURE_TELNET_TTYPE
    113 static char *ttype;
    114 #endif
    115 
    116 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
    117 static const char *autologin;
    118 #endif
    119 
    120 #ifdef CONFIG_FEATURE_AUTOWIDTH
    121 static int win_width, win_height;
    122 #endif
     96static void iacflush(void)
     97{
     98    write(G.netfd, G.iacbuf, G.iaclen);
     99    G.iaclen = 0;
     100}
     101
     102#define write_str(fd, str) write(fd, str, sizeof(str) - 1)
    123103
    124104static void doexit(int ev)
     
    135115        rawmode();
    136116
    137     WriteCS(1, "\r\nConsole escape. Commands are:\r\n\n"
     117    write_str(1, "\r\nConsole escape. Commands are:\r\n\n"
    138118            " l go to line mode\r\n"
    139119            " c go to character mode\r\n"
     
    144124        doexit(1);
    145125
    146     switch (b)
    147     {
     126    switch (b) {
    148127    case 'l':
    149         if (!G.gotsig)
    150         {
     128        if (!G.gotsig) {
    151129            do_linemode();
    152130            goto rrturn;
     
    154132        break;
    155133    case 'c':
    156         if (G.gotsig)
    157         {
     134        if (G.gotsig) {
    158135            will_charmode();
    159136            goto rrturn;
     
    169146    }
    170147
    171     WriteCS(1, "continuing...\r\n");
     148    write_str(1, "continuing...\r\n");
    172149
    173150    if (G.gotsig)
     
    178155
    179156}
     157
    180158static void handlenetoutput(int len)
    181159{
     
    190168     *  first - I cannot use programs like sz/rz
    191169     *  second - the 0x0D is sent as one character and if the next
    192      *          char is 0x0A then it's eaten by a server side.
     170     *      char is 0x0A then it's eaten by a server side.
    193171     *  third - whay doy you have to make 'many write()s'?
    194      *          I don't understand.
     172     *      I don't understand.
    195173     *  So I implemented it. It's realy useful for me. I hope that
    196174     *  others people will find it interesting to.
     
    210188        outbuf[j++] = *p;
    211189        if (*p == 0xff)
    212             outbuf[j++] = 0xff;
     190            outbuf[j++] = 0xff;
    213191        else if (*p == 0x0d)
    214             outbuf[j++] = 0x00;
    215     }
    216     if (j > 0 )
    217         write(G.netfd, outbuf, j);
    218 }
    219 
     192            outbuf[j++] = 0x00;
     193    }
     194    if (j > 0)
     195        write(G.netfd, outbuf, j);
     196}
    220197
    221198static void handlenetinput(int len)
     
    293270}
    294271
    295 
    296 /* ******************************* */
    297 
    298 static inline void putiac(int c)
     272static void putiac(int c)
    299273{
    300274    G.iacbuf[G.iaclen++] = c;
    301275}
    302 
    303276
    304277static void putiac2(byte wwdd, byte c)
     
    312285}
    313286
    314 #if 0
    315 static void putiac1(byte c)
    316 {
    317     if (G.iaclen + 2 > IACBUFSIZE)
    318         iacflush();
    319 
    320     putiac(IAC);
    321     putiac(c);
    322 }
    323 #endif
    324 
    325 #ifdef CONFIG_FEATURE_TELNET_TTYPE
     287#if ENABLE_FEATURE_TELNET_TTYPE
    326288static void putiac_subopt(byte c, char *str)
    327289{
     
    336298    putiac(0);
    337299
    338     while(*str)
     300    while (*str)
    339301        putiac(*str++);
    340302
     
    344306#endif
    345307
    346 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
     308#if ENABLE_FEATURE_TELNET_AUTOLOGIN
    347309static void putiac_subopt_autologin(void)
    348310{
    349     int len = strlen(autologin) + 6;    // (2 + 1 + 1 + strlen + 2)
    350     char *user = "USER";
     311    int len = strlen(G.autologin) + 6;  // (2 + 1 + 1 + strlen + 2)
     312    const char *user = "USER";
    351313
    352314    if (G.iaclen + len > IACBUFSIZE)
     
    359321    putiac(NEW_ENV_VAR);
    360322
    361     while(*user)
     323    while (*user)
    362324        putiac(*user++);
    363325
    364326    putiac(NEW_ENV_VALUE);
    365327
    366     while(*autologin)
    367         putiac(*autologin++);
     328    while (*G.autologin)
     329        putiac(*G.autologin++);
    368330
    369331    putiac(IAC);
     
    372334#endif
    373335
    374 #ifdef CONFIG_FEATURE_AUTOWIDTH
     336#if ENABLE_FEATURE_AUTOWIDTH
    375337static void putiac_naws(byte c, int x, int y)
    376338{
     
    392354#endif
    393355
    394 /* void putiacstring (subneg strings) */
    395 
    396 /* ******************************* */
    397 
    398 static char const escapecharis[] = "\r\nEscape character is ";
     356static char const escapecharis[] ALIGN1 = "\r\nEscape character is ";
    399357
    400358static void setConMode(void)
    401359{
    402     if (G.telflags & UF_ECHO)
    403     {
     360    if (G.telflags & UF_ECHO) {
    404361        if (G.charmode == CHM_TRY) {
    405362            G.charmode = CHM_ON;
     
    407364            rawmode();
    408365        }
    409     }
    410     else
    411     {
     366    } else {
    412367        if (G.charmode != CHM_OFF) {
    413368            G.charmode = CHM_OFF;
     
    418373}
    419374
    420 /* ******************************* */
    421 
    422375static void will_charmode(void)
    423376{
     
    442395}
    443396
    444 /* ******************************* */
    445 
    446 static inline void to_notsup(char c)
    447 {
    448     if      (G.telwish == WILL) putiac2(DONT, c);
    449     else if (G.telwish == DO)   putiac2(WONT, c);
    450 }
    451 
    452 static inline void to_echo(void)
     397static void to_notsup(char c)
     398{
     399    if (G.telwish == WILL)
     400        putiac2(DONT, c);
     401    else if (G.telwish == DO)
     402        putiac2(WONT, c);
     403}
     404
     405static void to_echo(void)
    453406{
    454407    /* if server requests ECHO, don't agree */
    455     if      (G.telwish == DO) { putiac2(WONT, TELOPT_ECHO); return; }
    456     else if (G.telwish == DONT) return;
    457 
    458     if (G.telflags & UF_ECHO)
    459     {
     408    if (G.telwish == DO) {
     409        putiac2(WONT, TELOPT_ECHO);
     410        return;
     411    }
     412    if (G.telwish == DONT)
     413        return;
     414
     415    if (G.telflags & UF_ECHO) {
    460416        if (G.telwish == WILL)
    461417            return;
    462     }
    463     else
    464         if (G.telwish == WONT)
    465             return;
     418    } else if (G.telwish == WONT)
     419        return;
    466420
    467421    if (G.charmode != CHM_OFF)
     
    474428
    475429    setConMode();
    476     WriteCS(1, "\r\n");  /* sudden modec */
    477 }
    478 
    479 static inline void to_sga(void)
     430    write_str(1, "\r\n");  /* sudden modec */
     431}
     432
     433static void to_sga(void)
    480434{
    481435    /* daemon always sends will/wont, client do/dont */
    482436
    483     if (G.telflags & UF_SGA)
    484     {
     437    if (G.telflags & UF_SGA) {
    485438        if (G.telwish == WILL)
    486439            return;
    487     }
    488     else
    489         if (G.telwish == WONT)
    490             return;
     440    } else if (G.telwish == WONT)
     441        return;
    491442
    492443    if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */
     
    494445    else
    495446        putiac2(DONT, TELOPT_SGA);
    496 
    497     return;
    498 }
    499 
    500 #ifdef CONFIG_FEATURE_TELNET_TTYPE
    501 static inline void to_ttype(void)
     447}
     448
     449#if ENABLE_FEATURE_TELNET_TTYPE
     450static void to_ttype(void)
    502451{
    503452    /* Tell server we will (or won't) do TTYPE */
    504453
    505     if(ttype)
     454    if (G.ttype)
    506455        putiac2(WILL, TELOPT_TTYPE);
    507456    else
    508457        putiac2(WONT, TELOPT_TTYPE);
    509 
    510     return;
    511 }
    512 #endif
    513 
    514 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
    515 static inline void to_new_environ(void)
     458}
     459#endif
     460
     461#if ENABLE_FEATURE_TELNET_AUTOLOGIN
     462static void to_new_environ(void)
    516463{
    517464    /* Tell server we will (or will not) do AUTOLOGIN */
    518465
    519     if (autologin)
     466    if (G.autologin)
    520467        putiac2(WILL, TELOPT_NEW_ENVIRON);
    521468    else
    522469        putiac2(WONT, TELOPT_NEW_ENVIRON);
    523 
    524     return;
    525 }
    526 #endif
    527 
    528 #ifdef CONFIG_FEATURE_AUTOWIDTH
    529 static inline void to_naws(void)
     470}
     471#endif
     472
     473#if ENABLE_FEATURE_AUTOWIDTH
     474static void to_naws(void)
    530475{
    531476    /* Tell server we will do NAWS */
    532477    putiac2(WILL, TELOPT_NAWS);
    533     return;
    534478}
    535479#endif
     
    537481static void telopt(byte c)
    538482{
    539     switch (c)
    540     {
    541         case TELOPT_ECHO:       to_echo();  break;
    542         case TELOPT_SGA:        to_sga();   break;
    543 #ifdef CONFIG_FEATURE_TELNET_TTYPE
    544         case TELOPT_TTYPE:      to_ttype();break;
    545 #endif
    546 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
    547         case TELOPT_NEW_ENVIRON:    to_new_environ();   break;
    548 #endif
    549 #ifdef CONFIG_FEATURE_AUTOWIDTH
    550         case TELOPT_NAWS:       to_naws();
    551                                 putiac_naws(c, win_width, win_height);
    552                                 break;
    553 #endif
    554         default:                to_notsup(c);
    555                                 break;
    556     }
    557 }
    558 
    559 
    560 /* ******************************* */
     483    switch (c) {
     484    case TELOPT_ECHO:
     485        to_echo(); break;
     486    case TELOPT_SGA:
     487        to_sga(); break;
     488#if ENABLE_FEATURE_TELNET_TTYPE
     489    case TELOPT_TTYPE:
     490        to_ttype(); break;
     491#endif
     492#if ENABLE_FEATURE_TELNET_AUTOLOGIN
     493    case TELOPT_NEW_ENVIRON:
     494        to_new_environ(); break;
     495#endif
     496#if ENABLE_FEATURE_AUTOWIDTH
     497    case TELOPT_NAWS:
     498        to_naws();
     499        putiac_naws(c, G.win_width, G.win_height);
     500        break;
     501#endif
     502    default:
     503        to_notsup(c);
     504        break;
     505    }
     506}
    561507
    562508/* subnegotiation -- ignore all (except TTYPE,NAWS) */
    563 
    564509static int subneg(byte c)
    565510{
    566     switch (G.telstate)
    567     {
     511    switch (G.telstate) {
    568512    case TS_SUB1:
    569513        if (c == IAC)
    570514            G.telstate = TS_SUB2;
    571 #ifdef CONFIG_FEATURE_TELNET_TTYPE
     515#if ENABLE_FEATURE_TELNET_TTYPE
    572516        else
    573517        if (c == TELOPT_TTYPE)
    574             putiac_subopt(TELOPT_TTYPE,ttype);
    575 #endif
    576 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
     518            putiac_subopt(TELOPT_TTYPE, G.ttype);
     519#endif
     520#if ENABLE_FEATURE_TELNET_AUTOLOGIN
    577521        else
    578522        if (c == TELOPT_NEW_ENVIRON)
     
    589533}
    590534
    591 /* ******************************* */
    592 
    593535static void fgotsig(int sig)
    594536{
     
    599541static void rawmode(void)
    600542{
    601     if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_raw);
     543    if (G.do_termios)
     544        tcsetattr(0, TCSADRAIN, &G.termios_raw);
    602545}
    603546
    604547static void cookmode(void)
    605548{
    606     if (G.do_termios) tcsetattr(0, TCSADRAIN, &G.termios_def);
    607 }
    608 
     549    if (G.do_termios)
     550        tcsetattr(0, TCSADRAIN, &G.termios_def);
     551}
     552
     553int telnet_main(int argc, char** argv);
    609554int telnet_main(int argc, char** argv)
    610555{
     556    char *host;
     557    int port;
    611558    int len;
    612     struct sockaddr_in s_in;
    613559#ifdef USE_POLL
    614560    struct pollfd ufds[2];
     
    618564#endif
    619565
    620 #ifdef CONFIG_FEATURE_AUTOWIDTH
    621     get_terminal_width_height(0, &win_width, &win_height);
    622 #endif
    623 
    624 #ifdef CONFIG_FEATURE_TELNET_TTYPE
    625     ttype = getenv("TERM");
    626 #endif
    627 
    628     memset(&G, 0, sizeof G);
     566    INIT_G();
     567
     568#if ENABLE_FEATURE_AUTOWIDTH
     569    get_terminal_width_height(0, &G.win_width, &G.win_height);
     570#endif
     571
     572#if ENABLE_FEATURE_TELNET_TTYPE
     573    G.ttype = getenv("TERM");
     574#endif
    629575
    630576    if (tcgetattr(0, &G.termios_def) >= 0) {
    631577        G.do_termios = 1;
    632 
    633578        G.termios_raw = G.termios_def;
    634579        cfmakeraw(&G.termios_raw);
     
    638583        bb_show_usage();
    639584
    640 #ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
    641     if (1 & bb_getopt_ulflags(argc, argv, "al:", &autologin))
    642         autologin = getenv("USER");
    643 
    644     if (optind < argc) {
    645         bb_lookup_host(&s_in, argv[optind++]);
    646         s_in.sin_port = bb_lookup_port((optind < argc) ? argv[optind++] :
    647                 "telnet", "tcp", 23);
    648         if (optind < argc)
    649             bb_show_usage();
    650     } else
     585#if ENABLE_FEATURE_TELNET_AUTOLOGIN
     586    if (1 & getopt32(argv, "al:", &G.autologin))
     587        G.autologin = getenv("USER");
     588    argv += optind;
     589#else
     590    argv++;
     591#endif
     592    if (!*argv)
    651593        bb_show_usage();
    652 #else
    653     bb_lookup_host(&s_in, argv[1]);
    654     s_in.sin_port = bb_lookup_port((argc == 3) ? argv[2] : "telnet", "tcp", 23);
    655 #endif
    656 
    657     G.netfd = xconnect(&s_in);
    658 
    659     setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);
     594    host = *argv++;
     595    port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23);
     596    if (*argv) /* extra params?? */
     597        bb_show_usage();
     598
     599    G.netfd = create_and_connect_stream_or_die(host, port);
     600
     601    setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));
    660602
    661603    signal(SIGINT, fgotsig);
     
    671613#endif
    672614
    673     while (1)
    674     {
     615    while (1) {
    675616#ifndef USE_POLL
    676617        fd_set rfds = readfds;
     
    699640            {
    700641                len = read(0, G.buf, DATABUFSIZE);
    701 
    702642                if (len <= 0)
    703643                    doexit(0);
    704 
    705644                TRACE(0, ("Read con: %d\n", len));
    706 
    707645                handlenetoutput(len);
    708646            }
     
    715653            {
    716654                len = read(G.netfd, G.buf, DATABUFSIZE);
    717 
    718                 if (len <= 0)
    719                 {
    720                     WriteCS(1, "Connection closed by foreign host.\r\n");
     655                if (len <= 0) {
     656                    write_str(1, "Connection closed by foreign host\r\n");
    721657                    doexit(1);
    722658                }
    723659                TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
    724 
    725660                handlenetinput(len);
    726661            }
Note: See TracChangeset for help on using the changeset viewer.