Annotation of 43BSDReno/libexec/telnetd/slc.c, revision 1.1.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.