Changeset 46304a4547d3e7cd3b7e98eaa2b8653034cd1c6b

Show
Ignore:
Timestamp:
02/08/08 05:29:46 (7 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1202448586 +0000
git-parent:

[30700011fc4916bef71870a2bae7739745a7a2bc]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1202448586 +0000
Message:

add in linemode

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_console_telnet.c

    r3070001 r46304a4  
    7272#define terminalname ncct->telnet->_terminalname 
    7373#define flowmode ncct->telnet->_flowmode 
     74#define linemode ncct->telnet->_linemode 
     75#define uselinemode ncct->telnet->_uselinemode 
     76#define alwayslinemode ncct->telnet->_alwayslinemode 
    7477#define restartany ncct->telnet->_restartany 
     78#define _terminit ncct->telnet->__terminit 
     79#define turn_on_sga ncct->telnet->_turn_on_sga 
     80#define useeditmode ncct->telnet->_useeditmode 
     81#define editmode ncct->telnet->_editmode 
     82#define def_slcbuf ncct->telnet->_def_slcbuf 
     83#define def_slclen ncct->telnet->_def_slclen 
     84#define slcchange ncct->telnet->_slcchange 
     85#define slcptr ncct->telnet->_slcptr 
     86#define slcbuf ncct->telnet->_slcbuf 
    7587#define def_tspeed ncct->telnet->_def_tspeed 
    7688#define def_rspeed ncct->telnet->_def_rspeed 
     
    103115  noit_console_continue_sending(ncct, &unused); 
    104116} 
     117static void set_termbuf(noit_console_closure_t ncct); 
     118static void init_termbuf(noit_console_closure_t ncct); 
     119static void defer_terminit(noit_console_closure_t ncct); 
     120static void flowstat(noit_console_closure_t ncct); 
     121static int spcset(noit_console_closure_t ncct, int func, cc_t *valp, cc_t **valpp); 
     122static void suboption(noit_console_closure_t ncct); 
     123static void send_slc(noit_console_closure_t ncct); 
     124static void default_slc(noit_console_closure_t ncct); 
     125static void get_slc_defaults(noit_console_closure_t ncct); 
     126static void add_slc(noit_console_closure_t ncct, char func, char flag, cc_t val); 
     127static void start_slc(noit_console_closure_t ncct, int getit); 
     128static int end_slc(noit_console_closure_t ncct, unsigned char **bufp); 
     129static void process_slc(noit_console_closure_t ncct, unsigned char func, unsigned char flag, cc_t val); 
     130static void change_slc(noit_console_closure_t ncct, char func, char flag, cc_t val); 
     131static void check_slc(noit_console_closure_t ncct); 
     132static void do_opt_slc(noit_console_closure_t ncct, unsigned char *ptr, int len); 
     133 
     134#ifdef LINEMODE 
    105135static void 
    106 suboption(noit_console_closure_t ncct); 
     136send_slc(noit_console_closure_t ncct) 
     137
     138        int i; 
     139 
     140        /* 
     141         * Send out list of triplets of special characters 
     142         * to client.  We only send info on the characters 
     143         * that are currently supported. 
     144         */ 
     145        for (i = 1; i <= NSLC; i++) { 
     146                if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) 
     147                        continue; 
     148                add_slc(ncct, (unsigned char)i, slctab[i].current.flag, 
     149                                                        slctab[i].current.val); 
     150        } 
     151 
     152}  /* end of send_slc */ 
     153 
     154/* 
     155 * default_slc 
     156 * 
     157 * Set pty special characters to all the defaults. 
     158 */ 
     159static void 
     160default_slc(noit_console_closure_t ncct) 
     161
     162        int i; 
     163 
     164        for (i = 1; i <= NSLC; i++) { 
     165                slctab[i].current.val = slctab[i].defset.val; 
     166                if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) 
     167                        slctab[i].current.flag = SLC_NOSUPPORT; 
     168                else 
     169                        slctab[i].current.flag = slctab[i].defset.flag; 
     170                if (slctab[i].sptr) { 
     171                        *(slctab[i].sptr) = slctab[i].defset.val; 
     172                } 
     173        } 
     174        slcchange = 1; 
     175 
     176}  /* end of default_slc */ 
     177#endif  /* LINEMODE */ 
     178 
     179/* 
     180 * get_slc_defaults 
     181 * 
     182 * Initialize the slc mapping table. 
     183 */ 
     184static void 
     185get_slc_defaults(noit_console_closure_t ncct) 
     186
     187        int i; 
     188 
     189        init_termbuf(ncct); 
     190 
     191        for (i = 1; i <= NSLC; i++) { 
     192                slctab[i].defset.flag = 
     193                        spcset(ncct, i, &slctab[i].defset.val, &slctab[i].sptr); 
     194                slctab[i].current.flag = SLC_NOSUPPORT; 
     195                slctab[i].current.val = 0; 
     196        } 
     197 
     198}  /* end of get_slc_defaults */ 
     199 
     200#ifdef  LINEMODE 
     201/* 
     202 * add_slc 
     203 * 
     204 * Add an slc triplet to the slc buffer. 
     205 */ 
     206static void 
     207add_slc(noit_console_closure_t ncct, char func, char flag, cc_t val) 
     208
     209 
     210        if ((*slcptr++ = (unsigned char)func) == 0xff) 
     211                *slcptr++ = 0xff; 
     212 
     213        if ((*slcptr++ = (unsigned char)flag) == 0xff) 
     214                *slcptr++ = 0xff; 
     215 
     216        if ((*slcptr++ = (unsigned char)val) == 0xff) 
     217                *slcptr++ = 0xff; 
     218 
     219}  /* end of add_slc */ 
     220 
     221/* 
     222 * start_slc 
     223 * 
     224 * Get ready to process incoming slc's and respond to them. 
     225 * 
     226 * The parameter getit is non-zero if it is necessary to grab a copy 
     227 * of the terminal control structures. 
     228 */ 
     229static void 
     230start_slc(noit_console_closure_t ncct, int getit) 
     231
     232 
     233        slcchange = 0; 
     234        if (getit) 
     235                init_termbuf(ncct); 
     236        (void) sprintf((char *)slcbuf, "%c%c%c%c", 
     237                                        IAC, SB, TELOPT_LINEMODE, LM_SLC); 
     238        slcptr = slcbuf + 4; 
     239 
     240}  /* end of start_slc */ 
     241 
     242/* 
     243 * end_slc 
     244 * 
     245 * Finish up the slc negotiation.  If something to send, then send it. 
     246 */ 
     247int 
     248end_slc(noit_console_closure_t ncct, unsigned char **bufp) 
     249
     250        int len; 
     251 
     252        /* 
     253         * If a change has occured, store the new terminal control 
     254         * structures back to the terminal driver. 
     255         */ 
     256        if (slcchange) { 
     257                set_termbuf(ncct); 
     258        } 
     259 
     260        /* 
     261         * If the pty state has not yet been fully processed and there is a 
     262         * deferred slc request from the client, then do not send any 
     263         * sort of slc negotiation now.  We will respond to the client's 
     264         * request very soon. 
     265         */ 
     266        if (def_slcbuf && (_terminit == 0)) { 
     267                return(0); 
     268        } 
     269 
     270        if (slcptr > (slcbuf + 4)) { 
     271                if (bufp) { 
     272                        *bufp = &slcbuf[4]; 
     273                        return(slcptr - slcbuf - 4); 
     274                } else { 
     275                        (void) sprintf((char *)slcptr, "%c%c", IAC, SE); 
     276                        slcptr += 2; 
     277                        len = slcptr - slcbuf; 
     278                        nc_write(ncct, slcbuf, len); 
     279                        netflush(ncct);  /* force it out immediately */ 
     280                } 
     281        } 
     282        return (0); 
     283 
     284}  /* end of end_slc */ 
     285 
     286/* 
     287 * process_slc 
     288 * 
     289 * Figure out what to do about the client's slc 
     290 */ 
     291static void 
     292process_slc(noit_console_closure_t ncct, unsigned char func, unsigned char flag, cc_t val) 
     293
     294        int hislevel, mylevel, ack; 
     295 
     296        /* 
     297         * Ensure that we know something about this function 
     298         */ 
     299        if (func > NSLC) { 
     300                add_slc(ncct, func, SLC_NOSUPPORT, 0); 
     301                return; 
     302        } 
     303 
     304        /* 
     305         * Process the special case requests of 0 SLC_DEFAULT 0 
     306         * and 0 SLC_VARIABLE 0.  Be a little forgiving here, don't 
     307         * worry about whether the value is actually 0 or not. 
     308         */ 
     309        if (func == 0) { 
     310                if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { 
     311                        default_slc(ncct); 
     312                        send_slc(ncct); 
     313                } else if (flag == SLC_VARIABLE) { 
     314                        send_slc(ncct); 
     315                } 
     316                return; 
     317        } 
     318 
     319        /* 
     320         * Appears to be a function that we know something about.  So 
     321         * get on with it and see what we know. 
     322         */ 
     323 
     324        hislevel = flag & SLC_LEVELBITS; 
     325        mylevel = slctab[func].current.flag & SLC_LEVELBITS; 
     326        ack = flag & SLC_ACK; 
     327        /* 
     328         * ignore the command if: 
     329         * the function value and level are the same as what we already have; 
     330         * or the level is the same and the ack bit is set 
     331         */ 
     332        if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { 
     333                return; 
     334        } else if (ack) { 
     335                /* 
     336                 * If we get here, we got an ack, but the levels don't match. 
     337                 * This shouldn't happen.  If it does, it is probably because 
     338                 * we have sent two requests to set a variable without getting 
     339                 * a response between them, and this is the first response. 
     340                 * So, ignore it, and wait for the next response. 
     341                 */ 
     342                return; 
     343        } else { 
     344                change_slc(ncct, func, flag, val); 
     345        } 
     346 
     347}  /* end of process_slc */ 
     348 
     349/* 
     350 * change_slc 
     351 * 
     352 * Process a request to change one of our special characters. 
     353 * Compare client's request with what we are capable of supporting. 
     354 */ 
     355static void 
     356change_slc(noit_console_closure_t ncct, char func, char flag, cc_t val) 
     357
     358        int hislevel, mylevel; 
     359 
     360        hislevel = flag & SLC_LEVELBITS; 
     361        mylevel = slctab[(int)func].defset.flag & SLC_LEVELBITS; 
     362        /* 
     363         * If client is setting a function to NOSUPPORT 
     364         * or DEFAULT, then we can easily and directly 
     365         * accomodate the request. 
     366         */ 
     367        if (hislevel == SLC_NOSUPPORT) { 
     368                slctab[(int)func].current.flag = flag; 
     369                slctab[(int)func].current.val = (cc_t)_POSIX_VDISABLE; 
     370                flag |= SLC_ACK; 
     371                add_slc(ncct, func, flag, val); 
     372                return; 
     373        } 
     374        if (hislevel == SLC_DEFAULT) { 
     375                /* 
     376                 * Special case here.  If client tells us to use 
     377                 * the default on a function we don't support, then 
     378                 * return NOSUPPORT instead of what we may have as a 
     379                 * default level of DEFAULT. 
     380                 */ 
     381                if (mylevel == SLC_DEFAULT) { 
     382                        slctab[(int)func].current.flag = SLC_NOSUPPORT; 
     383                } else { 
     384                        slctab[(int)func].current.flag = slctab[(int)func].defset.flag; 
     385                } 
     386                slctab[(int)func].current.val = slctab[(int)func].defset.val; 
     387                add_slc(ncct, func, slctab[(int)func].current.flag, 
     388                                                slctab[(int)func].current.val); 
     389                return; 
     390        } 
     391 
     392        /* 
     393         * Client wants us to change to a new value or he 
     394         * is telling us that he can't change to our value. 
     395         * Some of the slc's we support and can change, 
     396         * some we do support but can't change, 
     397         * and others we don't support at all. 
     398         * If we can change it then we have a pointer to 
     399         * the place to put the new value, so change it, 
     400         * otherwise, continue the negotiation. 
     401         */ 
     402        if (slctab[(int)func].sptr) { 
     403                /* 
     404                 * We can change this one. 
     405                 */ 
     406                slctab[(int)func].current.val = val; 
     407                *(slctab[(int)func].sptr) = val; 
     408                slctab[(int)func].current.flag = flag; 
     409                flag |= SLC_ACK; 
     410                slcchange = 1; 
     411                add_slc(ncct, func, flag, val); 
     412        } else { 
     413                /* 
     414                * It is not possible for us to support this 
     415                * request as he asks. 
     416                * 
     417                * If our level is DEFAULT, then just ack whatever was 
     418                * sent. 
     419                * 
     420                * If he can't change and we can't change, 
     421                * then degenerate to NOSUPPORT. 
     422                * 
     423                * Otherwise we send our level back to him, (CANTCHANGE 
     424                * or NOSUPPORT) and if CANTCHANGE, send 
     425                * our value as well. 
     426                */ 
     427                if (mylevel == SLC_DEFAULT) { 
     428                        slctab[(int)func].current.flag = flag; 
     429                        slctab[(int)func].current.val = val; 
     430                        flag |= SLC_ACK; 
     431                } else if (hislevel == SLC_CANTCHANGE && 
     432                                    mylevel == SLC_CANTCHANGE) { 
     433                        flag &= ~SLC_LEVELBITS; 
     434                        flag |= SLC_NOSUPPORT; 
     435                        slctab[(int)func].current.flag = flag; 
     436                } else { 
     437                        flag &= ~SLC_LEVELBITS; 
     438                        flag |= mylevel; 
     439                        slctab[(int)func].current.flag = flag; 
     440                        if (mylevel == SLC_CANTCHANGE) { 
     441                                slctab[(int)func].current.val = 
     442                                        slctab[(int)func].defset.val; 
     443                                val = slctab[(int)func].current.val; 
     444                        } 
     445                } 
     446                add_slc(ncct, func, flag, val); 
     447        } 
     448 
     449}  /* end of change_slc */ 
     450 
     451#if     defined(USE_TERMIO) && (VEOF == VMIN) 
     452cc_t oldeofc = '\004'; 
     453#endif 
     454 
     455/* 
     456 * check_slc 
     457 * 
     458 * Check the special characters in use and notify the client if any have 
     459 * changed.  Only those characters that are capable of being changed are 
     460 * likely to have changed.  If a local change occurs, kick the support level 
     461 * and flags up to the defaults. 
     462 */ 
     463static void 
     464check_slc(noit_console_closure_t ncct) 
     465
     466        int i; 
     467 
     468        for (i = 1; i <= NSLC; i++) { 
     469#if     defined(USE_TERMIO) && (VEOF == VMIN) 
     470                /* 
     471                 * In a perfect world this would be a neat little 
     472                 * function.  But in this world, we should not notify 
     473                 * client of changes to the VEOF char when 
     474                 * ICANON is off, because it is not representing 
     475                 * a special character. 
     476                 */ 
     477                if (i == SLC_EOF) { 
     478                        if (!noit_console_telnet_tty_isediting(ncct)) 
     479                                continue; 
     480                        else if (slctab[i].sptr) 
     481                                oldeofc = *(slctab[i].sptr); 
     482                } 
     483#endif  /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ 
     484                if (slctab[i].sptr && 
     485                                (*(slctab[i].sptr) != slctab[i].current.val)) { 
     486                        slctab[i].current.val = *(slctab[i].sptr); 
     487                        if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) 
     488                                slctab[i].current.flag = SLC_NOSUPPORT; 
     489                        else 
     490                                slctab[i].current.flag = slctab[i].defset.flag; 
     491                        add_slc(ncct, (unsigned char)i, slctab[i].current.flag, 
     492                                                slctab[i].current.val); 
     493                } 
     494        } 
     495}  /* check_slc */ 
     496 
     497/* 
     498 * do_opt_slc 
     499 * 
     500 * Process an slc option buffer.  Defer processing of incoming slc's 
     501 * until after the terminal state has been processed.  Save the first slc 
     502 * request that comes along, but discard all others. 
     503 * 
     504 * ptr points to the beginning of the buffer, len is the length. 
     505 */ 
     506static void 
     507do_opt_slc(noit_console_closure_t ncct, unsigned char *ptr, int len) 
     508
     509        unsigned char func, flag; 
     510        cc_t val; 
     511        unsigned char *end = ptr + len; 
     512 
     513        if (_terminit) {  /* go ahead */ 
     514                while (ptr < end) { 
     515                        func = *ptr++; 
     516                        if (ptr >= end) break; 
     517                        flag = *ptr++; 
     518                        if (ptr >= end) break; 
     519                        val = (cc_t)*ptr++; 
     520 
     521                        process_slc(ncct, func, flag, val); 
     522 
     523                } 
     524        } else { 
     525                /* 
     526                 * save this slc buffer if it is the first, otherwise dump 
     527                 * it. 
     528                 */ 
     529                if (def_slcbuf == (unsigned char *)0) { 
     530                        def_slclen = len; 
     531                        def_slcbuf = (unsigned char *)malloc((unsigned)len); 
     532                        if (def_slcbuf == (unsigned char *)0) 
     533                                return;  /* too bad */ 
     534                        memmove(def_slcbuf, ptr, len); 
     535                } 
     536        } 
     537 
     538}  /* end of do_opt_slc */ 
     539 
     540/* 
     541 * deferslc 
     542 * 
     543 * Do slc stuff that was deferred. 
     544 */ 
     545static void 
     546deferslc(noit_console_closure_t ncct) 
     547
     548        if (def_slcbuf) { 
     549                start_slc(ncct, 1); 
     550                do_opt_slc(ncct, def_slcbuf, def_slclen); 
     551                (void) end_slc(ncct, 0); 
     552                free(def_slcbuf); 
     553                def_slcbuf = (unsigned char *)0; 
     554                def_slclen = 0; 
     555        } 
     556 
     557}  /* end of deferslc */ 
     558#endif 
     559 
     560#ifdef  LINEMODE 
     561/* 
     562 * tty_flowmode()       Find out if flow control is enabled or disabled. 
     563 * tty_linemode()       Find out if linemode (external processing) is enabled. 
     564 * tty_setlinemod(on)   Turn on/off linemode. 
     565 * tty_isecho()         Find out if echoing is turned on. 
     566 * tty_setecho(on)      Enable/disable character echoing. 
     567 * tty_israw()          Find out if terminal is in RAW mode. 
     568 * tty_binaryin(on)     Turn on/off BINARY on input. 
     569 * tty_binaryout(on)    Turn on/off BINARY on output. 
     570 * tty_isediting()      Find out if line editing is enabled. 
     571 * tty_istrapsig()      Find out if signal trapping is enabled. 
     572 * tty_setedit(on)      Turn on/off line editing. 
     573 * tty_setsig(on)       Turn on/off signal trapping. 
     574 * tty_issofttab()      Find out if tab expansion is enabled. 
     575 * tty_setsofttab(on)   Turn on/off soft tab expansion. 
     576 * tty_islitecho()      Find out if typed control chars are echoed literally 
     577 * tty_setlitecho()     Turn on/off literal echo of control chars 
     578 * tty_tspeed(val)      Set transmit speed to val. 
     579 * tty_rspeed(val)      Set receive speed to val. 
     580 */ 
     581 
     582 
     583int 
     584noit_console_telnet_tty_linemode(noit_console_closure_t ncct) 
     585
     586#ifndef    USE_TERMIO 
     587#ifdef TS_EXTPROC 
     588    return(termbuf.state & TS_EXTPROC); 
     589#else 
     590    return 0; 
     591#endif 
     592#else 
     593    return(termbuf.c_lflag & EXTPROC); 
     594#endif 
     595
     596 
     597void 
     598noit_console_telnet_tty_setlinemode(noit_console_closure_t ncct, int on) 
     599
     600#ifdef    TIOCEXT 
     601    set_termbuf(ncct); 
     602    (void) ioctl(pty, TIOCEXT, (char *)&on); 
     603    init_termbuf(ncct); 
     604#else    /* !TIOCEXT */ 
     605# ifdef    EXTPROC 
     606    if (on) 
     607        termbuf.c_lflag |= EXTPROC; 
     608    else 
     609        termbuf.c_lflag &= ~EXTPROC; 
     610# endif 
     611#endif    /* TIOCEXT */ 
     612
     613 
     614void 
     615noit_console_telnet_tty_setsig(noit_console_closure_t ncct, int on) 
     616
     617#ifndef USE_TERMIO 
     618        if (on) 
     619                ; 
     620#else 
     621        if (on) 
     622                termbuf.c_lflag |= ISIG; 
     623        else 
     624                termbuf.c_lflag &= ~ISIG; 
     625#endif 
     626
     627 
     628void 
     629noit_console_telnet_tty_setedit(noit_console_closure_t ncct, int on) 
     630
     631#ifndef USE_TERMIO 
     632    if (on) 
     633        termbuf.sg.sg_flags &= ~CBREAK; 
     634    else 
     635        termbuf.sg.sg_flags |= CBREAK; 
     636#else 
     637    if (on) 
     638        termbuf.c_lflag |= ICANON; 
     639    else 
     640        termbuf.c_lflag &= ~ICANON; 
     641#endif 
     642
     643#endif  /* LINEMODE */ 
     644 
     645int 
     646noit_console_telnet_tty_istrapsig(noit_console_closure_t ncct) 
     647
     648#ifndef USE_TERMIO 
     649    return(!(termbuf.sg.sg_flags&RAW)); 
     650#else 
     651    return(termbuf.c_lflag & ISIG); 
     652#endif 
     653
     654 
     655#ifdef  LINEMODE 
     656int 
     657noit_console_telnet_tty_isediting(noit_console_closure_t ncct) 
     658
     659#ifndef USE_TERMIO 
     660    return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 
     661#else 
     662    return(termbuf.c_lflag & ICANON); 
     663#endif 
     664
     665#endif 
     666 
     667int 
     668noit_console_telnet_tty_issofttab(noit_console_closure_t ncct) 
     669
     670#ifndef    USE_TERMIO 
     671    return (termbuf.sg.sg_flags & XTABS); 
     672#else 
     673# ifdef    OXTABS 
     674    return (termbuf.c_oflag & OXTABS); 
     675# endif 
     676# ifdef    TABDLY 
     677    return ((termbuf.c_oflag & TABDLY) == TAB3); 
     678# endif 
     679#endif 
     680
     681 
     682void 
     683noit_console_telnet_tty_setsofttab(noit_console_closure_t ncct, int on) 
     684
     685#ifndef    USE_TERMIO 
     686    if (on) 
     687        termbuf.sg.sg_flags |= XTABS; 
     688    else 
     689        termbuf.sg.sg_flags &= ~XTABS; 
     690#else 
     691    if (on) { 
     692# ifdef    OXTABS 
     693        termbuf.c_oflag |= OXTABS; 
     694# endif 
     695# ifdef    TABDLY 
     696        termbuf.c_oflag &= ~TABDLY; 
     697        termbuf.c_oflag |= TAB3; 
     698# endif 
     699    } else { 
     700# ifdef    OXTABS 
     701        termbuf.c_oflag &= ~OXTABS; 
     702# endif 
     703# ifdef    TABDLY 
     704        termbuf.c_oflag &= ~TABDLY; 
     705        termbuf.c_oflag |= TAB0; 
     706# endif 
     707    } 
     708#endif 
     709
     710 
     711int 
     712noit_console_telnet_tty_islitecho(noit_console_closure_t ncct) 
     713
     714#ifndef    USE_TERMIO 
     715    return (!(termbuf.lflags & LCTLECH)); 
     716#else 
     717# ifdef    ECHOCTL 
     718    return (!(termbuf.c_lflag & ECHOCTL)); 
     719# endif 
     720# ifdef    TCTLECH 
     721    return (!(termbuf.c_lflag & TCTLECH)); 
     722# endif 
     723# if    !defined(ECHOCTL) && !defined(TCTLECH) 
     724    return (0);    /* assumes ctl chars are echoed '^x' */ 
     725# endif 
     726#endif 
     727
     728 
     729void 
     730noit_console_telnet_tty_setlitecho(noit_console_closure_t ncct, int on) 
     731
     732#ifndef    USE_TERMIO 
     733    if (on) 
     734        termbuf.lflags &= ~LCTLECH; 
     735    else 
     736        termbuf.lflags |= LCTLECH; 
     737#else 
     738# ifdef    ECHOCTL 
     739    if (on) 
     740        termbuf.c_lflag &= ~ECHOCTL; 
     741    else 
     742        termbuf.c_lflag |= ECHOCTL; 
     743# endif 
     744# ifdef    TCTLECH 
     745    if (on) 
     746        termbuf.c_lflag &= ~TCTLECH; 
     747    else 
     748        termbuf.c_lflag |= TCTLECH; 
     749# endif 
     750#endif 
     751
     752 
     753int 
     754noit_console_telnet_tty_iscrnl(noit_console_closure_t ncct) 
     755
     756#ifndef USE_TERMIO 
     757    return (termbuf.sg.sg_flags & CRMOD); 
     758#else 
     759    return (termbuf.c_iflag & ICRNL); 
     760#endif 
     761
    107762 
    108763void 
     
    142797noit_console_telnet_tty_flowmode(noit_console_closure_t ncct) 
    143798{ 
     799#ifndef USE_TERMIO 
     800    return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 
     801#else 
    144802    return((termbuf.c_iflag & IXON) ? 1 : 0); 
     803#endif 
    145804} 
    146805 
     
    148807noit_console_telnet_tty_binaryin(noit_console_closure_t ncct, int on) 
    149808{ 
     809#ifndef USE_TERMIO 
     810    if (on) 
     811        termbuf.lflags |= LPASS8; 
     812    else 
     813        termbuf.lflags &= ~LPASS8; 
     814#else 
     815    if (on) 
     816        termbuf.c_iflag &= ~ISTRIP; 
     817    else 
     818        termbuf.c_iflag |= ISTRIP; 
     819#endif 
     820} 
     821 
     822int 
     823noit_console_telnet_tty_isbinaryin(noit_console_closure_t ncct) 
     824{ 
     825#ifndef USE_TERMIO 
     826        return(termbuf.lflags & LPASS8); 
     827#else 
     828        return(!(termbuf.c_iflag & ISTRIP)); 
     829#endif 
     830} 
     831 
     832void 
     833noit_console_telnet_tty_binaryout(noit_console_closure_t ncct, int on) 
     834{ 
     835#ifndef USE_TERMIO 
     836    if (on) 
     837        termbuf.lflags |= LLITOUT; 
     838    else 
     839        termbuf.lflags &= ~LLITOUT; 
     840#else 
    150841    if (on) { 
    151         termbuf.c_iflag &= ~ISTRIP; 
     842        termbuf.c_cflag &= ~(CSIZE|PARENB); 
     843        termbuf.c_cflag |= CS8; 
     844        termbuf.c_oflag &= ~OPOST; 
    152845    } else { 
    153         termbuf.c_iflag |= ISTRIP; 
     846        termbuf.c_cflag &= ~CSIZE; 
     847        termbuf.c_cflag |= CS7|PARENB; 
     848        termbuf.c_oflag |= OPOST; 
    154849    } 
     850#endif 
     851} 
     852 
     853int 
     854noit_console_telnet_tty_isbinaryout(noit_console_closure_t ncct) 
     855{ 
     856#ifndef USE_TERMIO 
     857        return(termbuf.lflags & LLITOUT); 
     858#else 
     859        return(!(termbuf.c_oflag&OPOST)); 
     860#endif 
    155861} 
    156862 
     
    158864noit_console_telnet_tty_restartany(noit_console_closure_t ncct) 
    159865{ 
     866#ifndef USE_TERMIO 
     867# ifdef DECCTQ 
     868    return((termbuf.lflags & DECCTQ) ? 0 : 1); 
     869# else 
     870    return(-1); 
     871# endif 
     872#else 
    160873    return((termbuf.c_iflag & IXANY) ? 1 : 0); 
     874#endif 
     875} 
     876 
     877int 
     878noit_console_telnet_tty_isecho(noit_console_closure_t ncct) 
     879{ 
     880#ifndef USE_TERMIO 
     881        return (termbuf.sg.sg_flags & ECHO); 
     882#else 
     883        return (termbuf.c_lflag & ECHO); 
     884#endif 
    161885} 
    162886 
     
    182906} 
    183907 
    184 void 
    185 noit_console_telnet_tty_binaryout(noit_console_closure_t ncct, int on) 
    186 
    187     if (on) { 
    188         termbuf.c_cflag &= ~(CSIZE|PARENB); 
    189         termbuf.c_cflag |= CS8; 
    190         termbuf.c_oflag &= ~OPOST; 
    191     } else { 
    192         termbuf.c_cflag &= ~CSIZE; 
    193         termbuf.c_cflag |= CS7|PARENB; 
    194         termbuf.c_oflag |= OPOST; 
    195     } 
    196 
    197  
    198 void 
     908static void 
    199909init_termbuf(noit_console_closure_t ncct) 
    200910{ 
     
    223933#endif  /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 
    224934 
    225 void 
     935static void 
    226936set_termbuf(noit_console_closure_t ncct) 
    227937{ 
     
    247957} 
    248958 
     959#ifdef  LINEMODE 
     960/* 
     961 * localstat 
     962 * 
     963 * This function handles all management of linemode. 
     964 * 
     965 * Linemode allows the client to do the local editing of data 
     966 * and send only complete lines to the server.  Linemode state is 
     967 * based on the state of the pty driver.  If the pty is set for 
     968 * external processing, then we can use linemode.  Further, if we 
     969 * can use real linemode, then we can look at the edit control bits 
     970 * in the pty to determine what editing the client should do. 
     971 * 
     972 * Linemode support uses the following state flags to keep track of 
     973 * current and desired linemode state. 
     974 *      alwayslinemode : true if -l was specified on the telnetd 
     975 *      command line.  It means to have linemode on as much as 
     976 *      possible. 
     977 * 
     978 *      lmodetype: signifies whether the client can 
     979 *      handle real linemode, or if use of kludgeomatic linemode 
     980 *      is preferred.  It will be set to one of the following: 
     981 *              REAL_LINEMODE : use linemode option 
     982 *              NO_KLUDGE : don't initiate kludge linemode. 
     983 *              KLUDGE_LINEMODE : use kludge linemode 
     984 *              NO_LINEMODE : client is ignorant of linemode 
     985 * 
     986 *      linemode, uselinemode : linemode is true if linemode 
     987 *      is currently on, uselinemode is the state that we wish 
     988 *      to be in.  If another function wishes to turn linemode 
     989 *      on or off, it sets or clears uselinemode. 
     990 * 
     991 *      editmode, useeditmode : like linemode/uselinemode, but 
     992 *      these contain the edit mode states (edit and trapsig). 
     993 * 
     994 * The state variables correspond to some of the state information 
     995 * in the pty. 
     996 *      linemode: 
     997 *              In real linemode, this corresponds to whether the pty 
     998 *              expects external processing of incoming data. 
     999 *              In kludge linemode, this more closely corresponds to the 
     1000 *              whether normal processing is on or not.  (ICANON in 
     1001 *              system V, or COOKED mode in BSD.) 
     1002 *              If the -l option was specified (alwayslinemode), then 
     1003 *              an attempt is made to force external processing on at 
     1004 *              all times. 
     1005 * 
     1006 * The following heuristics are applied to determine linemode 
     1007 * handling within the server. 
     1008 *      1) Early on in starting up the server, an attempt is made 
     1009 *         to negotiate the linemode option.  If this succeeds 
     1010 *         then lmodetype is set to REAL_LINEMODE and all linemode 
     1011 *         processing occurs in the context of the linemode option. 
     1012 *      2) If the attempt to negotiate the linemode option failed, 
     1013 *         and the "-k" (don't initiate kludge linemode) isn't set, 
     1014 *         then we try to use kludge linemode.  We test for this 
     1015 *         capability by sending "do Timing Mark".  If a positive 
     1016 *         response comes back, then we assume that the client 
     1017 *         understands kludge linemode (ech!) and the 
     1018 *         lmodetype flag is set to KLUDGE_LINEMODE. 
     1019 *      3) Otherwise, linemode is not supported at all and 
     1020 *         lmodetype remains set to NO_LINEMODE (which happens 
     1021 *         to be 0 for convenience). 
     1022 *      4) At any time a command arrives that implies a higher 
     1023 *         state of linemode support in the client, we move to that 
     1024 *         linemode support. 
     1025 * 
     1026 * A short explanation of kludge linemode is in order here. 
     1027 *      1) The heuristic to determine support for kludge linemode 
     1028 *         is to send a do timing mark.  We assume that a client 
     1029 *         that supports timing marks also supports kludge linemode. 
     1030 *         A risky proposition at best. 
     1031 *      2) Further negotiation of linemode is done by changing the 
     1032 *         the server's state regarding SGA.  If server will SGA, 
     1033 *         then linemode is off, if server won't SGA, then linemode 
     1034 *         is on. 
     1035 */ 
     1036static void 
     1037localstat(noit_console_closure_t ncct) 
     1038{ 
     1039        int need_will_echo = 0; 
     1040 
     1041        /* 
     1042         * Check for changes to flow control if client supports it. 
     1043         */ 
     1044        flowstat(ncct); 
     1045 
     1046        /* 
     1047         * Check linemode on/off state 
     1048         */ 
     1049        uselinemode = noit_console_telnet_tty_linemode(ncct); 
     1050 
     1051        /* 
     1052         * If alwayslinemode is on, and pty is changing to turn it off, then 
     1053         * force linemode back on. 
     1054         */ 
     1055        if (alwayslinemode && linemode && !uselinemode) { 
     1056                uselinemode = 1; 
     1057                noit_console_telnet_tty_setlinemode(ncct, uselinemode); 
     1058        } 
     1059 
     1060        if (uselinemode) { 
     1061                /* 
     1062                 * Check for state of BINARY options. 
     1063                 * 
     1064                 * We only need to do the binary dance if we are actually going 
     1065                 * to use linemode.  As this confuses some telnet clients 
     1066                 * that don't support linemode, and doesn't gain us 
     1067                 * anything, we don't do it unless we're doing linemode. 
     1068                 * -Crh (henrich@msu.edu) 
     1069                 */ 
     1070 
     1071                if (noit_console_telnet_tty_isbinaryin(ncct)) { 
     1072                        if (his_want_state_is_wont(TELOPT_BINARY)) 
     1073                                send_do(TELOPT_BINARY, 1); 
     1074                } else { 
     1075                        if (his_want_state_is_will(TELOPT_BINARY)) 
     1076                                send_dont(TELOPT_BINARY, 1); 
     1077                } 
     1078 
     1079                if (noit_console_telnet_tty_isbinaryout(ncct)) { 
     1080                        if (my_want_state_is_wont(TELOPT_BINARY)) 
     1081                                send_will(TELOPT_BINARY, 1); 
     1082                } else { 
     1083                        if (my_want_state_is_will(TELOPT_BINARY)) 
     1084                                send_wont(TELOPT_BINARY, 1); 
     1085                } 
     1086        } 
     1087 
     1088 
     1089        /* 
     1090         * Do echo mode handling as soon as we know what the 
     1091         * linemode is going to be. 
     1092         * If the pty has echo turned off, then tell the client that 
     1093         * the server will echo.  If echo is on, then the server 
     1094         * will echo if in character mode, but in linemode the 
     1095         * client should do local echoing.  The state machine will 
     1096         * not send anything if it is unnecessary, so don't worry 
     1097         * about that here. 
     1098         * 
     1099         * If we need to send the WILL ECHO (because echo is off), 
     1100         * then delay that until after we have changed the MODE. 
     1101         * This way, when the user is turning off both editing 
     1102         * and echo, the client will get editing turned off first. 
     1103         * This keeps the client from going into encryption mode 
     1104         * and then right back out if it is doing auto-encryption 
     1105         * when passwords are being typed. 
     1106         */ 
     1107        if (uselinemode) { 
     1108                if (noit_console_telnet_tty_isecho(ncct)) 
     1109                        send_wont(TELOPT_ECHO, 1); 
     1110                else 
     1111                        need_will_echo = 1; 
     1112#ifdef  KLUDGELINEMODE 
     1113                if (lmodetype == KLUDGE_OK) 
     1114                        lmodetype = KLUDGE_LINEMODE; 
     1115#endif 
     1116        } 
     1117 
     1118        /* 
     1119         * If linemode is being turned off, send appropriate 
     1120         * command and then we're all done. 
     1121         */ 
     1122         if (!uselinemode && linemode) { 
     1123# ifdef KLUDGELINEMODE 
     1124                if (lmodetype == REAL_LINEMODE) { 
     1125# endif /* KLUDGELINEMODE */ 
     1126                        send_dont(TELOPT_LINEMODE, 1); 
     1127# ifdef KLUDGELINEMODE 
     1128                } else if (lmodetype == KLUDGE_LINEMODE) 
     1129                        send_will(TELOPT_SGA, 1); 
     1130# endif /* KLUDGELINEMODE */ 
     1131                send_will(TELOPT_ECHO, 1); 
     1132                linemode = uselinemode; 
     1133                goto done; 
     1134        } 
     1135 
     1136# ifdef KLUDGELINEMODE 
     1137        /* 
     1138         * If using real linemode check edit modes for possible later use. 
     1139         * If we are in kludge linemode, do the SGA negotiation. 
     1140         */ 
     1141        if (lmodetype == REAL_LINEMODE) { 
     1142# endif /* KLUDGELINEMODE */ 
     1143                useeditmode = 0; 
     1144                if (noit_console_telnet_tty_isediting(ncct)) 
     1145                        useeditmode |= MODE_EDIT; 
     1146                if (noit_console_telnet_tty_istrapsig(ncct)) 
     1147                        useeditmode |= MODE_TRAPSIG; 
     1148                if (noit_console_telnet_tty_issofttab(ncct)) 
     1149                        useeditmode |= MODE_SOFT_TAB; 
     1150                if (noit_console_telnet_tty_islitecho(ncct)) 
     1151                        useeditmode |= MODE_LIT_ECHO; 
     1152# ifdef KLUDGELINEMODE 
     1153        } else if (lmodetype == KLUDGE_LINEMODE) { 
     1154                if (noit_console_telnet_tty_isediting(ncct) && uselinemode) 
     1155                        send_wont(TELOPT_SGA, 1); 
     1156                else 
     1157                        send_will(TELOPT_SGA, 1); 
     1158        } 
     1159# endif /* KLUDGELINEMODE */ 
     1160 
     1161        /* 
     1162         * Negotiate linemode on if pty state has changed to turn it on. 
     1163         * Send appropriate command and send along edit mode, then all done. 
     1164         */ 
     1165        if (uselinemode && !linemode) { 
     1166# ifdef KLUDGELINEMODE 
     1167                if (lmodetype == KLUDGE_LINEMODE) { 
     1168                        send_wont(TELOPT_SGA, 1); 
     1169                } else if (lmodetype == REAL_LINEMODE) { 
     1170# endif /* KLUDGELINEMODE */ 
     1171                        send_do(TELOPT_LINEMODE, 1); 
     1172                        /* send along edit modes */ 
     1173                        nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, SB, 
     1174                                TELOPT_LINEMODE, LM_MODE, useeditmode, 
     1175                                IAC, SE); 
     1176                        editmode = useeditmode; 
     1177# ifdef KLUDGELINEMODE 
     1178                } 
     1179# endif /* KLUDGELINEMODE */ 
     1180                linemode = uselinemode; 
     1181                goto done; 
     1182        } 
     1183 
     1184# ifdef KLUDGELINEMODE 
     1185        /* 
     1186         * None of what follows is of any value if not using 
     1187         * real linemode. 
     1188         */ 
     1189        if (lmodetype < REAL_LINEMODE) 
     1190                goto done; 
     1191# endif /* KLUDGELINEMODE */ 
     1192 
     1193        if (linemode && his_state_is_will(TELOPT_LINEMODE)) { 
     1194                /* 
     1195                 * If edit mode changed, send edit mode. 
     1196                 */ 
     1197                 if (useeditmode != editmode) { 
     1198                        /* 
     1199                         * Send along appropriate edit mode mask. 
     1200                         */ 
     1201                        nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, SB, 
     1202                                TELOPT_LINEMODE, LM_MODE, useeditmode, 
     1203                                IAC, SE); 
     1204                        editmode = useeditmode; 
     1205                } 
     1206 
     1207 
     1208                /* 
     1209                 * Check for changes to special characters in use. 
     1210                 */ 
     1211                start_slc(ncct, 0); 
     1212                check_slc(ncct); 
     1213                (void) end_slc(ncct, 0); 
     1214        } 
     1215 
     1216done: 
     1217        if (need_will_echo) 
     1218                send_will(TELOPT_ECHO, 1); 
     1219        /* 
     1220         * Some things should be deferred until after the pty state has 
     1221         * been set by the local process.  Do those things that have been 
     1222         * deferred now.  This only happens once. 
     1223         */ 
     1224        if (_terminit == 0) { 
     1225                _terminit = 1; 
     1226                defer_terminit(ncct); 
     1227        } 
     1228 
     1229        netflush(ncct); 
     1230        set_termbuf(ncct); 
     1231        return; 
     1232 
     1233}  /* end of localstat */ 
     1234#endif  /* LINEMODE */ 
     1235 
    2491236/* 
    2501237 * flowstat 
     
    2521239 * Check for changes to flow control 
    2531240 */ 
    254 void 
     1241static void 
    2551242flowstat(noit_console_closure_t ncct) 
    2561243{ 
     
    2941281     */ 
    2951282    switch (code) { 
     1283#ifdef  LINEMODE 
     1284        case TELOPT_LINEMODE: 
     1285                /* 
     1286                 * Don't do anything unless client is asking us to change 
     1287                 * modes. 
     1288                 */ 
     1289                uselinemode = (parm1 == WILL); 
     1290                if (uselinemode != linemode) { 
     1291# ifdef KLUDGELINEMODE 
     1292                        /* 
     1293                         * If using kludge linemode, make sure that 
     1294                         * we can do what the client asks. 
     1295                         * We can not turn off linemode if alwayslinemode 
     1296                         * and the ICANON bit is set. 
     1297                         */ 
     1298                        if (lmodetype == KLUDGE_LINEMODE) { 
     1299                                if (alwayslinemode && noit_console_telnet_tty_isediting(ncct)) { 
     1300                                        uselinemode = 1; 
     1301                                } 
     1302                        } 
     1303 
     1304                        /* 
     1305                         * Quit now if we can't do it. 
     1306                         */ 
     1307                        if (uselinemode == linemode) 
     1308                                return; 
     1309 
     1310                        /* 
     1311                         * If using real linemode and linemode is being 
     1312                         * turned on, send along the edit mode mask. 
     1313                         */ 
     1314                        if (lmodetype == REAL_LINEMODE && uselinemode) 
     1315# else  /* KLUDGELINEMODE */ 
     1316                        if (uselinemode) 
     1317# endif /* KLUDGELINEMODE */ 
     1318                        { 
     1319                                useeditmode = 0; 
     1320                                if (noit_console_telnet_tty_isediting(ncct)) 
     1321                                        useeditmode |= MODE_EDIT; 
     1322                                if (noit_console_telnet_tty_istrapsig(ncct)) 
     1323                                        useeditmode |= MODE_TRAPSIG; 
     1324                                if (noit_console_telnet_tty_issofttab(ncct)) 
     1325                                        useeditmode |= MODE_SOFT_TAB; 
     1326                                if (noit_console_telnet_tty_islitecho(ncct)) 
     1327                                        useeditmode |= MODE_LIT_ECHO; 
     1328                                nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, 
     1329                                        SB, TELOPT_LINEMODE, LM_MODE, 
     1330                                                        useeditmode, IAC, SE); 
     1331                                editmode = useeditmode; 
     1332                        } 
     1333 
     1334 
     1335                        noit_console_telnet_tty_setlinemode(ncct, uselinemode); 
     1336 
     1337                        linemode = uselinemode; 
     1338 
     1339                        if (!linemode) 
     1340                                send_will(TELOPT_ECHO, 1); 
     1341                } 
     1342                break; 
     1343 
     1344        case LM_MODE: 
     1345            { 
     1346                int ack, changed; 
     1347 
     1348                /* 
     1349                 * Client has sent along a mode mask.  If it agrees with 
     1350                 * what we are currently doing, ignore it; if not, it could 
     1351                 * be viewed as a request to change.  Note that the server 
     1352                 * will change to the modes in an ack if it is different from 
     1353                 * what we currently have, but we will not ack the ack. 
     1354                 */ 
     1355                 useeditmode &= MODE_MASK; 
     1356                 ack = (useeditmode & MODE_ACK); 
     1357                 useeditmode &= ~MODE_ACK; 
     1358 
     1359                 if ((changed = (useeditmode ^ editmode))) { 
     1360                        /* 
     1361                         * This check is for a timing problem.  If the 
     1362                         * state of the tty has changed (due to the user 
     1363                         * application) we need to process that info 
     1364                         * before we write in the state contained in the 
     1365                         * ack!!!  This gets out the new MODE request, 
     1366                         * and when the ack to that command comes back 
     1367                         * we'll set it and be in the right mode. 
     1368                         */ 
     1369                        if (ack) 
     1370                                localstat(ncct); 
     1371                        if (changed & MODE_EDIT) 
     1372                                noit_console_telnet_tty_setedit(ncct, useeditmode & MODE_EDIT); 
     1373 
     1374                        if (changed & MODE_TRAPSIG) 
     1375                                noit_console_telnet_tty_setsig(ncct, useeditmode & MODE_TRAPSIG); 
     1376 
     1377                        if (changed & MODE_SOFT_TAB) 
     1378                                noit_console_telnet_tty_setsofttab(ncct, useeditmode & MODE_SOFT_TAB); 
     1379 
     1380                        if (changed & MODE_LIT_ECHO) 
     1381                                noit_console_telnet_tty_setlitecho(ncct, useeditmode & MODE_LIT_ECHO); 
     1382 
     1383                        set_termbuf(ncct); 
     1384 
     1385                        if (!ack) { 
     1386                                nc_printf(ncct, "%c%c%c%c%c%c%c", IAC, 
     1387                                        SB, TELOPT_LINEMODE, LM_MODE, 
     1388                                        useeditmode|MODE_ACK, 
     1389                                        IAC, SE); 
     1390                        } 
     1391 
     1392                        editmode = useeditmode; 
     1393                } 
     1394 
     1395                break; 
     1396 
     1397            }  /* end of case LM_MODE */ 
     1398#endif  /* LINEMODE */ 
    2961399    case TELOPT_NAWS: 
    2971400#ifdef  TIOCSWINSZ 
     
    3401443} 
    3411444 
     1445#ifdef  LINEMODE 
     1446/* 
     1447 * defer_terminit 
     1448 * 
     1449 * Some things should not be done until after the login process has started 
     1450 * and all the pty modes are set to what they are supposed to be.  This 
     1451 * function is called when the pty state has been processed for the first time. 
     1452 * It calls other functions that do things that were deferred in each module. 
     1453 */ 
     1454static void 
     1455defer_terminit(noit_console_closure_t ncct) 
     1456{ 
     1457 
     1458        /* 
     1459         * local stuff that got deferred. 
     1460         */ 
     1461        if (def_tspeed != -1) { 
     1462                clientstat(ncct, TELOPT_TSPEED, def_tspeed, def_rspeed); 
     1463                def_tspeed = def_rspeed = 0; 
     1464        } 
     1465 
     1466#ifdef  TIOCSWINSZ 
     1467        if (def_col || def_row) { 
     1468                struct winsize ws; 
     1469 
     1470                memset((char *)&ws, 0, sizeof(ws)); 
     1471                ws.ws_col = def_col; 
     1472                ws.ws_row = def_row; 
     1473                (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); 
     1474        } 
     1475#endif 
     1476 
     1477        /* 
     1478         * The only other module that currently defers anything. 
     1479         */ 
     1480        deferslc(ncct); 
     1481 
     1482}  /* end of defer_terminit */ 
     1483#endif 
     1484 
    3421485/* 
    3431486 * spcset(func, valp, valpp) 
     
    3521495 
    3531496#ifndef USE_TERMIO 
    354 int 
     1497static int 
    3551498spcset(noit_console_closure_t ncct, int func, cc_t *valp, cc_t **valpp) 
    3561499{ 
     
    6271770 
    6281771#if     defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 
    629         if (!noit_console_telnet_tty_isediting()) { 
     1772        if (!noit_console_telnet_tty_isediting(ncct)) { 
    6301773                extern char oldeofc; 
    6311774                pty_write(ncct, &oldeofc, 1); 
     
    6401783noit_console_telnet_closure_t 
    6411784noit_console_telnet_alloc(noit_console_closure_t ncct) { 
    642   int i, on; 
     1785  int on; 
    6431786  noit_console_telnet_closure_t telnet, tmp; 
     1787  static unsigned char ttytype_sbbuf[] = { 
     1788    IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE 
     1789  }; 
    6441790  tmp = ncct->telnet; 
    6451791 
     
    6501796  def_tspeed = -1; 
    6511797  def_rspeed = -1; 
    652   for (i = 1; i <= NSLC; i++) { 
    653     slctab[i].defset.flag = 
    654       spcset(ncct, i, &slctab[i].defset.val, &slctab[i].sptr); 
    655     slctab[i].current.flag = SLC_NOSUPPORT; 
    656     slctab[i].current.val = 0; 
    657   } 
     1798  get_slc_defaults(ncct); 
    6581799  if (my_state_is_wont(TELOPT_SGA)) 
    6591800    send_will(TELOPT_SGA, 1); 
     
    6701811    send_will(TELOPT_ECHO, 1); 
    6711812  on = 1; 
     1813  init_termbuf(ncct); 
     1814  localstat(ncct); 
     1815  send_do(TELOPT_TTYPE, 1); 
     1816  send_do(TELOPT_TSPEED, 1); 
     1817  send_do(TELOPT_XDISPLOC, 1); 
     1818  send_do(TELOPT_NEW_ENVIRON, 1); 
     1819  send_do(TELOPT_OLD_ENVIRON, 1); 
     1820  nc_write(ncct, ttytype_sbbuf, sizeof(ttytype_sbbuf)); 
    6721821 
    6731822  telnet = ncct->telnet; 
     
    7541903             */ 
    7551904            if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { 
     1905                int nc = *netip; 
    7561906#ifdef ENCRYPTION 
    757                 int nc = *netip; 
    7581907                if (decrypt_input) 
    7591908                    nc = (*decrypt_input)(nc & 0xff); 
    7601909#endif 
     1910                if (linemode && (ncc > 0) && (('\n' == nc) || 
     1911                         ((0 == nc) && noit_console_telnet_tty_iscrnl(ncct))) ) { 
     1912                        netip++; ncc--; 
     1913                        c = '\n'; 
     1914                } else 
    7611915                { 
    7621916#ifdef ENCRYPTION 
     
    10932247 
    10942248            case TELOPT_TM: 
    1095                 /* 
    1096                  * We never respond to a WILL TM, and 
    1097                  * we leave the state WONT. 
    1098                  */ 
     2249#if     defined(LINEMODE) && defined(KLUDGELINEMODE) 
     2250                        /* 
     2251                         * This telnetd implementation does not really 
     2252                         * support timing marks, it just uses them to 
     2253                         * support the kludge linemode stuff.  If we 
     2254                         * receive a will or wont TM in response to our 
     2255                         * do TM request that may have been sent to 
     2256                         * determine kludge linemode support, process 
     2257                         * it, otherwise TM should get a negative 
     2258                         * response back. 
     2259                         */ 
     2260                        /* 
     2261                         * Handle the linemode kludge stuff. 
     2262                         * If we are not currently supporting any 
     2263                         * linemode at all, then we assume that this 
     2264                         * is the client telling us to use kludge 
     2265                         * linemode in response to our query.  Set the 
     2266                         * linemode type that is to be supported, note 
     2267                         * that the client wishes to use linemode, and 
     2268                         * eat the will TM as though it never arrived. 
     2269                         */ 
     2270                        if (lmodetype < KLUDGE_LINEMODE) { 
     2271                                lmodetype = KLUDGE_LINEMODE; 
     2272                                clientstat(ncct, TELOPT_LINEMODE, WILL, 0); 
     2273                                send_wont(TELOPT_SGA, 1); 
     2274                        } else if (lmodetype == NO_AUTOKLUDGE) { 
     2275                                lmodetype = KLUDGE_OK; 
     2276                        } 
     2277#endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 
    10992278                break; 
    11002279 
     
    11192298                break; 
    11202299 
     2300#ifdef  LINEMODE 
     2301                case TELOPT_LINEMODE: 
     2302# ifdef KLUDGELINEMODE 
     2303                        /* 
     2304                         * Note client's desire to use linemode. 
     2305                         */ 
     2306                        lmodetype = REAL_LINEMODE; 
     2307# endif /* KLUDGELINEMODE */ 
     2308                        func = noit_console_telnet_doclientstat; 
     2309                        changeok++; 
     2310                        break; 
     2311#endif  /* LINEMODE */ 
    11212312 
    11222313#ifdef  AUTHENTICATION 
     
    11752366                break; 
    11762367 
     2368#ifdef  LINEMODE 
     2369                case TELOPT_LINEMODE: 
     2370# ifdef KLUDGELINEMODE 
     2371                        /* 
     2372                         * Note client's desire to use linemode. 
     2373                         */ 
     2374                        lmodetype = REAL_LINEMODE; 
     2375# endif /* KLUDGELINEMODE */ 
     2376                        func = noit_console_telnet_doclientstat; 
     2377                        break; 
     2378#endif  /* LINEMODE */ 
    11772379#ifdef  AUTHENTICATION 
    11782380            case TELOPT_AUTHENTICATION: 
     
    12372439                break; 
    12382440 
     2441#ifdef  LINEMODE 
     2442            case TELOPT_LINEMODE: 
     2443# ifdef KLUDGELINEMODE 
     2444                /* 
     2445                 * If real linemode is supported, then client is 
     2446                 * asking to turn linemode off. 
     2447                 */ 
     2448                if (lmodetype != REAL_LINEMODE) 
     2449                        break; 
     2450                lmodetype = KLUDGE_LINEMODE; 
     2451# endif /* KLUDGELINEMODE */ 
     2452                clientstat(ncct, TELOPT_LINEMODE, WONT, 0); 
     2453                break; 
     2454#endif  /* LINEMODE */ 
     2455 
    12392456            case TELOPT_TM: 
    12402457                /* 
     
    13022519            switch (option) { 
    13032520            case TELOPT_TM: 
     2521#if     defined(LINEMODE) && defined(KLUDGELINEMODE) 
     2522                if (lmodetype < NO_AUTOKLUDGE) { 
     2523                        lmodetype = NO_LINEMODE; 
     2524                        clientstat(TELOPT_LINEMODE, WONT, 0); 
     2525                        send_will(TELOPT_SGA, 1); 
     2526                        send_will(TELOPT_ECHO, 1); 
     2527                } 
     2528#endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 
    13042529                break; 
    13052530 
     
    13312556} 
    13322557 
    1333 /* 
    1334  * When we get a DONT SGA, we will try once to turn it 
    1335  * back on.  If the other side responds DONT SGA, we 
    1336  * leave it at that.  This is so that when we talk to 
    1337  * clients that understand KLUDGELINEMODE but not LINEMODE, 
    1338  * we'll keep them in char-at-a-time mode. 
    1339  */ 
    1340 int turn_on_sga = 0; 
    1341  
    13422558void 
    13432559noit_console_telnet_dooption(noit_console_closure_t ncct, int option) 
     
    13572573        switch (option) { 
    13582574        case TELOPT_ECHO: 
     2575#ifdef  LINEMODE 
     2576# ifdef KLUDGELINEMODE 
     2577            if (lmodetype == NO_LINEMODE) 
     2578# else 
     2579            if (his_state_is_wont(TELOPT_LINEMODE)) 
     2580# endif 
     2581#endif 
    13592582            { 
    13602583                init_termbuf(ncct); 
     
    13732596 
    13742597        case TELOPT_SGA: 
     2598#if     defined(LINEMODE) && defined(KLUDGELINEMODE) 
     2599                /* 
     2600                 * If kludge linemode is in use, then we must 
     2601                 * process an incoming do SGA for linemode 
     2602                 * purposes. 
     2603                 */ 
     2604            if (lmodetype == KLUDGE_LINEMODE) { 
     2605                /* 
     2606                 * Receipt of "do SGA" in kludge 
     2607                 * linemode is the peer asking us to 
     2608                 * turn off linemode.  Make note of 
     2609                 * the request. 
     2610                 */ 
     2611                clientstat(TELOPT_LINEMODE, WONT, 0); 
     2612                /* 
     2613                 * If linemode did not get turned off 
     2614                 * then don't tell peer that we did. 
     2615                 * Breaking here forces a wont SGA to 
     2616                 * be returned. 
     2617                 */ 
     2618                if (linemode) 
     2619                        break; 
     2620            } 
     2621#else 
    13752622            turn_on_sga = 0; 
     2623#endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 
    13762624            changeok++; 
    13772625            break; 
     
    14692717 
    14702718        case TELOPT_ECHO:       /* we should stop echoing */ 
     2719#ifdef  LINEMODE 
     2720# ifdef KLUDGELINEMODE 
     2721            if ((lmodetype != REAL_LINEMODE) && 
     2722                    (lmodetype != KLUDGE_LINEMODE)) 
     2723# else 
     2724            if (his_state_is_wont(TELOPT_LINEMODE)) 
     2725# endif 
     2726#endif 
    14712727            { 
    14722728                init_termbuf(ncct); 
     
    14772733 
    14782734        case TELOPT_SGA: 
     2735#if     defined(LINEMODE) && defined(KLUDGELINEMODE) 
     2736                /* 
     2737                 * If kludge linemode is in use, then we 
     2738                 * must process an incoming do SGA for 
     2739                 * linemode purposes. 
     2740                 */ 
     2741            if ((lmodetype == KLUDGE_LINEMODE) || 
     2742                    (lmodetype == KLUDGE_OK)) { 
     2743                /* 
     2744                 * The client is asking us to turn 
     2745                 * linemode on. 
     2746                 */ 
     2747                lmodetype = KLUDGE_LINEMODE; 
     2748                clientstat(TELOPT_LINEMODE, WILL, 0); 
     2749                /* 
     2750                 * If we did not turn line mode on, 
     2751                 * then what do we say?  Will SGA? 
     2752                 * This violates design of telnet. 
     2753                 * Gross.  Very Gross. 
     2754                 */ 
     2755            } 
     2756            break; 
     2757#else 
    14792758            set_my_want_state_wont(option); 
    14802759            if (my_state_is_will(option)) 
     
    14842763                send_will(option, 1); 
    14852764            return; 
     2765#endif  /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 
    14862766 
    14872767        default: 
     
    15992879 
    16002880    }  /* end of case TELOPT_NAWS */ 
    1601  
     2881#ifdef  LINEMODE 
     2882    case TELOPT_LINEMODE: { 
     2883        int request; 
     2884 
     2885        if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ 
     2886                break; 
     2887        /* 
     2888         * Process linemode suboptions. 
     2889         */ 
     2890        if (SB_EOF()) 
     2891            break;              /* garbage was sent */ 
     2892        request = SB_GET();     /* get will/wont */ 
     2893 
     2894        if (SB_EOF()) 
     2895            break;              /* another garbage check */ 
     2896 
     2897        if (request == LM_SLC) {  /* SLC is not preceeded by WILL or WONT */ 
     2898                /* 
     2899                 * Process suboption buffer of slc's 
     2900                 */ 
     2901                start_slc(ncct, 1); 
     2902                do_opt_slc(ncct, subpointer, subend - subpointer); 
     2903                (void) end_slc(ncct, 0); 
     2904                break; 
     2905        } else if (request == LM_MODE) { 
     2906                if (SB_EOF()) 
     2907                    return; 
     2908                useeditmode = SB_GET();  /* get mode flag */ 
     2909                clientstat(ncct, LM_MODE, 0, 0); 
     2910                break; 
     2911        } 
     2912 
     2913        if (SB_EOF()) 
     2914            break; 
     2915        switch (SB_GET()) {  /* what suboption? */ 
     2916        case LM_FORWARDMASK: 
     2917                /* 
     2918                 * According to spec, only server can send request for 
     2919                 * forwardmask, and client can only return a positive response. 
     2920                 * So don't worry about it. 
     2921                 */ 
     2922 
     2923        default: 
     2924                break; 
     2925        } 
     2926        break; 
     2927    }  /* end of case TELOPT_LINEMODE */ 
     2928#endif 
    16022929    case TELOPT_STATUS: { 
    16032930        int mode; 
     
    19623289    } 
    19633290 
     3291#ifdef  LINEMODE 
     3292        if (his_want_state_is_will(TELOPT_LINEMODE)) { 
     3293                unsigned char *cp, *cpe; 
     3294                int len; 
     3295 
     3296                ADD(SB); 
     3297                ADD(TELOPT_LINEMODE); 
     3298                ADD(LM_MODE); 
     3299                ADD_DATA(editmode); 
     3300                ADD(SE); 
     3301 
     3302                ADD(SB); 
     3303                ADD(TELOPT_LINEMODE); 
     3304                ADD(LM_SLC); 
     3305                start_slc(ncct, 0); 
     3306                send_slc(ncct); 
     3307                len = end_slc(ncct, &cp); 
     3308                for (cpe = cp + len; cp < cpe; cp++) 
     3309                        ADD_DATA(*cp); 
     3310                ADD(SE); 
     3311        } 
     3312#endif  /* LINEMODE */ 
    19643313 
    19653314    ADD(IAC); 
  • src/noit_console_telnet.h

    r3070001 r46304a4  
    4444#include <arpa/telnet.h> 
    4545#include <sys/ioctl.h> 
     46#include <sys/ioctl_compat.h> 
     47#ifdef HAVE_TERMIOS_H 
     48#include <termios.h> 
     49#endif 
    4650#ifdef HAVE_TERM_H 
    4751#include <term.h> 
    48 #define USE_TERMIO 
    4952#endif 
    5053 
     
    156159  int            _flowmode; 
    157160  int            _restartany; 
     161  int            __terminit; 
     162  int            _linemode; 
     163  int            _uselinemode; 
     164  int            _alwayslinemode; 
     165  int            _editmode; 
     166  int            _useeditmode; 
     167  unsigned char *_def_slcbuf; 
     168  int            _def_slclen; 
     169  int            _slcchange;    /* change to slc is requested */ 
     170  unsigned char *_slcptr;       /* pointer into slc buffer */ 
     171  unsigned char  _slcbuf[NSLC*6];       /* buffer for slc negotiation */ 
     172 
    158173  int            _def_tspeed; /* This one */ 
    159174  int            _def_rspeed; /* and this one, need init to -1 */ 
     175#if     !defined(LINEMODE) || !defined(KLUDGELINEMODE) 
     176  int            _turn_on_sga; 
     177#endif 
    160178#ifdef TIOCSWINSZ 
    161179  int            _def_row;