Annotation of 43BSDReno/libexec/telnetd/slc.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[] = "@(#)slc.c      5.4 (Berkeley) 6/28/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include "telnetd.h"
        !            25: 
        !            26: #ifdef LINEMODE
        !            27: /*
        !            28:  * local varibles
        !            29:  */
        !            30: static unsigned char   *def_slcbuf = (unsigned char *)0;
        !            31: static int             def_slclen = 0;
        !            32: static int             slcchange;      /* change to slc is requested */
        !            33: static unsigned char   *slcptr;        /* pointer into slc buffer */
        !            34: static unsigned char   slcbuf[NSLC*6]; /* buffer for slc negotiation */
        !            35: 
        !            36: /*
        !            37:  * send_slc
        !            38:  *
        !            39:  * Write out the current special characters to the client.
        !            40:  */
        !            41: send_slc()
        !            42: {
        !            43:        register int i;
        !            44: 
        !            45:        /*
        !            46:         * Send out list of triplets of special characters
        !            47:         * to client.  We only send info on the characters
        !            48:         * that are currently supported.
        !            49:         */
        !            50:        for (i = 1; i <= NSLC; i++) {
        !            51:                if ((slctab[i].current.flag & SLC_LEVELBITS) != SLC_NOSUPPORT) {
        !            52:                        add_slc((unsigned char)i, slctab[i].current.flag,
        !            53:                                                        slctab[i].current.val);
        !            54:                }
        !            55:        }
        !            56: 
        !            57: }  /* end of send_slc */
        !            58: 
        !            59: /*
        !            60:  * default_slc
        !            61:  *
        !            62:  * Set pty special characters to all the defaults.
        !            63:  */
        !            64: default_slc()
        !            65: {
        !            66:        register int i;
        !            67: 
        !            68:        for (i = 1; i <= NSLC; i++) {
        !            69:                slctab[i].current.flag = slctab[i].defset.flag;
        !            70:                slctab[i].current.val = slctab[i].defset.val;
        !            71:                if (slctab[i].sptr) {
        !            72:                        *(slctab[i].sptr) = slctab[i].defset.val;
        !            73:                }
        !            74:        }
        !            75:        slcchange = 1;
        !            76: 
        !            77: }  /* end of default_slc */
        !            78: #endif LINEMODE
        !            79: 
        !            80: /*
        !            81:  * get_slc_defaults
        !            82:  *
        !            83:  * Initialize the slc mapping table.
        !            84:  */
        !            85: get_slc_defaults()
        !            86: {
        !            87:        register int i;
        !            88: 
        !            89:        init_termbuf();
        !            90: 
        !            91:        for (i = 1; i <= NSLC; i++) {
        !            92:                slctab[i].defset.flag = 
        !            93:                        spcset(i, &slctab[i].defset.val, &slctab[i].sptr);
        !            94:                slctab[i].current.flag = SLC_NOSUPPORT; 
        !            95:                slctab[i].current.val = 0; 
        !            96:        }
        !            97: 
        !            98: }  /* end of get_slc_defaults */
        !            99: 
        !           100: #ifdef LINEMODE
        !           101: /*
        !           102:  * add_slc
        !           103:  *
        !           104:  * Add an slc triplet to the slc buffer.
        !           105:  */
        !           106: add_slc(func, flag, val)
        !           107:        register unsigned char func, flag;
        !           108:        cc_t val;
        !           109: {
        !           110: 
        !           111:        if ((*slcptr++ = func) == 0xff)
        !           112:                *slcptr++ = 0xff;
        !           113: 
        !           114:        if ((*slcptr++ = flag) == 0xff)
        !           115:                *slcptr++ = 0xff;
        !           116: 
        !           117:        if ((*slcptr++ = (unsigned char)val) == 0xff)
        !           118:                *slcptr++ = 0xff;
        !           119: 
        !           120: }  /* end of add_slc */
        !           121: 
        !           122: /*
        !           123:  * start_slc
        !           124:  *
        !           125:  * Get ready to process incoming slc's and respond to them.
        !           126:  *
        !           127:  * The parameter getit is non-zero if it is necessary to grab a copy
        !           128:  * of the terminal control structures.
        !           129:  */
        !           130: start_slc(getit)
        !           131:        register int getit;
        !           132: {
        !           133: 
        !           134:        slcchange = 0;
        !           135:        if (getit)
        !           136:                init_termbuf();
        !           137:        (void) sprintf(slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC);
        !           138:        slcptr = slcbuf + 4;
        !           139: 
        !           140: }  /* end of start_slc */
        !           141: 
        !           142: /*
        !           143:  * end_slc
        !           144:  *
        !           145:  * Finish up the slc negotiation.  If something to send, then send it.
        !           146:  */
        !           147: end_slc(bufp)
        !           148: register unsigned char **bufp;
        !           149: {
        !           150:        register int len;
        !           151:        void netflush();
        !           152: 
        !           153:        /*
        !           154:         * If a change has occured, store the new terminal control
        !           155:         * structures back to the terminal driver.
        !           156:         */
        !           157:        if (slcchange) {
        !           158:                set_termbuf();
        !           159:        }
        !           160: 
        !           161:        /*
        !           162:         * If the pty state has not yet been fully processed and there is a
        !           163:         * deferred slc request from the client, then do not send any
        !           164:         * sort of slc negotiation now.  We will respond to the client's
        !           165:         * request very soon.
        !           166:         */
        !           167:        if (def_slcbuf && (terminit() == 0)) {
        !           168:                return;
        !           169:        }
        !           170: 
        !           171:        if (slcptr > (slcbuf + 4)) {
        !           172:                if (bufp) {
        !           173:                        *bufp = &slcbuf[4];
        !           174:                        return(slcptr - slcbuf - 4);
        !           175:                } else {
        !           176:                        (void) sprintf(slcptr, "%c%c", IAC, SE);
        !           177:                        slcptr += 2;
        !           178:                        len = slcptr - slcbuf;
        !           179:                        writenet(slcbuf, len);
        !           180:                        netflush();  /* force it out immediately */
        !           181:                }
        !           182:        }
        !           183: 
        !           184: }  /* end of end_slc */
        !           185: 
        !           186: /*
        !           187:  * process_slc
        !           188:  *
        !           189:  * Figure out what to do about the client's slc
        !           190:  */
        !           191: process_slc(func, flag, val)
        !           192:        register unsigned char func, flag;
        !           193:        cc_t val;
        !           194: {
        !           195:        register int hislevel, mylevel, ack;
        !           196: 
        !           197:        /*
        !           198:         * Ensure that we know something about this function
        !           199:         */
        !           200:        if (func > NSLC) {
        !           201:                add_slc(func, SLC_NOSUPPORT, 0);
        !           202:                return;
        !           203:        }
        !           204: 
        !           205:        /*
        !           206:         * Process the special case requests of 0 SLC_DEFAULT 0
        !           207:         * and 0 SLC_VARIABLE 0.  Be a little forgiving here, don't
        !           208:         * worry about whether the value is actually 0 or not.
        !           209:         */
        !           210:        if (func == 0) {
        !           211:                if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) {
        !           212:                        default_slc();
        !           213:                }
        !           214:                if (flag == SLC_DEFAULT || flag == SLC_VARIABLE) {
        !           215:                        send_slc();
        !           216:                }
        !           217:                return;
        !           218:        }
        !           219: 
        !           220:        /*
        !           221:         * Appears to be a function that we know something about.  So
        !           222:         * get on with it and see what we know.
        !           223:         */
        !           224: 
        !           225:        hislevel = flag & SLC_LEVELBITS;
        !           226:        mylevel = slctab[func].current.flag & SLC_LEVELBITS;
        !           227:        ack = flag & SLC_ACK;
        !           228:        /*
        !           229:         * ignore the command if:
        !           230:         * the function value and level are the same as what we already have;
        !           231:         * or the level is the same and the ack bit is set
        !           232:         */
        !           233:        if (hislevel == mylevel && (val == slctab[func].current.val || ack)) {
        !           234:                return;
        !           235:        } else {
        !           236:                change_slc(func, flag, val);
        !           237:        }
        !           238: 
        !           239: }  /* end of process_slc */
        !           240: 
        !           241: /*
        !           242:  * change_slc
        !           243:  *
        !           244:  * Process a request to change one of our special characters.
        !           245:  * Compare client's request with what we are capable of supporting.
        !           246:  */
        !           247: change_slc(func, flag, val)
        !           248:        register unsigned char func, flag;
        !           249:        cc_t val;
        !           250: {
        !           251:        register int hislevel, mylevel;
        !           252:        
        !           253:        hislevel = flag & SLC_LEVELBITS;
        !           254:        mylevel = slctab[func].defset.flag & SLC_LEVELBITS;
        !           255:        /*
        !           256:         * If client is setting a function to NOSUPPORT
        !           257:         * or DEFAULT, then we can easily and directly
        !           258:         * accomodate the request.
        !           259:         */
        !           260:        if (hislevel == SLC_NOSUPPORT) {
        !           261:                slctab[func].current.flag = flag;
        !           262:                slctab[func].current.val = val;
        !           263:                flag |= SLC_ACK;
        !           264:                add_slc(func, flag, val);
        !           265:                return;
        !           266:        }
        !           267:        if (hislevel == SLC_DEFAULT) {
        !           268:                /*
        !           269:                 * Special case here.  If client tells us to use
        !           270:                 * the default on a function we don't support, then
        !           271:                 * return NOSUPPORT instead of what we may have as a
        !           272:                 * default level of DEFAULT.
        !           273:                 */
        !           274:                if (mylevel == SLC_DEFAULT) {
        !           275:                        slctab[func].current.flag = SLC_NOSUPPORT;
        !           276:                } else {
        !           277:                        slctab[func].current.flag = slctab[func].defset.flag;
        !           278:                }
        !           279:                slctab[func].current.val = slctab[func].defset.val;
        !           280:                add_slc(func, slctab[func].current.flag,
        !           281:                                                slctab[func].current.val);
        !           282:                return;
        !           283:        }
        !           284: 
        !           285:        /*
        !           286:         * Client wants us to change to a new value or he
        !           287:         * is telling us that he can't change to our value.
        !           288:         * Some of the slc's we support and can change,
        !           289:         * some we do support but can't change,
        !           290:         * and others we don't support at all.
        !           291:         * If we can change it then we have a pointer to
        !           292:         * the place to put the new value, so change it,
        !           293:         * otherwise, continue the negotiation.
        !           294:         */
        !           295:        if (slctab[func].sptr) {
        !           296:                /*
        !           297:                 * We can change this one.
        !           298:                 */
        !           299:                slctab[func].current.val = val;
        !           300:                *(slctab[func].sptr) = val;
        !           301:                slctab[func].current.flag = flag;
        !           302:                flag |= SLC_ACK;
        !           303:                slcchange = 1;
        !           304:                add_slc(func, flag, val);
        !           305:        } else {
        !           306:                /*
        !           307:                * It is not possible for us to support this
        !           308:                * request as he asks.
        !           309:                *
        !           310:                * If our level is DEFAULT, then just ack whatever was
        !           311:                * sent. 
        !           312:                *
        !           313:                * If he can't change and we can't change,
        !           314:                * then degenerate to NOSUPPORT.
        !           315:                *
        !           316:                * Otherwise we send our level back to him, (CANTCHANGE
        !           317:                * or NOSUPPORT) and if CANTCHANGE, send
        !           318:                * our value as well.
        !           319:                */
        !           320:                if (mylevel == SLC_DEFAULT) {
        !           321:                        slctab[func].current.flag = flag;
        !           322:                        slctab[func].current.val = val;
        !           323:                        flag |= SLC_ACK;
        !           324:                } else if (hislevel == SLC_CANTCHANGE &&
        !           325:                                    mylevel == SLC_CANTCHANGE) {
        !           326:                        flag &= ~SLC_LEVELBITS;
        !           327:                        flag |= SLC_NOSUPPORT;
        !           328:                        slctab[func].current.flag = flag;
        !           329:                } else {
        !           330:                        flag &= ~SLC_LEVELBITS;
        !           331:                        flag |= mylevel;
        !           332:                        slctab[func].current.flag = flag;
        !           333:                        if (mylevel == SLC_CANTCHANGE) {
        !           334:                                slctab[func].current.val =
        !           335:                                        slctab[func].defset.val;
        !           336:                                val = slctab[func].current.val;
        !           337:                        }
        !           338:                        
        !           339:                }
        !           340:                add_slc(func, flag, val);
        !           341:        }
        !           342: 
        !           343: }  /* end of change_slc */
        !           344: 
        !           345: #if    defined(USE_TERMIO) && defined(SYSV_TERMIO)
        !           346: cc_t oldeofc = '\004';
        !           347: #endif
        !           348: 
        !           349: /*
        !           350:  * check_slc
        !           351:  *
        !           352:  * Check the special characters in use and notify the client if any have
        !           353:  * changed.  Only those characters that are capable of being changed are
        !           354:  * likely to have changed.  If a local change occurs, kick the support level
        !           355:  * and flags up to the defaults.
        !           356:  */
        !           357: check_slc()
        !           358: {
        !           359:        register int i;
        !           360: 
        !           361:        for (i = 1; i <= NSLC; i++) {
        !           362: #if    defined(USE_TERMIO) && defined(SYSV_TERMIO)
        !           363:                /*
        !           364:                 * In a perfect world this would be a neat little
        !           365:                 * function.  But in this world, we should not notify
        !           366:                 * client of changes to the VEOF char when
        !           367:                 * ICANON is off, because it is not representing
        !           368:                 * a special character.
        !           369:                 */
        !           370:                if (i == SLC_EOF) {
        !           371:                        if (!tty_isediting())
        !           372:                                continue;
        !           373:                        else if (slctab[i].sptr)
        !           374:                                oldeofc = *(slctab[i].sptr);
        !           375:                }
        !           376: #endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */
        !           377:                if (slctab[i].sptr &&
        !           378:                                (*(slctab[i].sptr) != slctab[i].current.val)) {
        !           379:                        slctab[i].current.val = *(slctab[i].sptr);
        !           380:                        slctab[i].current.flag = slctab[i].defset.flag;
        !           381:                        add_slc((unsigned char)i, slctab[i].current.flag,
        !           382:                                                slctab[i].current.val);
        !           383:                }
        !           384:        }
        !           385:                        
        !           386: }  /* check_slc */
        !           387: 
        !           388: /*
        !           389:  * do_opt_slc
        !           390:  *
        !           391:  * Process an slc option buffer.  Defer processing of incoming slc's
        !           392:  * until after the terminal state has been processed.  Save the first slc
        !           393:  * request that comes along, but discard all others.
        !           394:  *
        !           395:  * ptr points to the beginning of the buffer, len is the length.
        !           396:  */
        !           397: do_opt_slc(ptr, len)
        !           398: register char *ptr;
        !           399: register int len;
        !           400: {
        !           401:        register unsigned char func, flag;
        !           402:        cc_t val;
        !           403:        register char *end = (char *)(ptr + len);
        !           404:        char *malloc();
        !           405: 
        !           406:        if (terminit()) {  /* go ahead */
        !           407:                while (ptr < end) {
        !           408:                        func = *ptr++;
        !           409:                        if (ptr >= end) break;
        !           410:                        flag = *ptr++;
        !           411:                        if (ptr >= end) break;
        !           412:                        val = (cc_t)*ptr++;
        !           413: 
        !           414:                        process_slc(func, flag, val);
        !           415: 
        !           416:                }
        !           417:        } else {
        !           418:                /*
        !           419:                 * save this slc buffer if it is the first, otherwise dump
        !           420:                 * it.
        !           421:                 */
        !           422:                if (def_slcbuf == (unsigned char *)0) {
        !           423:                        def_slclen = len;
        !           424:                        def_slcbuf = (unsigned char *)malloc((unsigned)len);
        !           425:                        if (def_slcbuf == (unsigned char *)0)
        !           426:                                return;  /* too bad */
        !           427:                        bcopy(ptr, def_slcbuf, len);
        !           428:                }
        !           429:        }
        !           430: 
        !           431: }  /* end of do_opt_slc */
        !           432: 
        !           433: /*
        !           434:  * deferslc
        !           435:  *
        !           436:  * Do slc stuff that was deferred.
        !           437:  */
        !           438: deferslc()
        !           439: {
        !           440:        if (def_slcbuf) {
        !           441:                start_slc(1);
        !           442:                do_opt_slc(def_slcbuf, def_slclen);
        !           443:                end_slc(0);
        !           444:                free(def_slcbuf);
        !           445:                def_slcbuf = (unsigned char *)0;
        !           446:                def_slclen = 0;
        !           447:        }
        !           448: 
        !           449: }  /* end of deferslc */
        !           450: 
        !           451: #endif /* LINEMODE */

unix.superglobalmegacorp.com

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