Annotation of 43BSDReno/libexec/telnetd/termstat.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: static char sccsid[] = "@(#)termstat.c 5.6 (Berkeley) 6/28/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include "telnetd.h"
        !            25: 
        !            26: /*
        !            27:  * local variables
        !            28:  */
        !            29: #ifdef LINEMODE
        !            30: static int _terminit = 0;
        !            31: static int def_tspeed = -1, def_rspeed = -1;
        !            32: #ifdef TIOCSWINSZ
        !            33: static int def_row = 0, def_col = 0;
        !            34: #endif
        !            35: #endif LINEMODE
        !            36: 
        !            37: #if    defined(CRAY2) && defined(UNICOS5)
        !            38: int    newmap = 1;     /* nonzero if \n maps to ^M^J */
        !            39: #endif
        !            40: 
        !            41: #ifdef LINEMODE
        !            42: /*
        !            43:  * localstat
        !            44:  *
        !            45:  * This function handles all management of linemode.
        !            46:  *
        !            47:  * Linemode allows the client to do the local editing of data
        !            48:  * and send only complete lines to the server.  Linemode state is
        !            49:  * based on the state of the pty driver.  If the pty is set for
        !            50:  * external processing, then we can use linemode.  Further, if we
        !            51:  * can use real linemode, then we can look at the edit control bits
        !            52:  * in the pty to determine what editing the client should do.
        !            53:  *
        !            54:  * Linemode support uses the following state flags to keep track of
        !            55:  * current and desired linemode state.
        !            56:  *     alwayslinemode : true if -l was specified on the telnetd
        !            57:  *     command line.  It means to have linemode on as much as
        !            58:  *     possible.
        !            59:  *
        !            60:  *     lmodetype: signifies whether the client can
        !            61:  *     handle real linemode, or if use of kludgeomatic linemode
        !            62:  *     is preferred.  It will be set to one of the following:
        !            63:  *             REAL_LINEMODE : use linemode option
        !            64:  *             KLUDGE_LINEMODE : use kludge linemode
        !            65:  *             NO_LINEMODE : client is ignorant of linemode
        !            66:  *
        !            67:  *     linemode, uselinemode : linemode is true if linemode
        !            68:  *     is currently on, uselinemode is the state that we wish
        !            69:  *     to be in.  If another function wishes to turn linemode
        !            70:  *     on or off, it sets or clears uselinemode.
        !            71:  *
        !            72:  *     editmode, useeditmode : like linemode/uselinemode, but
        !            73:  *     these contain the edit mode states (edit and trapsig).
        !            74:  *
        !            75:  * The state variables correspond to some of the state information
        !            76:  * in the pty.
        !            77:  *     linemode:
        !            78:  *             In real linemode, this corresponds to whether the pty
        !            79:  *             expects external processing of incoming data.
        !            80:  *             In kludge linemode, this more closely corresponds to the
        !            81:  *             whether normal processing is on or not.  (ICANON in
        !            82:  *             system V, or COOKED mode in BSD.)
        !            83:  *             If the -l option was specified (alwayslinemode), then
        !            84:  *             an attempt is made to force external processing on at
        !            85:  *             all times.
        !            86:  *
        !            87:  * The following heuristics are applied to determine linemode
        !            88:  * handling within the server.
        !            89:  *     1) Early on in starting up the server, an attempt is made
        !            90:  *        to negotiate the linemode option.  If this succeeds
        !            91:  *        then lmodetype is set to REAL_LINEMODE and all linemode
        !            92:  *        processing occurs in the context of the linemode option.
        !            93:  *     2) If the attempt to negotiate the linemode option failed,
        !            94:  *        then we try to use kludge linemode.  We test for this
        !            95:  *        capability by sending "do Timing Mark".  If a positive
        !            96:  *        response comes back, then we assume that the client
        !            97:  *        understands kludge linemode (ech!) and the
        !            98:  *        lmodetype flag is set to KLUDGE_LINEMODE.
        !            99:  *     3) Otherwise, linemode is not supported at all and
        !           100:  *        lmodetype remains set to NO_LINEMODE (which happens
        !           101:  *        to be 0 for convenience).
        !           102:  *     4) At any time a command arrives that implies a higher
        !           103:  *        state of linemode support in the client, we move to that
        !           104:  *        linemode support.
        !           105:  *
        !           106:  * A short explanation of kludge linemode is in order here.
        !           107:  *     1) The heuristic to determine support for kludge linemode
        !           108:  *        is to send a do timing mark.  We assume that a client
        !           109:  *        that supports timing marks also supports kludge linemode.
        !           110:  *        A risky proposition at best.
        !           111:  *     2) Further negotiation of linemode is done by changing the
        !           112:  *        the server's state regarding SGA.  If server will SGA,
        !           113:  *        then linemode is off, if server won't SGA, then linemode
        !           114:  *        is on.
        !           115:  */
        !           116: localstat()
        !           117: {
        !           118:        void netflush();
        !           119: 
        !           120: #if    defined(CRAY2) && defined(UNICOS5)
        !           121:        /*
        !           122:         * Keep track of that ol' CR/NL mapping while we're in the
        !           123:         * neighborhood.
        !           124:         */
        !           125:        newmap = tty_isnewmap();
        !           126: #endif defined(CRAY2) && defined(UNICOS5)
        !           127: 
        !           128:        /*
        !           129:         * Check for state of BINARY options.
        !           130:         */
        !           131:        if (tty_isbinaryin()) {
        !           132:                if (his_want_state_is_wont(TELOPT_BINARY))
        !           133:                        send_do(TELOPT_BINARY, 1);
        !           134:        } else {
        !           135:                if (his_want_state_is_will(TELOPT_BINARY))
        !           136:                        send_dont(TELOPT_BINARY, 1);
        !           137:        }
        !           138: 
        !           139:        if (tty_isbinaryout()) {
        !           140:                if (my_want_state_is_wont(TELOPT_BINARY))
        !           141:                        send_will(TELOPT_BINARY, 1);
        !           142:        } else {
        !           143:                if (my_want_state_is_will(TELOPT_BINARY))
        !           144:                        send_wont(TELOPT_BINARY, 1);
        !           145:        }
        !           146: 
        !           147:        /*
        !           148:         * Check for changes to flow control if client supports it.
        !           149:         */
        !           150:        if (his_state_is_will(TELOPT_LFLOW)) {
        !           151:                if (tty_flowmode() != flowmode) {
        !           152:                        flowmode = tty_flowmode();
        !           153:                        (void) sprintf(nfrontp, "%c%c%c%c%c%c", IAC, SB,
        !           154:                                TELOPT_LFLOW, flowmode, IAC, SE);
        !           155:                        nfrontp += 6;
        !           156:                }
        !           157:        }
        !           158: 
        !           159:        /*
        !           160:         * Check linemode on/off state
        !           161:         */
        !           162:        uselinemode = tty_linemode();
        !           163: 
        !           164:        /*
        !           165:         * If alwayslinemode is on, and pty is changing to turn it off, then
        !           166:         * force linemode back on.
        !           167:         */
        !           168:        if (alwayslinemode && linemode && !uselinemode) {
        !           169:                uselinemode = 1;
        !           170:                tty_setlinemode(uselinemode);
        !           171:        }
        !           172: 
        !           173:        /*
        !           174:         * Do echo mode handling as soon as we know what the
        !           175:         * linemode is going to be.
        !           176:         * If the pty has echo turned off, then tell the client that
        !           177:         * the server will echo.  If echo is on, then the server
        !           178:         * will echo if in character mode, but in linemode the
        !           179:         * client should do local echoing.  The state machine will
        !           180:         * not send anything if it is unnecessary, so don't worry
        !           181:         * about that here.
        !           182:         */
        !           183:        if (tty_isecho() && uselinemode)
        !           184:                send_wont(TELOPT_ECHO, 1);
        !           185:        else
        !           186:                send_will(TELOPT_ECHO, 1);
        !           187: 
        !           188:        /*
        !           189:         * If linemode is being turned off, send appropriate
        !           190:         * command and then we're all done.
        !           191:         */
        !           192:         if (!uselinemode && linemode) {
        !           193: # ifdef        KLUDGELINEMODE
        !           194:                if (lmodetype == REAL_LINEMODE)
        !           195: # endif        /* KLUDGELINEMODE */
        !           196:                        send_dont(TELOPT_LINEMODE, 1);
        !           197: # ifdef        KLUDGELINEMODE
        !           198:                else if (lmodetype == KLUDGE_LINEMODE)
        !           199:                        send_will(TELOPT_SGA, 1);
        !           200: # endif        /* KLUDGELINEMODE */
        !           201:                linemode = uselinemode;
        !           202:                goto done;
        !           203:        }
        !           204: 
        !           205: # ifdef        KLUDGELINEMODE
        !           206:        /*
        !           207:         * If using real linemode check edit modes for possible later use.
        !           208:         * If we are in kludge linemode, do the SGA negotiation.
        !           209:         */
        !           210:        if (lmodetype == REAL_LINEMODE) {
        !           211: # endif        /* KLUDGELINEMODE */
        !           212:                useeditmode = 0;
        !           213:                if (tty_isediting())
        !           214:                        useeditmode |= MODE_EDIT;
        !           215:                if (tty_istrapsig())
        !           216:                        useeditmode |= MODE_TRAPSIG;
        !           217:                if (tty_issofttab())
        !           218:                        useeditmode |= MODE_SOFT_TAB;
        !           219:                if (tty_islitecho())
        !           220:                        useeditmode |= MODE_LIT_ECHO;
        !           221: # ifdef        KLUDGELINEMODE
        !           222:        } else if (lmodetype == KLUDGE_LINEMODE) {
        !           223:                if (tty_isediting() && uselinemode)
        !           224:                        send_wont(TELOPT_SGA, 1);
        !           225:                else
        !           226:                        send_will(TELOPT_SGA, 1);
        !           227:        }
        !           228: # endif        /* KLUDGELINEMODE */
        !           229: 
        !           230:        /*
        !           231:         * Negotiate linemode on if pty state has changed to turn it on.
        !           232:         * Send appropriate command and send along edit mode, then all done.
        !           233:         */
        !           234:        if (uselinemode && !linemode) {
        !           235: # ifdef        KLUDGELINEMODE
        !           236:                if (lmodetype == KLUDGE_LINEMODE) {
        !           237:                        send_wont(TELOPT_SGA, 1);
        !           238:                } else if (lmodetype == REAL_LINEMODE) {
        !           239: # endif        /* KLUDGELINEMODE */
        !           240:                        send_do(TELOPT_LINEMODE, 1);
        !           241:                        /* send along edit modes */
        !           242:                        (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
        !           243:                                TELOPT_LINEMODE, LM_MODE, useeditmode,
        !           244:                                IAC, SE);
        !           245:                        nfrontp += 7;
        !           246:                        editmode = useeditmode;
        !           247: # ifdef        KLUDGELINEMODE
        !           248:                }
        !           249: # endif        /* KLUDGELINEMODE */
        !           250:                linemode = uselinemode;
        !           251:                goto done;
        !           252:        }
        !           253: 
        !           254: # ifdef        KLUDGELINEMODE
        !           255:        /*
        !           256:         * None of what follows is of any value if not using
        !           257:         * real linemode.
        !           258:         */
        !           259:        if (lmodetype < REAL_LINEMODE)
        !           260:                goto done;
        !           261: # endif        /* KLUDGELINEMODE */
        !           262: 
        !           263:        if (linemode) {
        !           264:                /*
        !           265:                 * If edit mode changed, send edit mode.
        !           266:                 */
        !           267:                 if (useeditmode != editmode) {
        !           268:                        /*
        !           269:                         * Send along appropriate edit mode mask.
        !           270:                         */
        !           271:                        (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB,
        !           272:                                TELOPT_LINEMODE, LM_MODE, useeditmode,
        !           273:                                IAC, SE);
        !           274:                        nfrontp += 7;
        !           275:                        editmode = useeditmode;
        !           276:                }
        !           277:                                                        
        !           278: 
        !           279:                /*
        !           280:                 * Check for changes to special characters in use.
        !           281:                 */
        !           282:                start_slc(0);
        !           283:                check_slc();
        !           284:                end_slc(0);
        !           285:        }
        !           286: 
        !           287: done:
        !           288:        /*
        !           289:         * Some things should be deferred until after the pty state has
        !           290:         * been set by the local process.  Do those things that have been
        !           291:         * deferred now.  This only happens once.
        !           292:         */
        !           293:        if (_terminit == 0) {
        !           294:                _terminit = 1;
        !           295:                defer_terminit();
        !           296:        }
        !           297: 
        !           298:        netflush();
        !           299:        set_termbuf();
        !           300:        return;
        !           301: 
        !           302: }  /* end of localstat */
        !           303: #endif /* LINEMODE */
        !           304: 
        !           305: 
        !           306: /*
        !           307:  * clientstat
        !           308:  *
        !           309:  * Process linemode related requests from the client.
        !           310:  * Client can request a change to only one of linemode, editmode or slc's
        !           311:  * at a time, and if using kludge linemode, then only linemode may be
        !           312:  * affected.
        !           313:  */
        !           314: clientstat(code, parm1, parm2)
        !           315: register int code, parm1, parm2;
        !           316: {
        !           317:        void netflush();
        !           318: 
        !           319:        /*
        !           320:         * Get a copy of terminal characteristics.
        !           321:         */
        !           322:        init_termbuf();
        !           323: 
        !           324:        /*
        !           325:         * Process request from client. code tells what it is.
        !           326:         */
        !           327:        switch (code) {
        !           328: #ifdef LINEMODE
        !           329:        case TELOPT_LINEMODE:
        !           330:                /*
        !           331:                 * Don't do anything unless client is asking us to change
        !           332:                 * modes.
        !           333:                 */
        !           334:                uselinemode = (parm1 == WILL);
        !           335:                if (uselinemode != linemode) {
        !           336: # ifdef        KLUDGELINEMODE
        !           337:                        /*
        !           338:                         * If using kludge linemode, make sure that
        !           339:                         * we can do what the client asks.
        !           340:                         * We can not turn off linemode if alwayslinemode
        !           341:                         * and the ICANON bit is set.
        !           342:                         */
        !           343:                        if (lmodetype == KLUDGE_LINEMODE) {
        !           344:                                if (alwayslinemode && tty_isediting()) {
        !           345:                                        uselinemode = 1;
        !           346:                                }
        !           347:                        }
        !           348:                
        !           349:                        /*
        !           350:                         * Quit now if we can't do it.
        !           351:                         */
        !           352:                        if (uselinemode == linemode)
        !           353:                                return;
        !           354: 
        !           355:                        /*
        !           356:                         * If using real linemode and linemode is being
        !           357:                         * turned on, send along the edit mode mask.
        !           358:                         */
        !           359:                        if (lmodetype == REAL_LINEMODE && uselinemode)
        !           360: # else /* KLUDGELINEMODE */
        !           361:                        if (uselinemode)
        !           362: # endif        /* KLUDGELINEMODE */
        !           363:                        {
        !           364:                                useeditmode = 0;
        !           365:                                if (tty_isediting())
        !           366:                                        useeditmode |= MODE_EDIT;
        !           367:                                if (tty_istrapsig)
        !           368:                                        useeditmode |= MODE_TRAPSIG;
        !           369:                                if (tty_issofttab())
        !           370:                                        useeditmode |= MODE_SOFT_TAB;
        !           371:                                if (tty_islitecho())
        !           372:                                        useeditmode |= MODE_LIT_ECHO;
        !           373:                                (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
        !           374:                                        SB, TELOPT_LINEMODE, LM_MODE,
        !           375:                                                        useeditmode, IAC, SE);
        !           376:                                nfrontp += 7;
        !           377:                                editmode = useeditmode;
        !           378:                        }
        !           379: 
        !           380: 
        !           381:                        tty_setlinemode(uselinemode);
        !           382: 
        !           383:                        linemode = uselinemode;
        !           384: 
        !           385:                }
        !           386:                break;
        !           387:        
        !           388:        case LM_MODE:
        !           389:            {
        !           390:                register int ack, changed;
        !           391: 
        !           392:                /*
        !           393:                 * Client has sent along a mode mask.  If it agrees with
        !           394:                 * what we are currently doing, ignore it; if not, it could
        !           395:                 * be viewed as a request to change.  Note that the server
        !           396:                 * will change to the modes in an ack if it is different from
        !           397:                 * what we currently have, but we will not ack the ack.
        !           398:                 */
        !           399:                 useeditmode &= MODE_MASK;
        !           400:                 ack = (useeditmode & MODE_ACK);
        !           401:                 useeditmode &= ~MODE_ACK;
        !           402: 
        !           403:                 if (changed = (useeditmode ^ editmode)) {
        !           404:                        if (changed & MODE_EDIT)
        !           405:                                tty_setedit(useeditmode & MODE_EDIT);
        !           406: 
        !           407:                        if (changed & MODE_TRAPSIG)
        !           408:                                tty_setsig(useeditmode & MODE_TRAPSIG);
        !           409: 
        !           410:                        if (changed & MODE_SOFT_TAB)
        !           411:                                tty_setsofttab(useeditmode & MODE_SOFT_TAB);
        !           412: 
        !           413:                        if (changed & MODE_LIT_ECHO)
        !           414:                                tty_setlitecho(useeditmode & MODE_LIT_ECHO);
        !           415: 
        !           416:                        set_termbuf();
        !           417: 
        !           418:                        if (!ack) {
        !           419:                                (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC,
        !           420:                                        SB, TELOPT_LINEMODE, LM_MODE,
        !           421:                                        useeditmode|MODE_ACK,
        !           422:                                        IAC, SE);
        !           423:                                nfrontp += 7;
        !           424:                        }
        !           425:                
        !           426:                        editmode = useeditmode;
        !           427:                }
        !           428: 
        !           429:                break;
        !           430: 
        !           431:            }  /* end of case LM_MODE */
        !           432: #endif /* LINEMODE */
        !           433: 
        !           434:        case TELOPT_NAWS:
        !           435: #ifdef TIOCSWINSZ
        !           436:            {
        !           437:                struct winsize ws;
        !           438: 
        !           439: #ifdef LINEMODE
        !           440:                /*
        !           441:                 * Defer changing window size until after terminal is
        !           442:                 * initialized.
        !           443:                 */
        !           444:                if (terminit() == 0) {
        !           445:                        def_col = parm1;
        !           446:                        def_row = parm2;
        !           447:                        return;
        !           448:                }
        !           449: #endif /* LINEMODE */
        !           450: 
        !           451:                /*
        !           452:                 * Change window size as requested by client.
        !           453:                 */
        !           454: 
        !           455:                ws.ws_col = parm1;
        !           456:                ws.ws_row = parm2;
        !           457:                (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
        !           458:            }
        !           459: #endif /* TIOCSWINSZ */
        !           460:                
        !           461:                break;
        !           462:        
        !           463:        case TELOPT_TSPEED:
        !           464:            {
        !           465: #ifdef LINEMODE
        !           466:                /*
        !           467:                 * Defer changing the terminal speed.
        !           468:                 */
        !           469:                if (terminit() == 0) {
        !           470:                        def_tspeed = parm1;
        !           471:                        def_rspeed = parm2;
        !           472:                        return;
        !           473:                }
        !           474: #endif /* LINEMODE */
        !           475:                /*
        !           476:                 * Change terminal speed as requested by client.
        !           477:                 */
        !           478:                tty_tspeed(parm1);
        !           479:                tty_rspeed(parm2);
        !           480:                set_termbuf();
        !           481: 
        !           482:                break;
        !           483: 
        !           484:            }  /* end of case TELOPT_TSPEED */
        !           485: 
        !           486:        default:
        !           487:                /* What? */
        !           488:                break;
        !           489:        }  /* end of switch */
        !           490: 
        !           491: #if    defined(CRAY2) && defined(UNICOS5)
        !           492:        /*
        !           493:         * Just in case of the likely event that we changed the pty state.
        !           494:         */
        !           495:        rcv_ioctl();
        !           496: #endif /* defined(CRAY2) && defined(UNICOS5) */
        !           497: 
        !           498:        netflush();
        !           499: 
        !           500: }  /* end of clientstat */
        !           501: 
        !           502: #if    defined(CRAY2) && defined(UNICOS5)
        !           503: termstat()
        !           504: {
        !           505:        needtermstat = 1;
        !           506: }
        !           507: 
        !           508: _termstat()
        !           509: {
        !           510:        needtermstat = 0;
        !           511:        init_termbuf();
        !           512:        localstat();
        !           513:        rcv_ioctl();
        !           514: }
        !           515: #endif /* defined(CRAY2) && defined(UNICOS5) */
        !           516: 
        !           517: #ifdef LINEMODE
        !           518: /*
        !           519:  * defer_terminit
        !           520:  *
        !           521:  * Some things should not be done until after the login process has started
        !           522:  * and all the pty modes are set to what they are supposed to be.  This
        !           523:  * function is called when the pty state has been processed for the first time. 
        !           524:  * It calls other functions that do things that were deferred in each module.
        !           525:  */
        !           526: defer_terminit()
        !           527: {
        !           528: 
        !           529:        /*
        !           530:         * local stuff that got deferred.
        !           531:         */
        !           532:        if (def_tspeed != -1) {
        !           533:                clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed);
        !           534:                def_tspeed = def_rspeed = 0;
        !           535:        }
        !           536: 
        !           537: #ifdef TIOCSWINSZ
        !           538:        if (def_col || def_row) {
        !           539:                struct winsize ws;
        !           540: 
        !           541:                ws.ws_col = def_col;
        !           542:                ws.ws_row = def_row;
        !           543:                (void) ioctl(pty, TIOCSWINSZ, (char *)&ws);
        !           544:        }
        !           545: #endif
        !           546: 
        !           547:        /*
        !           548:         * The only other module that currently defers anything.
        !           549:         */
        !           550:        deferslc();
        !           551: 
        !           552: }  /* end of defer_terminit */
        !           553: 
        !           554: /*
        !           555:  * terminit
        !           556:  *
        !           557:  * Returns true if the pty state has been processed yet.
        !           558:  */
        !           559: int terminit()
        !           560: {
        !           561:        return _terminit;
        !           562: 
        !           563: }  /* end of terminit */
        !           564: #endif /* LINEMODE */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.