[BACK]Return to telnet.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / telnet

Annotation of src/usr.bin/telnet/telnet.c, Revision 1.19

1.19    ! otto        1: /*     $OpenBSD: telnet.c,v 1.18 2003/11/08 19:17:29 jmc Exp $ */
1.2       niklas      2: /*     $NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $       */
                      3:
1.1       deraadt     4: /*
                      5:  * Copyright (c) 1988, 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.16      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
1.4       art        33: #include "telnet_locl.h"
1.9       millert    34: #include <curses.h>
                     35: #include <term.h>
1.1       deraadt    36:
1.4       art        37: #define        strip(x) (eight ? (x) : ((x) & 0x7f))
1.1       deraadt    38:
                     39: static unsigned char   subbuffer[SUBBUFSIZE],
                     40:                        *subpointer, *subend;    /* buffer for sub-options */
                     41: #define        SB_CLEAR()      subpointer = subbuffer;
                     42: #define        SB_TERM()       { subend = subpointer; SB_CLEAR(); }
                     43: #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
                     44:                                *subpointer++ = (c); \
                     45:                        }
                     46:
                     47: #define        SB_GET()        ((*subpointer++)&0xff)
                     48: #define        SB_PEEK()       ((*subpointer)&0xff)
                     49: #define        SB_EOF()        (subpointer >= subend)
                     50: #define        SB_LEN()        (subend - subpointer)
                     51:
                     52: char   options[256];           /* The combined options */
                     53: char   do_dont_resp[256];
                     54: char   will_wont_resp[256];
                     55:
                     56: int
1.4       art        57:        eight = 3,
                     58:        binary = 0,
1.1       deraadt    59:        autologin = 0,  /* Autologin anyone? */
                     60:        skiprc = 0,
                     61:        connected,
                     62:        showoptions,
                     63:        In3270,         /* Are we in 3270 mode? */
                     64:        ISend,          /* trying to send network data in */
                     65:        debug = 0,
                     66:        crmod,
                     67:        netdata,        /* Print out network data flow */
                     68:        crlf,           /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
                     69: #if    defined(TN3270)
                     70:        noasynchtty = 0,/* User specified "-noasynch" on command line */
                     71:        noasynchnet = 0,/* User specified "-noasynch" on command line */
                     72:        askedSGA = 0,   /* We have talked about suppress go ahead */
                     73: #endif /* defined(TN3270) */
                     74:        telnetport,
1.15      hin        75:        wantencryption = 0,
1.1       deraadt    76:        SYNCHing,       /* we are in TELNET SYNCH mode */
                     77:        flushout,       /* flush output */
                     78:        autoflush = 0,  /* flush output when interrupting? */
                     79:        autosynch,      /* send interrupt characters with SYNCH? */
                     80:        localflow,      /* we handle flow control locally */
                     81:        restartany,     /* if flow control enabled, restart on any character */
                     82:        localchars,     /* we recognize interrupt/quit */
                     83:        donelclchars,   /* the user has set "localchars" */
                     84:        donebinarytoggle,       /* the user has put us in binary */
                     85:        dontlecho,      /* do we suppress local echoing right now? */
                     86:        globalmode,
                     87:        clienteof = 0;
                     88:
                     89: char *prompt = 0;
                     90:
1.15      hin        91: int scheduler_lockout_tty = 0;
                     92:
1.1       deraadt    93: cc_t escape;
                     94: cc_t rlogin;
                     95: #ifdef KLUDGELINEMODE
                     96: cc_t echoc;
                     97: #endif
                     98:
                     99: /*
                    100:  * Telnet receiver states for fsm
                    101:  */
                    102: #define        TS_DATA         0
                    103: #define        TS_IAC          1
                    104: #define        TS_WILL         2
                    105: #define        TS_WONT         3
                    106: #define        TS_DO           4
                    107: #define        TS_DONT         5
                    108: #define        TS_CR           6
                    109: #define        TS_SB           7               /* sub-option collection */
                    110: #define        TS_SE           8               /* looking for sub-option end */
                    111:
                    112: static int     telrcv_state;
                    113: #ifdef OLD_ENVIRON
                    114: unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
                    115: #else
                    116: # define telopt_environ TELOPT_NEW_ENVIRON
                    117: #endif
                    118:
                    119: jmp_buf        toplevel = { 0 };
                    120: jmp_buf        peerdied;
                    121:
                    122: int    flushline;
                    123: int    linemode;
                    124:
                    125: #ifdef KLUDGELINEMODE
                    126: int    kludgelinemode = 1;
                    127: #endif
                    128:
                    129: /*
                    130:  * The following are some clocks used to decide how to interpret
                    131:  * the relationship between various variables.
                    132:  */
                    133:
                    134: Clocks clocks;
                    135:
                    136: 
                    137: /*
                    138:  * Initialize telnet environment.
                    139:  */
                    140:
                    141:     void
                    142: init_telnet()
                    143: {
                    144:     env_init();
                    145:
                    146:     SB_CLEAR();
1.4       art       147:     memset((char *)options, 0, sizeof options);
1.1       deraadt   148:
                    149:     connected = In3270 = ISend = localflow = donebinarytoggle = 0;
1.4       art       150: #if    defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1       deraadt   151:     auth_encrypt_connect(connected);
1.4       art       152: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1       deraadt   153:     restartany = -1;
                    154:
                    155:     SYNCHing = 0;
                    156:
                    157:     /* Don't change NetTrace */
                    158:
                    159:     escape = CONTROL(']');
                    160:     rlogin = _POSIX_VDISABLE;
                    161: #ifdef KLUDGELINEMODE
                    162:     echoc = CONTROL('E');
                    163: #endif
                    164:
                    165:     flushline = 1;
                    166:     telrcv_state = TS_DATA;
                    167: }
                    168: 
                    169:
                    170: /*
                    171:  * These routines are in charge of sending option negotiations
                    172:  * to the other side.
                    173:  *
                    174:  * The basic idea is that we send the negotiation if either side
                    175:  * is in disagreement as to what the current state should be.
                    176:  */
                    177:
                    178:     void
                    179: send_do(c, init)
1.13      mpech     180:     int c, init;
1.1       deraadt   181: {
                    182:     if (init) {
                    183:        if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
                    184:                                my_want_state_is_do(c))
                    185:            return;
                    186:        set_my_want_state_do(c);
                    187:        do_dont_resp[c]++;
                    188:     }
                    189:     NET2ADD(IAC, DO);
                    190:     NETADD(c);
1.12      hin       191:     printoption("SENT",DO, c);
1.1       deraadt   192: }
                    193:
                    194:     void
                    195: send_dont(c, init)
1.13      mpech     196:     int c, init;
1.1       deraadt   197: {
                    198:     if (init) {
                    199:        if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
                    200:                                my_want_state_is_dont(c))
                    201:            return;
                    202:        set_my_want_state_dont(c);
                    203:        do_dont_resp[c]++;
                    204:     }
                    205:     NET2ADD(IAC, DONT);
                    206:     NETADD(c);
                    207:     printoption("SENT", DONT, c);
                    208: }
                    209:
                    210:     void
                    211: send_will(c, init)
1.13      mpech     212:     int c, init;
1.1       deraadt   213: {
                    214:     if (init) {
                    215:        if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
                    216:                                my_want_state_is_will(c))
                    217:            return;
                    218:        set_my_want_state_will(c);
                    219:        will_wont_resp[c]++;
                    220:     }
                    221:     NET2ADD(IAC, WILL);
                    222:     NETADD(c);
                    223:     printoption("SENT", WILL, c);
                    224: }
                    225:
                    226:     void
                    227: send_wont(c, init)
1.13      mpech     228:     int c, init;
1.1       deraadt   229: {
                    230:     if (init) {
                    231:        if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
                    232:                                my_want_state_is_wont(c))
                    233:            return;
                    234:        set_my_want_state_wont(c);
                    235:        will_wont_resp[c]++;
                    236:     }
                    237:     NET2ADD(IAC, WONT);
                    238:     NETADD(c);
                    239:     printoption("SENT", WONT, c);
                    240: }
                    241:
                    242:
                    243:        void
                    244: willoption(option)
                    245:        int option;
                    246: {
                    247:        int new_state_ok = 0;
                    248:
                    249:        if (do_dont_resp[option]) {
                    250:            --do_dont_resp[option];
                    251:            if (do_dont_resp[option] && my_state_is_do(option))
                    252:                --do_dont_resp[option];
                    253:        }
                    254:
                    255:        if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
                    256:
                    257:            switch (option) {
                    258:
                    259:            case TELOPT_ECHO:
                    260: #          if defined(TN3270)
                    261:                /*
                    262:                 * The following is a pain in the rear-end.
                    263:                 * Various IBM servers (some versions of Wiscnet,
                    264:                 * possibly Fibronics/Spartacus, and who knows who
                    265:                 * else) will NOT allow us to send "DO SGA" too early
                    266:                 * in the setup proceedings.  On the other hand,
                    267:                 * 4.2 servers (telnetd) won't set SGA correctly.
                    268:                 * So, we are stuck.  Empirically (but, based on
                    269:                 * a VERY small sample), the IBM servers don't send
                    270:                 * out anything about ECHO, so we postpone our sending
                    271:                 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
                    272:                 * DO send).
                    273:                  */
                    274:                {
                    275:                    if (askedSGA == 0) {
                    276:                        askedSGA = 1;
                    277:                        if (my_want_state_is_dont(TELOPT_SGA))
                    278:                            send_do(TELOPT_SGA, 1);
                    279:                    }
                    280:                }
                    281:                    /* Fall through */
                    282:            case TELOPT_EOR:
                    283: #endif     /* defined(TN3270) */
                    284:            case TELOPT_BINARY:
                    285:            case TELOPT_SGA:
                    286:                settimer(modenegotiated);
                    287:                /* FALL THROUGH */
                    288:            case TELOPT_STATUS:
                    289: #if    defined(AUTHENTICATION)
                    290:            case TELOPT_AUTHENTICATION:
                    291: #endif
1.4       art       292: #if    defined(ENCRYPTION)
                    293:            case TELOPT_ENCRYPT:
                    294: #endif
1.1       deraadt   295:                new_state_ok = 1;
                    296:                break;
                    297:
                    298:            case TELOPT_TM:
                    299:                if (flushout)
                    300:                    flushout = 0;
                    301:                /*
                    302:                 * Special case for TM.  If we get back a WILL,
                    303:                 * pretend we got back a WONT.
                    304:                 */
                    305:                set_my_want_state_dont(option);
                    306:                set_my_state_dont(option);
                    307:                return;                 /* Never reply to TM will's/wont's */
                    308:
                    309:            case TELOPT_LINEMODE:
                    310:            default:
                    311:                break;
                    312:            }
                    313:
                    314:            if (new_state_ok) {
                    315:                set_my_want_state_do(option);
                    316:                send_do(option, 0);
                    317:                setconnmode(0);         /* possibly set new tty mode */
                    318:            } else {
                    319:                do_dont_resp[option]++;
                    320:                send_dont(option, 0);
                    321:            }
                    322:        }
                    323:        set_my_state_do(option);
1.4       art       324: #if    defined(ENCRYPTION)
                    325:        if (option == TELOPT_ENCRYPT)
                    326:                encrypt_send_support();
                    327: #endif
                    328:
1.1       deraadt   329: }
                    330:
                    331:        void
                    332: wontoption(option)
                    333:        int option;
                    334: {
                    335:        if (do_dont_resp[option]) {
                    336:            --do_dont_resp[option];
                    337:            if (do_dont_resp[option] && my_state_is_dont(option))
                    338:                --do_dont_resp[option];
                    339:        }
                    340:
                    341:        if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
                    342:
                    343:            switch (option) {
                    344:
                    345: #ifdef KLUDGELINEMODE
                    346:            case TELOPT_SGA:
                    347:                if (!kludgelinemode)
                    348:                    break;
                    349:                /* FALL THROUGH */
                    350: #endif
                    351:            case TELOPT_ECHO:
                    352:                settimer(modenegotiated);
                    353:                break;
                    354:
                    355:            case TELOPT_TM:
                    356:                if (flushout)
                    357:                    flushout = 0;
                    358:                set_my_want_state_dont(option);
                    359:                set_my_state_dont(option);
                    360:                return;         /* Never reply to TM will's/wont's */
                    361:
1.4       art       362: #ifdef ENCRYPTION
                    363:            case TELOPT_ENCRYPT:
                    364:                encrypt_not();
                    365:                break;
                    366: #endif
1.1       deraadt   367:            default:
                    368:                break;
                    369:            }
                    370:            set_my_want_state_dont(option);
                    371:            if (my_state_is_do(option))
                    372:                send_dont(option, 0);
                    373:            setconnmode(0);                     /* Set new tty mode */
                    374:        } else if (option == TELOPT_TM) {
                    375:            /*
                    376:             * Special case for TM.
                    377:             */
                    378:            if (flushout)
                    379:                flushout = 0;
                    380:            set_my_want_state_dont(option);
                    381:        }
                    382:        set_my_state_dont(option);
                    383: }
                    384:
                    385:        static void
                    386: dooption(option)
                    387:        int option;
                    388: {
                    389:        int new_state_ok = 0;
                    390:
                    391:        if (will_wont_resp[option]) {
                    392:            --will_wont_resp[option];
                    393:            if (will_wont_resp[option] && my_state_is_will(option))
                    394:                --will_wont_resp[option];
                    395:        }
                    396:
                    397:        if (will_wont_resp[option] == 0) {
                    398:          if (my_want_state_is_wont(option)) {
                    399:
                    400:            switch (option) {
                    401:
                    402:            case TELOPT_TM:
                    403:                /*
                    404:                 * Special case for TM.  We send a WILL, but pretend
                    405:                 * we sent WONT.
                    406:                 */
                    407:                send_will(option, 0);
                    408:                set_my_want_state_wont(TELOPT_TM);
                    409:                set_my_state_wont(TELOPT_TM);
                    410:                return;
                    411:
                    412: #      if defined(TN3270)
                    413:            case TELOPT_EOR:            /* end of record */
                    414: #      endif   /* defined(TN3270) */
                    415:            case TELOPT_BINARY:         /* binary mode */
                    416:            case TELOPT_NAWS:           /* window size */
                    417:            case TELOPT_TSPEED:         /* terminal speed */
                    418:            case TELOPT_LFLOW:          /* local flow control */
                    419:            case TELOPT_TTYPE:          /* terminal type option */
                    420:            case TELOPT_SGA:            /* no big deal */
1.4       art       421: #if    defined(ENCRYPTION)
                    422:            case TELOPT_ENCRYPT:        /* encryption variable option */
                    423: #endif
1.1       deraadt   424:                new_state_ok = 1;
                    425:                break;
                    426:
                    427:            case TELOPT_NEW_ENVIRON:    /* New environment variable option */
                    428: #ifdef OLD_ENVIRON
                    429:                if (my_state_is_will(TELOPT_OLD_ENVIRON))
                    430:                        send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
                    431:                goto env_common;
                    432:            case TELOPT_OLD_ENVIRON:    /* Old environment variable option */
                    433:                if (my_state_is_will(TELOPT_NEW_ENVIRON))
                    434:                        break;          /* Don't enable if new one is in use! */
                    435:            env_common:
                    436:                telopt_environ = option;
                    437: #endif
                    438:                new_state_ok = 1;
                    439:                break;
                    440:
                    441: #if    defined(AUTHENTICATION)
                    442:            case TELOPT_AUTHENTICATION:
                    443:                if (autologin)
                    444:                        new_state_ok = 1;
                    445:                break;
                    446: #endif
                    447:
                    448:            case TELOPT_XDISPLOC:       /* X Display location */
1.19    ! otto      449:                if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1       deraadt   450:                    new_state_ok = 1;
                    451:                break;
                    452:
                    453:            case TELOPT_LINEMODE:
                    454: #ifdef KLUDGELINEMODE
                    455:                kludgelinemode = 0;
                    456:                send_do(TELOPT_SGA, 1);
                    457: #endif
                    458:                set_my_want_state_will(TELOPT_LINEMODE);
                    459:                send_will(option, 0);
                    460:                set_my_state_will(TELOPT_LINEMODE);
                    461:                slc_init();
                    462:                return;
                    463:
                    464:            case TELOPT_ECHO:           /* We're never going to echo... */
                    465:            default:
                    466:                break;
                    467:            }
                    468:
                    469:            if (new_state_ok) {
                    470:                set_my_want_state_will(option);
                    471:                send_will(option, 0);
                    472:                setconnmode(0);                 /* Set new tty mode */
                    473:            } else {
                    474:                will_wont_resp[option]++;
                    475:                send_wont(option, 0);
                    476:            }
                    477:          } else {
                    478:            /*
                    479:             * Handle options that need more things done after the
                    480:             * other side has acknowledged the option.
                    481:             */
                    482:            switch (option) {
                    483:            case TELOPT_LINEMODE:
                    484: #ifdef KLUDGELINEMODE
                    485:                kludgelinemode = 0;
                    486:                send_do(TELOPT_SGA, 1);
                    487: #endif
                    488:                set_my_state_will(option);
                    489:                slc_init();
                    490:                send_do(TELOPT_SGA, 0);
                    491:                return;
                    492:            }
                    493:          }
                    494:        }
                    495:        set_my_state_will(option);
                    496: }
                    497:
                    498:        static void
                    499: dontoption(option)
                    500:        int option;
                    501: {
                    502:
                    503:        if (will_wont_resp[option]) {
                    504:            --will_wont_resp[option];
                    505:            if (will_wont_resp[option] && my_state_is_wont(option))
                    506:                --will_wont_resp[option];
                    507:        }
                    508:
                    509:        if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
                    510:            switch (option) {
                    511:            case TELOPT_LINEMODE:
                    512:                linemode = 0;   /* put us back to the default state */
                    513:                break;
                    514: #ifdef OLD_ENVIRON
                    515:            case TELOPT_NEW_ENVIRON:
                    516:                /*
                    517:                 * The new environ option wasn't recognized, try
                    518:                 * the old one.
                    519:                 */
                    520:                send_will(TELOPT_OLD_ENVIRON, 1);
                    521:                telopt_environ = TELOPT_OLD_ENVIRON;
                    522:                break;
                    523: #endif
                    524:            }
                    525:            /* we always accept a DONT */
                    526:            set_my_want_state_wont(option);
                    527:            if (my_state_is_will(option))
                    528:                send_wont(option, 0);
                    529:            setconnmode(0);                     /* Set new tty mode */
                    530:        }
                    531:        set_my_state_wont(option);
                    532: }
                    533:
                    534: /*
1.11      provos    535:  * This routine will turn a pipe separated list of names in the buffer
1.9       millert   536:  * into an array of pointers to NUL terminated names.  We toss out any
                    537:  * bad, duplicate, or verbose names (names with spaces).
1.1       deraadt   538:  */
                    539:
1.14      millert   540: int is_unique(char *, char **, char **);
1.5       art       541:
1.1       deraadt   542: static char *name_unknown = "UNKNOWN";
                    543: static char *unknown[] = { 0, 0 };
                    544:
                    545:        char **
                    546: mklist(buf, name)
                    547:        char *buf, *name;
                    548: {
1.13      mpech     549:        int n;
                    550:        char c, *cp, **argvp, *cp2, **argv, **avt;
1.1       deraadt   551:
                    552:        if (name) {
1.2       niklas    553:                if ((int)strlen(name) > 40) {
1.1       deraadt   554:                        name = 0;
                    555:                        unknown[0] = name_unknown;
                    556:                } else {
                    557:                        unknown[0] = name;
                    558:                        upcase(name);
                    559:                }
                    560:        } else
                    561:                unknown[0] = name_unknown;
                    562:        /*
                    563:         * Count up the number of names.
                    564:         */
1.9       millert   565:        for (n = 1, cp = buf; *cp; cp++) {
1.1       deraadt   566:                if (*cp == '|')
                    567:                        n++;
                    568:        }
                    569:        /*
                    570:         * Allocate an array to put the name pointers into
                    571:         */
                    572:        argv = (char **)malloc((n+3)*sizeof(char *));
                    573:        if (argv == 0)
                    574:                return(unknown);
                    575:
                    576:        /*
                    577:         * Fill up the array of pointers to names.
                    578:         */
                    579:        *argv = 0;
                    580:        argvp = argv+1;
                    581:        n = 0;
                    582:        for (cp = cp2 = buf; (c = *cp);  cp++) {
                    583:                if (c == '|' || c == ':') {
                    584:                        *cp++ = '\0';
                    585:                        /*
                    586:                         * Skip entries that have spaces or are over 40
                    587:                         * characters long.  If this is our environment
                    588:                         * name, then put it up front.  Otherwise, as
                    589:                         * long as this is not a duplicate name (case
                    590:                         * insensitive) add it to the list.
                    591:                         */
                    592:                        if (n || (cp - cp2 > 41))
                    593:                                ;
                    594:                        else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
                    595:                                *argv = cp2;
                    596:                        else if (is_unique(cp2, argv+1, argvp))
                    597:                                *argvp++ = cp2;
                    598:                        if (c == ':')
                    599:                                break;
                    600:                        /*
                    601:                         * Skip multiple delimiters. Reset cp2 to
                    602:                         * the beginning of the next name. Reset n,
                    603:                         * the flag for names with spaces.
                    604:                         */
                    605:                        while ((c = *cp) == '|')
                    606:                                cp++;
                    607:                        cp2 = cp;
                    608:                        n = 0;
                    609:                }
                    610:                /*
                    611:                 * Skip entries with spaces or non-ascii values.
                    612:                 * Convert lower case letters to upper case.
                    613:                 */
1.4       art       614: #define ISASCII(c) (!((c)&0x80))
                    615:                if ((c == ' ') || !ISASCII(c))
1.1       deraadt   616:                        n = 1;
                    617:                else if (islower(c))
                    618:                        *cp = toupper(c);
                    619:        }
1.2       niklas    620:
1.1       deraadt   621:        /*
                    622:         * Check for an old V6 2 character name.  If the second
                    623:         * name points to the beginning of the buffer, and is
                    624:         * only 2 characters long, move it to the end of the array.
                    625:         */
                    626:        if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
                    627:                --argvp;
                    628:                for (avt = &argv[1]; avt < argvp; avt++)
                    629:                        *avt = *(avt+1);
                    630:                *argvp++ = buf;
                    631:        }
                    632:
                    633:        /*
                    634:         * Duplicate last name, for TTYPE option, and null
                    635:         * terminate the array.  If we didn't find a match on
                    636:         * our terminal name, put that name at the beginning.
                    637:         */
                    638:        cp = *(argvp-1);
                    639:        *argvp++ = cp;
                    640:        *argvp = 0;
                    641:
                    642:        if (*argv == 0) {
                    643:                if (name)
                    644:                        *argv = name;
                    645:                else {
                    646:                        --argvp;
                    647:                        for (avt = argv; avt < argvp; avt++)
                    648:                                *avt = *(avt+1);
                    649:                }
                    650:        }
                    651:        if (*argv)
                    652:                return(argv);
                    653:        else
                    654:                return(unknown);
                    655: }
                    656:
                    657:        int
                    658: is_unique(name, as, ae)
1.13      mpech     659:        char *name, **as, **ae;
1.1       deraadt   660: {
1.13      mpech     661:        char **ap;
                    662:        int n;
1.1       deraadt   663:
                    664:        n = strlen(name) + 1;
                    665:        for (ap = as; ap < ae; ap++)
                    666:                if (strncasecmp(*ap, name, n) == 0)
                    667:                        return(0);
                    668:        return (1);
                    669: }
                    670:
                    671: int resettermname = 1;
                    672:
                    673:        char *
                    674: gettermname()
                    675: {
                    676:        char *tname;
                    677:        static char **tnamep = 0;
                    678:        static char **next;
1.10      millert   679:        int errret;
1.1       deraadt   680:
                    681:        if (resettermname) {
                    682:                resettermname = 0;
                    683:                if (tnamep && tnamep != unknown)
                    684:                        free(tnamep);
1.19    ! otto      685:                if ((tname = (char *)env_getvalue((unsigned char *)"TERM", 0)) &&
1.10      millert   686:                                (setupterm(tname, 1, &errret) == OK)) {
1.9       millert   687:                        tnamep = mklist(ttytype, tname);
1.1       deraadt   688:                } else {
1.2       niklas    689:                        if (tname && ((int)strlen(tname) <= 40)) {
1.1       deraadt   690:                                unknown[0] = tname;
                    691:                                upcase(tname);
                    692:                        } else
                    693:                                unknown[0] = name_unknown;
                    694:                        tnamep = unknown;
                    695:                }
                    696:                next = tnamep;
                    697:        }
                    698:        if (*next == 0)
                    699:                next = tnamep;
                    700:        return(*next++);
                    701: }
                    702: /*
                    703:  * suboption()
                    704:  *
                    705:  *     Look at the sub-option buffer, and try to be helpful to the other
                    706:  * side.
                    707:  *
                    708:  *     Currently we recognize:
                    709:  *
                    710:  *             Terminal type, send request.
                    711:  *             Terminal speed (send request).
                    712:  *             Local flow control (is request).
                    713:  *             Linemode
                    714:  */
                    715:
                    716:     static void
                    717: suboption()
                    718: {
                    719:     unsigned char subchar;
                    720:
                    721:     printsub('<', subbuffer, SB_LEN()+2);
                    722:     switch (subchar = SB_GET()) {
                    723:     case TELOPT_TTYPE:
                    724:        if (my_want_state_is_wont(TELOPT_TTYPE))
                    725:            return;
                    726:        if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
                    727:            return;
                    728:        } else {
                    729:            char *name;
                    730:            unsigned char temp[50];
                    731:            int len;
                    732:
                    733: #if    defined(TN3270)
                    734:            if (tn3270_ttype()) {
                    735:                return;
                    736:            }
                    737: #endif /* defined(TN3270) */
                    738:            name = gettermname();
                    739:            len = strlen(name) + 4 + 2;
                    740:            if (len < NETROOM()) {
1.4       art       741:                snprintf((char *)temp, sizeof(temp),
                    742:                         "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
                    743:                         TELQUAL_IS, name, IAC, SE);
1.1       deraadt   744:                ring_supply_data(&netoring, temp, len);
                    745:                printsub('>', &temp[2], len-2);
                    746:            } else {
                    747:                ExitString("No room in buffer for terminal type.\n", 1);
                    748:                /*NOTREACHED*/
                    749:            }
                    750:        }
                    751:        break;
                    752:     case TELOPT_TSPEED:
                    753:        if (my_want_state_is_wont(TELOPT_TSPEED))
                    754:            return;
                    755:        if (SB_EOF())
                    756:            return;
                    757:        if (SB_GET() == TELQUAL_SEND) {
                    758:            long ospeed, ispeed;
                    759:            unsigned char temp[50];
                    760:            int len;
                    761:
                    762:            TerminalSpeeds(&ispeed, &ospeed);
                    763:
1.4       art       764:            snprintf((char *)temp, sizeof(temp),
1.5       art       765:                     "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
1.4       art       766:                     TELQUAL_IS, ospeed, ispeed, IAC, SE);
1.1       deraadt   767:            len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
                    768:
                    769:            if (len < NETROOM()) {
                    770:                ring_supply_data(&netoring, temp, len);
                    771:                printsub('>', temp+2, len - 2);
                    772:            }
                    773: /*@*/      else printf("lm_will: not enough room in buffer\n");
                    774:        }
                    775:        break;
                    776:     case TELOPT_LFLOW:
                    777:        if (my_want_state_is_wont(TELOPT_LFLOW))
                    778:            return;
                    779:        if (SB_EOF())
                    780:            return;
                    781:        switch(SB_GET()) {
                    782:        case LFLOW_RESTART_ANY:
                    783:            restartany = 1;
                    784:            break;
                    785:        case LFLOW_RESTART_XON:
                    786:            restartany = 0;
                    787:            break;
                    788:        case LFLOW_ON:
                    789:            localflow = 1;
                    790:            break;
                    791:        case LFLOW_OFF:
                    792:            localflow = 0;
                    793:            break;
                    794:        default:
                    795:            return;
                    796:        }
                    797:        setcommandmode();
                    798:        setconnmode(0);
                    799:        break;
                    800:
                    801:     case TELOPT_LINEMODE:
                    802:        if (my_want_state_is_wont(TELOPT_LINEMODE))
                    803:            return;
                    804:        if (SB_EOF())
                    805:            return;
                    806:        switch (SB_GET()) {
                    807:        case WILL:
                    808:            lm_will(subpointer, SB_LEN());
                    809:            break;
                    810:        case WONT:
                    811:            lm_wont(subpointer, SB_LEN());
                    812:            break;
                    813:        case DO:
                    814:            lm_do(subpointer, SB_LEN());
                    815:            break;
                    816:        case DONT:
                    817:            lm_dont(subpointer, SB_LEN());
                    818:            break;
                    819:        case LM_SLC:
                    820:            slc(subpointer, SB_LEN());
                    821:            break;
                    822:        case LM_MODE:
                    823:            lm_mode(subpointer, SB_LEN(), 0);
                    824:            break;
                    825:        default:
                    826:            break;
                    827:        }
                    828:        break;
                    829:
                    830: #ifdef OLD_ENVIRON
                    831:     case TELOPT_OLD_ENVIRON:
                    832: #endif
                    833:     case TELOPT_NEW_ENVIRON:
                    834:        if (SB_EOF())
                    835:            return;
                    836:        switch(SB_PEEK()) {
                    837:        case TELQUAL_IS:
                    838:        case TELQUAL_INFO:
                    839:            if (my_want_state_is_dont(subchar))
                    840:                return;
                    841:            break;
                    842:        case TELQUAL_SEND:
                    843:            if (my_want_state_is_wont(subchar)) {
                    844:                return;
                    845:            }
                    846:            break;
                    847:        default:
                    848:            return;
                    849:        }
                    850:        env_opt(subpointer, SB_LEN());
                    851:        break;
                    852:
                    853:     case TELOPT_XDISPLOC:
                    854:        if (my_want_state_is_wont(TELOPT_XDISPLOC))
                    855:            return;
                    856:        if (SB_EOF())
                    857:            return;
                    858:        if (SB_GET() == TELQUAL_SEND) {
                    859:            unsigned char temp[50], *dp;
                    860:            int len;
                    861:
1.19    ! otto      862:            if ((dp = env_getvalue((unsigned char *)"DISPLAY", 0)) == NULL) {
1.1       deraadt   863:                /*
                    864:                 * Something happened, we no longer have a DISPLAY
                    865:                 * variable.  So, turn off the option.
                    866:                 */
                    867:                send_wont(TELOPT_XDISPLOC, 1);
                    868:                break;
                    869:            }
1.4       art       870:            snprintf((char *)temp, sizeof(temp),
                    871:                    "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
1.1       deraadt   872:                    TELQUAL_IS, dp, IAC, SE);
                    873:            len = strlen((char *)temp+4) + 4;   /* temp[3] is 0 ... */
                    874:
                    875:            if (len < NETROOM()) {
                    876:                ring_supply_data(&netoring, temp, len);
                    877:                printsub('>', temp+2, len - 2);
                    878:            }
                    879: /*@*/      else printf("lm_will: not enough room in buffer\n");
                    880:        }
                    881:        break;
                    882:
                    883: #if    defined(AUTHENTICATION)
                    884:        case TELOPT_AUTHENTICATION: {
                    885:                if (!autologin)
                    886:                        break;
                    887:                if (SB_EOF())
                    888:                        return;
                    889:                switch(SB_GET()) {
                    890:                case TELQUAL_IS:
                    891:                        if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
                    892:                                return;
                    893:                        auth_is(subpointer, SB_LEN());
                    894:                        break;
                    895:                case TELQUAL_SEND:
                    896:                        if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
                    897:                                return;
                    898:                        auth_send(subpointer, SB_LEN());
                    899:                        break;
                    900:                case TELQUAL_REPLY:
                    901:                        if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
                    902:                                return;
                    903:                        auth_reply(subpointer, SB_LEN());
                    904:                        break;
                    905:                case TELQUAL_NAME:
                    906:                        if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
                    907:                                return;
                    908:                        auth_name(subpointer, SB_LEN());
                    909:                        break;
                    910:                }
                    911:        }
                    912:        break;
                    913: #endif
1.4       art       914: #if    defined(ENCRYPTION)
                    915:        case TELOPT_ENCRYPT:
                    916:                if (SB_EOF())
                    917:                        return;
                    918:                switch(SB_GET()) {
                    919:                case ENCRYPT_START:
                    920:                        if (my_want_state_is_dont(TELOPT_ENCRYPT))
                    921:                                return;
                    922:                        encrypt_start(subpointer, SB_LEN());
                    923:                        break;
                    924:                case ENCRYPT_END:
                    925:                        if (my_want_state_is_dont(TELOPT_ENCRYPT))
                    926:                                return;
                    927:                        encrypt_end();
                    928:                        break;
                    929:                case ENCRYPT_SUPPORT:
                    930:                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
                    931:                                 return;
                    932:                        encrypt_support(subpointer, SB_LEN());
                    933:                        break;
                    934:                case ENCRYPT_REQSTART:
                    935:                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
                    936:                                return;
                    937:                        encrypt_request_start(subpointer, SB_LEN());
                    938:                        break;
                    939:                case ENCRYPT_REQEND:
                    940:                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
                    941:                                 return;
                    942:                        /*
                    943:                         * We can always send an REQEND so that we cannot
                    944:                         * get stuck encrypting.  We should only get this
                    945:                         * if we have been able to get in the correct mode
                    946:                         * anyhow.
                    947:                         */
                    948:                        encrypt_request_end();
                    949:                        break;
                    950:                case ENCRYPT_IS:
                    951:                         if (my_want_state_is_dont(TELOPT_ENCRYPT))
                    952:                                 return;
                    953:                        encrypt_is(subpointer, SB_LEN());
                    954:                        break;
                    955:                case ENCRYPT_REPLY:
                    956:                        if (my_want_state_is_wont(TELOPT_ENCRYPT))
                    957:                                 return;
                    958:                        encrypt_reply(subpointer, SB_LEN());
                    959:                        break;
                    960:                case ENCRYPT_ENC_KEYID:
                    961:                         if (my_want_state_is_dont(TELOPT_ENCRYPT))
                    962:                                 return;
                    963:                         encrypt_enc_keyid(subpointer, SB_LEN());
                    964:                         break;
                    965:                case ENCRYPT_DEC_KEYID:
                    966:                         if (my_want_state_is_wont(TELOPT_ENCRYPT))
                    967:                                 return;
                    968:                         encrypt_dec_keyid(subpointer, SB_LEN());
                    969:                         break;
                    970:                default:
                    971:                         break;
                    972:                }
                    973:                break;
                    974: #endif
1.1       deraadt   975:     default:
                    976:        break;
                    977:     }
                    978: }
                    979:
                    980: static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
                    981:
                    982:     void
                    983: lm_will(cmd, len)
                    984:     unsigned char *cmd;
                    985:     int len;
                    986: {
                    987:     if (len < 1) {
                    988: /*@*/  printf("lm_will: no command!!!\n");     /* Should not happen... */
                    989:        return;
                    990:     }
                    991:     switch(cmd[0]) {
                    992:     case LM_FORWARDMASK:       /* We shouldn't ever get this... */
                    993:     default:
                    994:        str_lm[3] = DONT;
                    995:        str_lm[4] = cmd[0];
                    996:        if (NETROOM() > sizeof(str_lm)) {
                    997:            ring_supply_data(&netoring, str_lm, sizeof(str_lm));
                    998:            printsub('>', &str_lm[2], sizeof(str_lm)-2);
                    999:        }
                   1000: /*@*/  else printf("lm_will: not enough room in buffer\n");
                   1001:        break;
                   1002:     }
                   1003: }
                   1004:
                   1005:     void
                   1006: lm_wont(cmd, len)
                   1007:     unsigned char *cmd;
                   1008:     int len;
                   1009: {
                   1010:     if (len < 1) {
                   1011: /*@*/  printf("lm_wont: no command!!!\n");     /* Should not happen... */
                   1012:        return;
                   1013:     }
                   1014:     switch(cmd[0]) {
                   1015:     case LM_FORWARDMASK:       /* We shouldn't ever get this... */
                   1016:     default:
                   1017:        /* We are always DONT, so don't respond */
                   1018:        return;
                   1019:     }
                   1020: }
                   1021:
                   1022:     void
                   1023: lm_do(cmd, len)
                   1024:     unsigned char *cmd;
                   1025:     int len;
                   1026: {
                   1027:     if (len < 1) {
                   1028: /*@*/  printf("lm_do: no command!!!\n");       /* Should not happen... */
                   1029:        return;
                   1030:     }
                   1031:     switch(cmd[0]) {
                   1032:     case LM_FORWARDMASK:
                   1033:     default:
                   1034:        str_lm[3] = WONT;
                   1035:        str_lm[4] = cmd[0];
                   1036:        if (NETROOM() > sizeof(str_lm)) {
                   1037:            ring_supply_data(&netoring, str_lm, sizeof(str_lm));
                   1038:            printsub('>', &str_lm[2], sizeof(str_lm)-2);
                   1039:        }
                   1040: /*@*/  else printf("lm_do: not enough room in buffer\n");
                   1041:        break;
                   1042:     }
                   1043: }
                   1044:
                   1045:     void
                   1046: lm_dont(cmd, len)
                   1047:     unsigned char *cmd;
                   1048:     int len;
                   1049: {
                   1050:     if (len < 1) {
                   1051: /*@*/  printf("lm_dont: no command!!!\n");     /* Should not happen... */
                   1052:        return;
                   1053:     }
                   1054:     switch(cmd[0]) {
                   1055:     case LM_FORWARDMASK:
                   1056:     default:
                   1057:        /* we are always WONT, so don't respond */
                   1058:        break;
                   1059:     }
                   1060: }
                   1061:
                   1062: static unsigned char str_lm_mode[] = {
                   1063:        IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
                   1064: };
                   1065:
                   1066:        void
                   1067: lm_mode(cmd, len, init)
                   1068:        unsigned char *cmd;
                   1069:        int len, init;
                   1070: {
                   1071:        if (len != 1)
                   1072:                return;
                   1073:        if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
                   1074:                return;
                   1075:        if (*cmd&MODE_ACK)
                   1076:                return;
                   1077:        linemode = *cmd&(MODE_MASK&~MODE_ACK);
                   1078:        str_lm_mode[4] = linemode;
                   1079:        if (!init)
                   1080:            str_lm_mode[4] |= MODE_ACK;
                   1081:        if (NETROOM() > sizeof(str_lm_mode)) {
                   1082:            ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
                   1083:            printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
                   1084:        }
                   1085: /*@*/  else printf("lm_mode: not enough room in buffer\n");
                   1086:        setconnmode(0); /* set changed mode */
                   1087: }
                   1088:
                   1089: 
                   1090:
                   1091: /*
                   1092:  * slc()
                   1093:  * Handle special character suboption of LINEMODE.
                   1094:  */
                   1095:
                   1096: struct spc {
                   1097:        cc_t val;
                   1098:        cc_t *valp;
                   1099:        char flags;     /* Current flags & level */
                   1100:        char mylevel;   /* Maximum level & flags */
                   1101: } spc_data[NSLC+1];
                   1102:
                   1103: #define SLC_IMPORT     0
                   1104: #define        SLC_EXPORT      1
                   1105: #define SLC_RVALUE     2
                   1106: static int slc_mode = SLC_EXPORT;
                   1107:
                   1108:        void
                   1109: slc_init()
                   1110: {
1.13      mpech    1111:        struct spc *spcp;
1.1       deraadt  1112:
                   1113:        localchars = 1;
                   1114:        for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
                   1115:                spcp->val = 0;
                   1116:                spcp->valp = 0;
                   1117:                spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
                   1118:        }
                   1119:
                   1120: #define        initfunc(func, flags) { \
                   1121:                                        spcp = &spc_data[func]; \
1.4       art      1122:                                        if ((spcp->valp = tcval(func))) { \
1.1       deraadt  1123:                                            spcp->val = *spcp->valp; \
                   1124:                                            spcp->mylevel = SLC_VARIABLE|flags; \
                   1125:                                        } else { \
                   1126:                                            spcp->val = 0; \
                   1127:                                            spcp->mylevel = SLC_DEFAULT; \
                   1128:                                        } \
                   1129:                                    }
                   1130:
                   1131:        initfunc(SLC_SYNCH, 0);
                   1132:        /* No BRK */
                   1133:        initfunc(SLC_AO, 0);
                   1134:        initfunc(SLC_AYT, 0);
                   1135:        /* No EOR */
                   1136:        initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
                   1137:        initfunc(SLC_EOF, 0);
                   1138: #ifndef        SYSV_TERMIO
                   1139:        initfunc(SLC_SUSP, SLC_FLUSHIN);
                   1140: #endif
                   1141:        initfunc(SLC_EC, 0);
                   1142:        initfunc(SLC_EL, 0);
                   1143: #ifndef        SYSV_TERMIO
                   1144:        initfunc(SLC_EW, 0);
                   1145:        initfunc(SLC_RP, 0);
                   1146:        initfunc(SLC_LNEXT, 0);
                   1147: #endif
                   1148:        initfunc(SLC_XON, 0);
                   1149:        initfunc(SLC_XOFF, 0);
                   1150: #ifdef SYSV_TERMIO
                   1151:        spc_data[SLC_XON].mylevel = SLC_CANTCHANGE;
                   1152:        spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE;
                   1153: #endif
                   1154:        initfunc(SLC_FORW1, 0);
                   1155: #ifdef USE_TERMIO
                   1156:        initfunc(SLC_FORW2, 0);
                   1157:        /* No FORW2 */
                   1158: #endif
                   1159:
                   1160:        initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
                   1161: #undef initfunc
                   1162:
                   1163:        if (slc_mode == SLC_EXPORT)
                   1164:                slc_export();
                   1165:        else
                   1166:                slc_import(1);
                   1167:
                   1168: }
                   1169:
                   1170:     void
                   1171: slcstate()
                   1172: {
                   1173:     printf("Special characters are %s values\n",
                   1174:                slc_mode == SLC_IMPORT ? "remote default" :
                   1175:                slc_mode == SLC_EXPORT ? "local" :
                   1176:                                         "remote");
                   1177: }
                   1178:
                   1179:     void
                   1180: slc_mode_export()
                   1181: {
                   1182:     slc_mode = SLC_EXPORT;
                   1183:     if (my_state_is_will(TELOPT_LINEMODE))
                   1184:        slc_export();
                   1185: }
                   1186:
                   1187:     void
                   1188: slc_mode_import(def)
                   1189:     int def;
                   1190: {
                   1191:     slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
                   1192:     if (my_state_is_will(TELOPT_LINEMODE))
                   1193:        slc_import(def);
                   1194: }
                   1195:
                   1196: unsigned char slc_import_val[] = {
                   1197:        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
                   1198: };
                   1199: unsigned char slc_import_def[] = {
                   1200:        IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
                   1201: };
                   1202:
                   1203:     void
                   1204: slc_import(def)
                   1205:     int def;
                   1206: {
                   1207:     if (NETROOM() > sizeof(slc_import_val)) {
                   1208:        if (def) {
                   1209:            ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
                   1210:            printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
                   1211:        } else {
                   1212:            ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
                   1213:            printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
                   1214:        }
                   1215:     }
                   1216: /*@*/ else printf("slc_import: not enough room\n");
                   1217: }
                   1218:
                   1219:     void
                   1220: slc_export()
                   1221: {
1.13      mpech    1222:     struct spc *spcp;
1.1       deraadt  1223:
                   1224:     TerminalDefaultChars();
                   1225:
                   1226:     slc_start_reply();
                   1227:     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
                   1228:        if (spcp->mylevel != SLC_NOSUPPORT) {
                   1229:            if (spcp->val == (cc_t)(_POSIX_VDISABLE))
                   1230:                spcp->flags = SLC_NOSUPPORT;
                   1231:            else
                   1232:                spcp->flags = spcp->mylevel;
                   1233:            if (spcp->valp)
                   1234:                spcp->val = *spcp->valp;
                   1235:            slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
                   1236:        }
                   1237:     }
                   1238:     slc_end_reply();
                   1239:     (void)slc_update();
                   1240:     setconnmode(1);    /* Make sure the character values are set */
                   1241: }
                   1242:
                   1243:        void
                   1244: slc(cp, len)
1.13      mpech    1245:        unsigned char *cp;
1.1       deraadt  1246:        int len;
                   1247: {
1.13      mpech    1248:        struct spc *spcp;
                   1249:        int func,level;
1.1       deraadt  1250:
                   1251:        slc_start_reply();
                   1252:
                   1253:        for (; len >= 3; len -=3, cp +=3) {
                   1254:
                   1255:                func = cp[SLC_FUNC];
                   1256:
                   1257:                if (func == 0) {
                   1258:                        /*
                   1259:                         * Client side: always ignore 0 function.
                   1260:                         */
                   1261:                        continue;
                   1262:                }
                   1263:                if (func > NSLC) {
                   1264:                        if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
                   1265:                                slc_add_reply(func, SLC_NOSUPPORT, 0);
                   1266:                        continue;
                   1267:                }
                   1268:
                   1269:                spcp = &spc_data[func];
                   1270:
                   1271:                level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
                   1272:
                   1273:                if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
                   1274:                    ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
                   1275:                        continue;
                   1276:                }
                   1277:
                   1278:                if (level == (SLC_DEFAULT|SLC_ACK)) {
                   1279:                        /*
                   1280:                         * This is an error condition, the SLC_ACK
                   1281:                         * bit should never be set for the SLC_DEFAULT
                   1282:                         * level.  Our best guess to recover is to
                   1283:                         * ignore the SLC_ACK bit.
                   1284:                         */
                   1285:                        cp[SLC_FLAGS] &= ~SLC_ACK;
                   1286:                }
                   1287:
                   1288:                if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
                   1289:                        spcp->val = (cc_t)cp[SLC_VALUE];
                   1290:                        spcp->flags = cp[SLC_FLAGS];    /* include SLC_ACK */
                   1291:                        continue;
                   1292:                }
                   1293:
                   1294:                level &= ~SLC_ACK;
                   1295:
                   1296:                if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
                   1297:                        spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
                   1298:                        spcp->val = (cc_t)cp[SLC_VALUE];
                   1299:                }
                   1300:                if (level == SLC_DEFAULT) {
                   1301:                        if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
                   1302:                                spcp->flags = spcp->mylevel;
                   1303:                        else
                   1304:                                spcp->flags = SLC_NOSUPPORT;
                   1305:                }
                   1306:                slc_add_reply(func, spcp->flags, spcp->val);
                   1307:        }
                   1308:        slc_end_reply();
                   1309:        if (slc_update())
                   1310:                setconnmode(1); /* set the  new character values */
                   1311: }
                   1312:
                   1313:     void
                   1314: slc_check()
                   1315: {
1.13      mpech    1316:     struct spc *spcp;
1.1       deraadt  1317:
                   1318:     slc_start_reply();
                   1319:     for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
                   1320:        if (spcp->valp && spcp->val != *spcp->valp) {
                   1321:            spcp->val = *spcp->valp;
                   1322:            if (spcp->val == (cc_t)(_POSIX_VDISABLE))
                   1323:                spcp->flags = SLC_NOSUPPORT;
                   1324:            else
                   1325:                spcp->flags = spcp->mylevel;
                   1326:            slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
                   1327:        }
                   1328:     }
                   1329:     slc_end_reply();
                   1330:     setconnmode(1);
                   1331: }
                   1332:
                   1333:
1.19    ! otto     1334: static unsigned char slc_reply[2 * SUBBUFSIZE];
        !          1335: static unsigned char *slc_replyp;
        !          1336:
        !          1337:        unsigned char
        !          1338: slc_add(unsigned char ch)
        !          1339: {
        !          1340:        if (slc_replyp == slc_reply + sizeof(slc_reply))
        !          1341:                return ch;
        !          1342:        return *slc_replyp++ = ch;
        !          1343: }
1.1       deraadt  1344:
                   1345:        void
                   1346: slc_start_reply()
                   1347: {
                   1348:        slc_replyp = slc_reply;
1.19    ! otto     1349:        slc_add(IAC);
        !          1350:        slc_add(SB);
        !          1351:        slc_add(TELOPT_LINEMODE);
        !          1352:        slc_add(LM_SLC);
1.1       deraadt  1353: }
                   1354:
                   1355:        void
                   1356: slc_add_reply(func, flags, value)
                   1357:        unsigned char func;
                   1358:        unsigned char flags;
                   1359:        cc_t value;
                   1360: {
1.19    ! otto     1361:        if (slc_replyp + 6 >= slc_reply + sizeof(slc_reply)) {
        !          1362:                printf("slc_add_reply: not enough room\n");
        !          1363:                return;
        !          1364:        }
        !          1365:        if (slc_add(func) == IAC)
        !          1366:                slc_add(IAC);
        !          1367:        if (slc_add(flags) == IAC)
        !          1368:                slc_add(IAC);
        !          1369:        if (slc_add((unsigned char)value) == IAC)
        !          1370:                slc_add(IAC);
1.1       deraadt  1371: }
                   1372:
                   1373:     void
                   1374: slc_end_reply()
                   1375: {
1.13      mpech    1376:     int len;
1.1       deraadt  1377:
1.19    ! otto     1378:     if (slc_replyp + 2 >= slc_reply + sizeof(slc_reply)) {
        !          1379:        printf("slc_end_reply: not enough room\n");
        !          1380:        return;
        !          1381:     }
        !          1382:
        !          1383:     slc_add(IAC);
        !          1384:     slc_add(SE);
1.1       deraadt  1385:     len = slc_replyp - slc_reply;
                   1386:     if (len <= 6)
                   1387:        return;
                   1388:     if (NETROOM() > len) {
                   1389:        ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
                   1390:        printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
                   1391:     }
                   1392: /*@*/else printf("slc_end_reply: not enough room\n");
                   1393: }
                   1394:
                   1395:        int
                   1396: slc_update()
                   1397: {
1.13      mpech    1398:        struct spc *spcp;
1.1       deraadt  1399:        int need_update = 0;
                   1400:
                   1401:        for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
                   1402:                if (!(spcp->flags&SLC_ACK))
                   1403:                        continue;
                   1404:                spcp->flags &= ~SLC_ACK;
                   1405:                if (spcp->valp && (*spcp->valp != spcp->val)) {
                   1406:                        *spcp->valp = spcp->val;
                   1407:                        need_update = 1;
                   1408:                }
                   1409:        }
                   1410:        return(need_update);
                   1411: }
                   1412:
                   1413: #ifdef OLD_ENVIRON
                   1414: # ifdef        ENV_HACK
                   1415: /*
                   1416:  * Earlier version of telnet/telnetd from the BSD code had
                   1417:  * the definitions of VALUE and VAR reversed.  To ensure
                   1418:  * maximum interoperability, we assume that the server is
                   1419:  * an older BSD server, until proven otherwise.  The newer
                   1420:  * BSD servers should be able to handle either definition,
                   1421:  * so it is better to use the wrong values if we don't
                   1422:  * know what type of server it is.
                   1423:  */
                   1424: int env_auto = 1;
                   1425: int old_env_var = OLD_ENV_VAR;
                   1426: int old_env_value = OLD_ENV_VALUE;
                   1427: # else
                   1428: #  define old_env_var OLD_ENV_VAR
                   1429: #  define old_env_value OLD_ENV_VALUE
                   1430: # endif
                   1431: #endif
                   1432:
                   1433:        void
                   1434: env_opt(buf, len)
1.13      mpech    1435:        unsigned char *buf;
                   1436:        int len;
1.1       deraadt  1437: {
1.13      mpech    1438:        unsigned char *ep = 0, *epc = 0;
                   1439:        int i;
1.1       deraadt  1440:
                   1441:        switch(buf[0]&0xff) {
                   1442:        case TELQUAL_SEND:
                   1443:                env_opt_start();
                   1444:                if (len == 1) {
                   1445:                        env_opt_add(NULL);
                   1446:                } else for (i = 1; i < len; i++) {
                   1447:                        switch (buf[i]&0xff) {
                   1448: #ifdef OLD_ENVIRON
                   1449:                        case OLD_ENV_VAR:
                   1450: # ifdef        ENV_HACK
                   1451:                                if (telopt_environ == TELOPT_OLD_ENVIRON
                   1452:                                    && env_auto) {
                   1453:                                        /* Server has the same definitions */
                   1454:                                        old_env_var = OLD_ENV_VAR;
                   1455:                                        old_env_value = OLD_ENV_VALUE;
                   1456:                                }
                   1457:                                /* FALL THROUGH */
                   1458: # endif
                   1459:                        case OLD_ENV_VALUE:
                   1460:                                /*
                   1461:                                 * Although OLD_ENV_VALUE is not legal, we will
                   1462:                                 * still recognize it, just in case it is an
                   1463:                                 * old server that has VAR & VALUE mixed up...
                   1464:                                 */
                   1465:                                /* FALL THROUGH */
                   1466: #else
                   1467:                        case NEW_ENV_VAR:
                   1468: #endif
                   1469:                        case ENV_USERVAR:
                   1470:                                if (ep) {
                   1471:                                        *epc = 0;
                   1472:                                        env_opt_add(ep);
                   1473:                                }
                   1474:                                ep = epc = &buf[i+1];
                   1475:                                break;
                   1476:                        case ENV_ESC:
                   1477:                                i++;
                   1478:                                /*FALL THROUGH*/
                   1479:                        default:
                   1480:                                if (epc)
                   1481:                                        *epc++ = buf[i];
                   1482:                                break;
                   1483:                        }
                   1484:                }
                   1485:                if (ep) {
                   1486:                        *epc = 0;
                   1487:                        env_opt_add(ep);
                   1488:                }
                   1489:                env_opt_end(1);
                   1490:                break;
                   1491:
                   1492:        case TELQUAL_IS:
                   1493:        case TELQUAL_INFO:
                   1494:                /* Ignore for now.  We shouldn't get it anyway. */
                   1495:                break;
                   1496:
                   1497:        default:
                   1498:                break;
                   1499:        }
                   1500: }
                   1501:
1.19    ! otto     1502: #define        OPT_REPLY_SIZE  (2 * SUBBUFSIZE)
        !          1503: static unsigned char *opt_reply;
        !          1504: static unsigned char *opt_replyp;
        !          1505: static unsigned char *opt_replyend;
1.1       deraadt  1506:
                   1507:        void
1.19    ! otto     1508: opt_add(unsigned char ch)
        !          1509: {
        !          1510:        if (opt_replyp == opt_replyend)
        !          1511:                return;
        !          1512:        *opt_replyp++ = ch;
        !          1513: }
        !          1514:        void
1.1       deraadt  1515: env_opt_start()
                   1516: {
1.8       itojun   1517:        unsigned char *p;
                   1518:
                   1519:        if (opt_reply) {
                   1520:                p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
                   1521:                if (p == NULL)
                   1522:                        free(opt_reply);
                   1523:        } else
                   1524:                p = (unsigned char *)malloc(OPT_REPLY_SIZE);
                   1525:        opt_reply = p;
1.1       deraadt  1526:        if (opt_reply == NULL) {
                   1527: /*@*/          printf("env_opt_start: malloc()/realloc() failed!!!\n");
                   1528:                opt_reply = opt_replyp = opt_replyend = NULL;
                   1529:                return;
                   1530:        }
                   1531:        opt_replyp = opt_reply;
                   1532:        opt_replyend = opt_reply + OPT_REPLY_SIZE;
1.19    ! otto     1533:        opt_add(IAC);
        !          1534:        opt_add(SB);
        !          1535:        opt_add(telopt_environ);
        !          1536:        opt_add(TELQUAL_IS);
1.1       deraadt  1537: }
                   1538:
                   1539:        void
                   1540: env_opt_start_info()
                   1541: {
                   1542:        env_opt_start();
                   1543:        if (opt_replyp)
                   1544:            opt_replyp[-1] = TELQUAL_INFO;
                   1545: }
                   1546:
                   1547:        void
                   1548: env_opt_add(ep)
1.13      mpech    1549:        unsigned char *ep;
1.1       deraadt  1550: {
1.13      mpech    1551:        unsigned char *vp, c;
1.1       deraadt  1552:
                   1553:        if (opt_reply == NULL)          /*XXX*/
                   1554:                return;                 /*XXX*/
                   1555:
                   1556:        if (ep == NULL || *ep == '\0') {
                   1557:                /* Send user defined variables first. */
                   1558:                env_default(1, 0);
1.4       art      1559:                while ((ep = env_default(0, 0)))
1.1       deraadt  1560:                        env_opt_add(ep);
                   1561:
                   1562:                /* Now add the list of well know variables.  */
                   1563:                env_default(1, 1);
1.4       art      1564:                while ((ep = env_default(0, 1)))
1.1       deraadt  1565:                        env_opt_add(ep);
                   1566:                return;
                   1567:        }
1.19    ! otto     1568:        vp = env_getvalue(ep, 1);
        !          1569:        if (opt_replyp + 2 * (vp ? strlen((char *)vp) : 0) +
        !          1570:                                2 * strlen((char *)ep) + 6 > opt_replyend)
1.1       deraadt  1571:        {
1.19    ! otto     1572:                size_t len;
1.8       itojun   1573:                unsigned char *p;
1.19    ! otto     1574:
1.1       deraadt  1575:                len = opt_replyend - opt_reply;
1.19    ! otto     1576:                len += OPT_REPLY_SIZE + 2 * strlen(ep);
        !          1577:                if (vp)
        !          1578:                        len += 2 * strlen(vp);
1.8       itojun   1579:                p = (unsigned char *)realloc(opt_reply, len);
1.19    ! otto     1580:                if (p == NULL) {
1.8       itojun   1581:                        free(opt_reply);
1.1       deraadt  1582: /*@*/                  printf("env_opt_add: realloc() failed!!!\n");
                   1583:                        opt_reply = opt_replyp = opt_replyend = NULL;
                   1584:                        return;
                   1585:                }
1.19    ! otto     1586:                opt_replyp = p + (opt_replyp - opt_reply);
        !          1587:                opt_replyend = p + len;
        !          1588:                opt_reply = p;
1.1       deraadt  1589:        }
1.4       art      1590:        if (opt_welldefined((char *)ep))
1.1       deraadt  1591: #ifdef OLD_ENVIRON
                   1592:                if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19    ! otto     1593:                        opt_add(old_env_var);
1.1       deraadt  1594:                else
                   1595: #endif
1.19    ! otto     1596:                        opt_add(NEW_ENV_VAR);
1.1       deraadt  1597:        else
1.19    ! otto     1598:                opt_add(ENV_USERVAR);
        !          1599:
1.1       deraadt  1600:        for (;;) {
1.4       art      1601:                while ((c = *ep++)) {
1.1       deraadt  1602:                        switch(c&0xff) {
                   1603:                        case IAC:
1.19    ! otto     1604:                                opt_add(IAC);
1.1       deraadt  1605:                                break;
                   1606:                        case NEW_ENV_VAR:
                   1607:                        case NEW_ENV_VALUE:
                   1608:                        case ENV_ESC:
                   1609:                        case ENV_USERVAR:
1.19    ! otto     1610:                                opt_add(ENV_ESC);
1.1       deraadt  1611:                                break;
                   1612:                        }
1.19    ! otto     1613:                        opt_add(c);
1.1       deraadt  1614:                }
1.4       art      1615:                if ((ep = vp)) {
1.1       deraadt  1616: #ifdef OLD_ENVIRON
                   1617:                        if (telopt_environ == TELOPT_OLD_ENVIRON)
1.19    ! otto     1618:                                opt_add(old_env_value);
1.1       deraadt  1619:                        else
                   1620: #endif
1.19    ! otto     1621:                                opt_add(NEW_ENV_VALUE);
1.1       deraadt  1622:                        vp = NULL;
                   1623:                } else
                   1624:                        break;
                   1625:        }
                   1626: }
                   1627:
                   1628:        int
                   1629: opt_welldefined(ep)
                   1630:        char *ep;
                   1631: {
                   1632:        if ((strcmp(ep, "USER") == 0) ||
                   1633:            (strcmp(ep, "DISPLAY") == 0) ||
                   1634:            (strcmp(ep, "PRINTER") == 0) ||
                   1635:            (strcmp(ep, "SYSTEMTYPE") == 0) ||
                   1636:            (strcmp(ep, "JOB") == 0) ||
                   1637:            (strcmp(ep, "ACCT") == 0))
                   1638:                return(1);
                   1639:        return(0);
                   1640: }
                   1641:        void
                   1642: env_opt_end(emptyok)
1.13      mpech    1643:        int emptyok;
1.1       deraadt  1644: {
1.13      mpech    1645:        int len;
1.1       deraadt  1646:
                   1647:        len = opt_replyp - opt_reply + 2;
                   1648:        if (emptyok || len > 6) {
1.19    ! otto     1649:                opt_add(IAC);
        !          1650:                opt_add(SE);
1.1       deraadt  1651:                if (NETROOM() > len) {
                   1652:                        ring_supply_data(&netoring, opt_reply, len);
                   1653:                        printsub('>', &opt_reply[2], len - 2);
                   1654:                }
                   1655: /*@*/          else printf("slc_end_reply: not enough room\n");
                   1656:        }
                   1657:        if (opt_reply) {
                   1658:                free(opt_reply);
                   1659:                opt_reply = opt_replyp = opt_replyend = NULL;
                   1660:        }
                   1661: }
                   1662:
                   1663: 
                   1664:
                   1665:     int
                   1666: telrcv()
                   1667: {
1.13      mpech    1668:     int c;
                   1669:     int scc;
                   1670:     unsigned char *sbp;
1.1       deraadt  1671:     int count;
                   1672:     int returnValue = 0;
                   1673:
                   1674:     scc = 0;
                   1675:     count = 0;
                   1676:     while (TTYROOM() > 2) {
                   1677:        if (scc == 0) {
                   1678:            if (count) {
                   1679:                ring_consumed(&netiring, count);
                   1680:                returnValue = 1;
                   1681:                count = 0;
                   1682:            }
                   1683:            sbp = netiring.consume;
                   1684:            scc = ring_full_consecutive(&netiring);
                   1685:            if (scc == 0) {
                   1686:                /* No more data coming in */
                   1687:                break;
                   1688:            }
                   1689:        }
                   1690:
                   1691:        c = *sbp++ & 0xff, scc--; count++;
1.4       art      1692: #if    defined(ENCRYPTION)
                   1693:        if (decrypt_input)
                   1694:                 c = (*decrypt_input)(c);
                   1695: #endif
1.1       deraadt  1696:
                   1697:        switch (telrcv_state) {
                   1698:
                   1699:        case TS_CR:
                   1700:            telrcv_state = TS_DATA;
                   1701:            if (c == '\0') {
                   1702:                break;  /* Ignore \0 after CR */
                   1703:            }
                   1704:            else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
                   1705:                TTYADD(c);
                   1706:                break;
                   1707:            }
                   1708:            /* Else, fall through */
                   1709:
                   1710:        case TS_DATA:
                   1711:            if (c == IAC) {
                   1712:                telrcv_state = TS_IAC;
                   1713:                break;
                   1714:            }
                   1715: #          if defined(TN3270)
                   1716:            if (In3270) {
                   1717:                *Ifrontp++ = c;
                   1718:                while (scc > 0) {
                   1719:                    c = *sbp++ & 0377, scc--; count++;
                   1720:                    if (c == IAC) {
                   1721:                        telrcv_state = TS_IAC;
                   1722:                        break;
                   1723:                    }
                   1724:                    *Ifrontp++ = c;
                   1725:                }
                   1726:            } else
                   1727: #          endif /* defined(TN3270) */
                   1728:                    /*
                   1729:                     * The 'crmod' hack (see following) is needed
1.4       art      1730:                     * since we can't set CRMOD on output only.
1.1       deraadt  1731:                     * Machines like MULTICS like to send \r without
                   1732:                     * \n; since we must turn off CRMOD to get proper
                   1733:                     * input, the mapping is done here (sigh).
                   1734:                     */
                   1735:            if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
                   1736:                if (scc > 0) {
                   1737:                    c = *sbp&0xff;
1.4       art      1738: #if    defined(ENCRYPTION)
                   1739:                    if (decrypt_input)
                   1740:                         c = (*decrypt_input)(c);
                   1741: #endif
1.1       deraadt  1742:                    if (c == 0) {
                   1743:                        sbp++, scc--; count++;
                   1744:                        /* a "true" CR */
                   1745:                        TTYADD('\r');
                   1746:                    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
                   1747:                                        (c == '\n')) {
                   1748:                        sbp++, scc--; count++;
                   1749:                        TTYADD('\n');
                   1750:                    } else {
1.4       art      1751: #if    defined(ENCRYPTION)
                   1752:                        if (decrypt_input)
                   1753:                            (*decrypt_input)(-1);
                   1754: #endif
1.1       deraadt  1755:                        TTYADD('\r');
                   1756:                        if (crmod) {
                   1757:                                TTYADD('\n');
                   1758:                        }
                   1759:                    }
                   1760:                } else {
                   1761:                    telrcv_state = TS_CR;
                   1762:                    TTYADD('\r');
                   1763:                    if (crmod) {
                   1764:                            TTYADD('\n');
                   1765:                    }
                   1766:                }
                   1767:            } else {
                   1768:                TTYADD(c);
                   1769:            }
                   1770:            continue;
                   1771:
                   1772:        case TS_IAC:
                   1773: process_iac:
                   1774:            switch (c) {
1.2       niklas   1775:
1.1       deraadt  1776:            case WILL:
                   1777:                telrcv_state = TS_WILL;
                   1778:                continue;
                   1779:
                   1780:            case WONT:
                   1781:                telrcv_state = TS_WONT;
                   1782:                continue;
                   1783:
                   1784:            case DO:
                   1785:                telrcv_state = TS_DO;
                   1786:                continue;
                   1787:
                   1788:            case DONT:
                   1789:                telrcv_state = TS_DONT;
                   1790:                continue;
                   1791:
                   1792:            case DM:
                   1793:                    /*
                   1794:                     * We may have missed an urgent notification,
                   1795:                     * so make sure we flush whatever is in the
                   1796:                     * buffer currently.
                   1797:                     */
                   1798:                printoption("RCVD", IAC, DM);
                   1799:                SYNCHing = 1;
                   1800:                (void) ttyflush(1);
                   1801:                SYNCHing = stilloob();
                   1802:                settimer(gotDM);
                   1803:                break;
                   1804:
                   1805:            case SB:
                   1806:                SB_CLEAR();
                   1807:                telrcv_state = TS_SB;
                   1808:                continue;
                   1809:
                   1810: #          if defined(TN3270)
                   1811:            case EOR:
                   1812:                if (In3270) {
                   1813:                    if (Ibackp == Ifrontp) {
                   1814:                        Ibackp = Ifrontp = Ibuf;
                   1815:                        ISend = 0;      /* should have been! */
                   1816:                    } else {
                   1817:                        Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
                   1818:                        ISend = 1;
                   1819:                    }
                   1820:                }
                   1821:                printoption("RCVD", IAC, EOR);
                   1822:                break;
                   1823: #          endif /* defined(TN3270) */
                   1824:
                   1825:            case IAC:
                   1826: #          if !defined(TN3270)
                   1827:                TTYADD(IAC);
                   1828: #          else /* !defined(TN3270) */
                   1829:                if (In3270) {
                   1830:                    *Ifrontp++ = IAC;
                   1831:                } else {
                   1832:                    TTYADD(IAC);
                   1833:                }
                   1834: #          endif /* !defined(TN3270) */
                   1835:                break;
                   1836:
                   1837:            case NOP:
                   1838:            case GA:
                   1839:            default:
                   1840:                printoption("RCVD", IAC, c);
                   1841:                break;
                   1842:            }
                   1843:            telrcv_state = TS_DATA;
                   1844:            continue;
                   1845:
                   1846:        case TS_WILL:
                   1847:            printoption("RCVD", WILL, c);
                   1848:            willoption(c);
                   1849:            SetIn3270();
                   1850:            telrcv_state = TS_DATA;
                   1851:            continue;
                   1852:
                   1853:        case TS_WONT:
                   1854:            printoption("RCVD", WONT, c);
                   1855:            wontoption(c);
                   1856:            SetIn3270();
                   1857:            telrcv_state = TS_DATA;
                   1858:            continue;
                   1859:
                   1860:        case TS_DO:
                   1861:            printoption("RCVD", DO, c);
                   1862:            dooption(c);
                   1863:            SetIn3270();
                   1864:            if (c == TELOPT_NAWS) {
                   1865:                sendnaws();
                   1866:            } else if (c == TELOPT_LFLOW) {
                   1867:                localflow = 1;
                   1868:                setcommandmode();
                   1869:                setconnmode(0);
                   1870:            }
                   1871:            telrcv_state = TS_DATA;
                   1872:            continue;
                   1873:
                   1874:        case TS_DONT:
                   1875:            printoption("RCVD", DONT, c);
                   1876:            dontoption(c);
                   1877:            flushline = 1;
                   1878:            setconnmode(0);     /* set new tty mode (maybe) */
                   1879:            SetIn3270();
                   1880:            telrcv_state = TS_DATA;
                   1881:            continue;
                   1882:
                   1883:        case TS_SB:
                   1884:            if (c == IAC) {
                   1885:                telrcv_state = TS_SE;
                   1886:            } else {
                   1887:                SB_ACCUM(c);
                   1888:            }
                   1889:            continue;
                   1890:
                   1891:        case TS_SE:
                   1892:            if (c != SE) {
                   1893:                if (c != IAC) {
                   1894:                    /*
                   1895:                     * This is an error.  We only expect to get
                   1896:                     * "IAC IAC" or "IAC SE".  Several things may
1.18      jmc      1897:                     * have happened.  An IAC was not doubled, the
1.1       deraadt  1898:                     * IAC SE was left off, or another option got
                   1899:                     * inserted into the suboption are all possibilities.
                   1900:                     * If we assume that the IAC was not doubled,
                   1901:                     * and really the IAC SE was left off, we could
                   1902:                     * get into an infinate loop here.  So, instead,
                   1903:                     * we terminate the suboption, and process the
                   1904:                     * partial suboption if we can.
                   1905:                     */
                   1906:                    SB_ACCUM(IAC);
                   1907:                    SB_ACCUM(c);
                   1908:                    subpointer -= 2;
                   1909:                    SB_TERM();
                   1910:
                   1911:                    printoption("In SUBOPTION processing, RCVD", IAC, c);
                   1912:                    suboption();        /* handle sub-option */
                   1913:                    SetIn3270();
                   1914:                    telrcv_state = TS_IAC;
                   1915:                    goto process_iac;
                   1916:                }
                   1917:                SB_ACCUM(c);
                   1918:                telrcv_state = TS_SB;
                   1919:            } else {
                   1920:                SB_ACCUM(IAC);
                   1921:                SB_ACCUM(SE);
                   1922:                subpointer -= 2;
                   1923:                SB_TERM();
                   1924:                suboption();    /* handle sub-option */
                   1925:                SetIn3270();
                   1926:                telrcv_state = TS_DATA;
                   1927:            }
                   1928:        }
                   1929:     }
                   1930:     if (count)
                   1931:        ring_consumed(&netiring, count);
                   1932:     return returnValue||count;
                   1933: }
                   1934:
                   1935: static int bol = 1, local = 0;
                   1936:
                   1937:     int
                   1938: rlogin_susp()
                   1939: {
                   1940:     if (local) {
                   1941:        local = 0;
                   1942:        bol = 1;
                   1943:        command(0, "z\n", 2);
                   1944:        return(1);
                   1945:     }
                   1946:     return(0);
                   1947: }
                   1948:
                   1949:     static int
                   1950: telsnd()
                   1951: {
                   1952:     int tcc;
                   1953:     int count;
                   1954:     int returnValue = 0;
                   1955:     unsigned char *tbp;
                   1956:
                   1957:     tcc = 0;
                   1958:     count = 0;
                   1959:     while (NETROOM() > 2) {
1.13      mpech    1960:        int sc;
                   1961:        int c;
1.1       deraadt  1962:
                   1963:        if (tcc == 0) {
                   1964:            if (count) {
                   1965:                ring_consumed(&ttyiring, count);
                   1966:                returnValue = 1;
                   1967:                count = 0;
                   1968:            }
                   1969:            tbp = ttyiring.consume;
                   1970:            tcc = ring_full_consecutive(&ttyiring);
                   1971:            if (tcc == 0) {
                   1972:                break;
                   1973:            }
                   1974:        }
                   1975:        c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
                   1976:        if (rlogin != _POSIX_VDISABLE) {
                   1977:                if (bol) {
                   1978:                        bol = 0;
                   1979:                        if (sc == rlogin) {
                   1980:                                local = 1;
                   1981:                                continue;
                   1982:                        }
                   1983:                } else if (local) {
                   1984:                        local = 0;
                   1985:                        if (sc == '.' || c == termEofChar) {
                   1986:                                bol = 1;
                   1987:                                command(0, "close\n", 6);
                   1988:                                continue;
                   1989:                        }
                   1990:                        if (sc == termSuspChar) {
                   1991:                                bol = 1;
                   1992:                                command(0, "z\n", 2);
                   1993:                                continue;
                   1994:                        }
                   1995:                        if (sc == escape) {
                   1996:                                command(0, (char *)tbp, tcc);
                   1997:                                bol = 1;
                   1998:                                count += tcc;
                   1999:                                tcc = 0;
                   2000:                                flushline = 1;
                   2001:                                break;
                   2002:                        }
                   2003:                        if (sc != rlogin) {
                   2004:                                ++tcc;
                   2005:                                --tbp;
                   2006:                                --count;
                   2007:                                c = sc = rlogin;
                   2008:                        }
                   2009:                }
                   2010:                if ((sc == '\n') || (sc == '\r'))
                   2011:                        bol = 1;
1.7       aaron    2012:        } else if (escape != _POSIX_VDISABLE && sc == escape) {
1.1       deraadt  2013:            /*
                   2014:             * Double escape is a pass through of a single escape character.
                   2015:             */
                   2016:            if (tcc && strip(*tbp) == escape) {
                   2017:                tbp++;
                   2018:                tcc--;
                   2019:                count++;
                   2020:                bol = 0;
                   2021:            } else {
                   2022:                command(0, (char *)tbp, tcc);
                   2023:                bol = 1;
                   2024:                count += tcc;
                   2025:                tcc = 0;
                   2026:                flushline = 1;
                   2027:                break;
                   2028:            }
                   2029:        } else
                   2030:            bol = 0;
                   2031: #ifdef KLUDGELINEMODE
                   2032:        if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
                   2033:            if (tcc > 0 && strip(*tbp) == echoc) {
                   2034:                tcc--; tbp++; count++;
                   2035:            } else {
                   2036:                dontlecho = !dontlecho;
                   2037:                settimer(echotoggle);
                   2038:                setconnmode(0);
                   2039:                flushline = 1;
                   2040:                break;
                   2041:            }
                   2042:        }
                   2043: #endif
1.3       deraadt  2044:        if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
1.1       deraadt  2045:            if (TerminalSpecialChars(sc) == 0) {
                   2046:                bol = 1;
                   2047:                break;
                   2048:            }
                   2049:        }
                   2050:        if (my_want_state_is_wont(TELOPT_BINARY)) {
                   2051:            switch (c) {
                   2052:            case '\n':
                   2053:                    /*
                   2054:                     * If we are in CRMOD mode (\r ==> \n)
                   2055:                     * on our local machine, then probably
                   2056:                     * a newline (unix) is CRLF (TELNET).
                   2057:                     */
                   2058:                if (MODE_LOCAL_CHARS(globalmode)) {
                   2059:                    NETADD('\r');
                   2060:                }
                   2061:                NETADD('\n');
                   2062:                bol = flushline = 1;
                   2063:                break;
                   2064:            case '\r':
                   2065:                if (!crlf) {
                   2066:                    NET2ADD('\r', '\0');
                   2067:                } else {
                   2068:                    NET2ADD('\r', '\n');
                   2069:                }
                   2070:                bol = flushline = 1;
                   2071:                break;
                   2072:            case IAC:
                   2073:                NET2ADD(IAC, IAC);
                   2074:                break;
                   2075:            default:
                   2076:                NETADD(c);
                   2077:                break;
                   2078:            }
                   2079:        } else if (c == IAC) {
                   2080:            NET2ADD(IAC, IAC);
                   2081:        } else {
                   2082:            NETADD(c);
                   2083:        }
                   2084:     }
                   2085:     if (count)
                   2086:        ring_consumed(&ttyiring, count);
                   2087:     return returnValue||count;         /* Non-zero if we did anything */
                   2088: }
                   2089: 
                   2090: /*
                   2091:  * Scheduler()
                   2092:  *
                   2093:  * Try to do something.
                   2094:  *
                   2095:  * If we do something useful, return 1; else return 0.
                   2096:  *
                   2097:  */
                   2098:
                   2099:
                   2100:     int
                   2101: Scheduler(block)
                   2102:     int        block;                  /* should we block in the select ? */
                   2103: {
                   2104:                /* One wants to be a bit careful about setting returnValue
                   2105:                 * to one, since a one implies we did some useful work,
                   2106:                 * and therefore probably won't be called to block next
                   2107:                 * time (TN3270 mode only).
                   2108:                 */
                   2109:     int returnValue;
                   2110:     int netin, netout, netex, ttyin, ttyout;
                   2111:
                   2112:     /* Decide which rings should be processed */
                   2113:
                   2114:     netout = ring_full_count(&netoring) &&
                   2115:            (flushline ||
                   2116:                (my_want_state_is_wont(TELOPT_LINEMODE)
                   2117: #ifdef KLUDGELINEMODE
                   2118:                        && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
                   2119: #endif
                   2120:                ) ||
                   2121:                        my_want_state_is_will(TELOPT_BINARY));
                   2122:     ttyout = ring_full_count(&ttyoring);
                   2123:
                   2124: #if    defined(TN3270)
                   2125:     ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
                   2126: #else  /* defined(TN3270) */
                   2127:     ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
                   2128: #endif /* defined(TN3270) */
                   2129:
                   2130: #if    defined(TN3270)
                   2131:     netin = ring_empty_count(&netiring);
                   2132: #   else /* !defined(TN3270) */
                   2133:     netin = !ISend && ring_empty_count(&netiring);
                   2134: #   endif /* !defined(TN3270) */
                   2135:
                   2136:     netex = !SYNCHing;
                   2137:
                   2138:     /* If we have seen a signal recently, reset things */
1.15      hin      2139:
                   2140:     if (scheduler_lockout_tty) {
                   2141:        ttyin = ttyout = 0;
                   2142:     }
                   2143:
1.1       deraadt  2144: #   if defined(TN3270) && defined(unix)
                   2145:     if (HaveInput) {
                   2146:        HaveInput = 0;
                   2147:        (void) signal(SIGIO, inputAvailable);
                   2148:     }
                   2149: #endif /* defined(TN3270) && defined(unix) */
                   2150:
                   2151:     /* Call to system code to process rings */
                   2152:
                   2153:     returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
                   2154:
                   2155:     /* Now, look at the input rings, looking for work to do. */
                   2156:
                   2157:     if (ring_full_count(&ttyiring)) {
                   2158: #   if defined(TN3270)
                   2159:        if (In3270) {
                   2160:            int c;
                   2161:
                   2162:            c = DataFromTerminal(ttyiring.consume,
                   2163:                                        ring_full_consecutive(&ttyiring));
                   2164:            if (c) {
                   2165:                returnValue = 1;
1.2       niklas   2166:                ring_consumed(&ttyiring, c);
1.1       deraadt  2167:            }
                   2168:        } else {
                   2169: #   endif /* defined(TN3270) */
                   2170:            returnValue |= telsnd();
                   2171: #   if defined(TN3270)
                   2172:        }
                   2173: #   endif /* defined(TN3270) */
                   2174:     }
                   2175:
                   2176:     if (ring_full_count(&netiring)) {
                   2177: #      if !defined(TN3270)
                   2178:        returnValue |= telrcv();
                   2179: #      else /* !defined(TN3270) */
                   2180:        returnValue = Push3270();
                   2181: #      endif /* !defined(TN3270) */
                   2182:     }
                   2183:     return returnValue;
                   2184: }
                   2185: 
                   2186: /*
                   2187:  * Select from tty and network...
                   2188:  */
                   2189:     void
                   2190: telnet(user)
                   2191:     char *user;
                   2192: {
1.15      hin      2193:     int printed_encrypt = 0;
                   2194:
1.1       deraadt  2195:     sys_telnet_init();
                   2196:
1.4       art      2197: #if    defined(AUTHENTICATION) || defined(ENCRYPTION)
1.1       deraadt  2198:     {
                   2199:        static char local_host[256] = { 0 };
                   2200:
                   2201:        if (!local_host[0]) {
                   2202:                gethostname(local_host, sizeof(local_host));
                   2203:                local_host[sizeof(local_host)-1] = 0;
                   2204:        }
                   2205:        auth_encrypt_init(local_host, hostname, "TELNET", 0);
                   2206:        auth_encrypt_user(user);
                   2207:     }
1.4       art      2208: #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
1.1       deraadt  2209: #   if !defined(TN3270)
                   2210:     if (telnetport) {
                   2211: #if    defined(AUTHENTICATION)
                   2212:        if (autologin)
                   2213:                send_will(TELOPT_AUTHENTICATION, 1);
                   2214: #endif
1.4       art      2215: #if    defined(ENCRYPTION)
                   2216:        send_do(TELOPT_ENCRYPT, 1);
                   2217:        send_will(TELOPT_ENCRYPT, 1);
                   2218: #endif
1.1       deraadt  2219:        send_do(TELOPT_SGA, 1);
                   2220:        send_will(TELOPT_TTYPE, 1);
                   2221:        send_will(TELOPT_NAWS, 1);
                   2222:        send_will(TELOPT_TSPEED, 1);
                   2223:        send_will(TELOPT_LFLOW, 1);
                   2224:        send_will(TELOPT_LINEMODE, 1);
                   2225:        send_will(TELOPT_NEW_ENVIRON, 1);
                   2226:        send_do(TELOPT_STATUS, 1);
1.19    ! otto     2227:        if (env_getvalue((unsigned char *)"DISPLAY", 0))
1.1       deraadt  2228:            send_will(TELOPT_XDISPLOC, 1);
1.4       art      2229:        if (binary)
                   2230:            tel_enter_binary(binary);
1.1       deraadt  2231:     }
                   2232: #   endif /* !defined(TN3270) */
                   2233:
1.15      hin      2234: #ifdef ENCRYPTION
                   2235:     /*
                   2236:      * Note: we assume a tie to the authentication option here.  This
                   2237:      * is necessary so that authentication fails, we don't spin
                   2238:      * forever.
                   2239:      */
                   2240:     if (wantencryption) {
                   2241:        extern int auth_has_failed;
                   2242:        time_t timeout = time(0) + 60;
                   2243:
                   2244:        send_do(TELOPT_ENCRYPT, 1);
                   2245:        send_will(TELOPT_ENCRYPT, 1);
                   2246:        while (1) {
                   2247:            if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) {
                   2248:                if (wantencryption == -1) {
                   2249:                    break;
                   2250:                } else {
                   2251:                    printf("\nServer refused to negotiate authentication,");
                   2252:                    printf(" which is required for encryption.\n");
                   2253:                    Exit(1);
                   2254:                }
                   2255:            }
                   2256:            if (auth_has_failed) {
1.17      jmc      2257:                printf("\nAuthentication negotiation has failed,");
1.15      hin      2258:                printf(" which is required for encryption.\n");
                   2259:                Exit(1);
                   2260:            }
                   2261:            if (my_want_state_is_dont(TELOPT_ENCRYPT) ||
                   2262:                my_want_state_is_wont(TELOPT_ENCRYPT)) {
                   2263:                printf("\nServer refused to negotiate encryption.\n");
                   2264:                Exit(1);
                   2265:            }
                   2266:            if (encrypt_is_encrypting())
                   2267:                break;
                   2268:            if (time(0) > timeout) {
                   2269:                printf("\nEncryption could not be enabled.\n");
                   2270:                Exit(1);
                   2271:            }
                   2272:            if (printed_encrypt == 0) {
                   2273:                printed_encrypt = 1;
                   2274:                printf("Waiting for encryption to be negotiated...\n");
                   2275:                /*
                   2276:                 * Turn on MODE_TRAPSIG and then turn off localchars
                   2277:                 * so that ^C will cause telnet to exit.
                   2278:                 */
                   2279:                TerminalNewMode(getconnmode()|MODE_TRAPSIG);
                   2280:                intr_waiting = 1;
                   2281:            }
                   2282:            if (intr_happened) {
                   2283:                printf("\nUser interrupt.\n");
                   2284:                Exit(1);
                   2285:            }
                   2286:            telnet_spin();
                   2287:        }
                   2288:        if (printed_encrypt) {
                   2289:            printf("Encryption negotiated.\n");
                   2290:            intr_waiting = 0;
                   2291:            setconnmode(0);
                   2292:        }
                   2293:     }
                   2294: #endif
                   2295:
1.1       deraadt  2296: #   if !defined(TN3270)
                   2297:     for (;;) {
                   2298:        int schedValue;
                   2299:
                   2300:        while ((schedValue = Scheduler(0)) != 0) {
                   2301:            if (schedValue == -1) {
                   2302:                setcommandmode();
                   2303:                return;
                   2304:            }
                   2305:        }
                   2306:
                   2307:        if (Scheduler(1) == -1) {
                   2308:            setcommandmode();
                   2309:            return;
                   2310:        }
                   2311:     }
                   2312: #   else /* !defined(TN3270) */
                   2313:     for (;;) {
                   2314:        int schedValue;
                   2315:
                   2316:        while (!In3270 && !shell_active) {
                   2317:            if (Scheduler(1) == -1) {
                   2318:                setcommandmode();
                   2319:                return;
                   2320:            }
                   2321:        }
                   2322:
                   2323:        while ((schedValue = Scheduler(0)) != 0) {
                   2324:            if (schedValue == -1) {
                   2325:                setcommandmode();
                   2326:                return;
                   2327:            }
                   2328:        }
                   2329:                /* If there is data waiting to go out to terminal, don't
                   2330:                 * schedule any more data for the terminal.
                   2331:                 */
                   2332:        if (ring_full_count(&ttyoring)) {
                   2333:            schedValue = 1;
                   2334:        } else {
                   2335:            if (shell_active) {
                   2336:                if (shell_continue() == 0) {
                   2337:                    ConnectScreen();
                   2338:                }
                   2339:            } else if (In3270) {
                   2340:                schedValue = DoTerminalOutput();
                   2341:            }
                   2342:        }
                   2343:        if (schedValue && (shell_active == 0)) {
                   2344:            if (Scheduler(1) == -1) {
                   2345:                setcommandmode();
                   2346:                return;
                   2347:            }
                   2348:        }
                   2349:     }
                   2350: #   endif /* !defined(TN3270) */
                   2351: }
                   2352: 
                   2353: #if    0       /* XXX - this not being in is a bug */
                   2354: /*
                   2355:  * nextitem()
                   2356:  *
                   2357:  *     Return the address of the next "item" in the TELNET data
                   2358:  * stream.  This will be the address of the next character if
                   2359:  * the current address is a user data character, or it will
                   2360:  * be the address of the character following the TELNET command
                   2361:  * if the current address is a TELNET IAC ("I Am a Command")
                   2362:  * character.
                   2363:  */
                   2364:
                   2365:     static char *
                   2366: nextitem(current)
                   2367:     char *current;
                   2368: {
                   2369:     if ((*current&0xff) != IAC) {
                   2370:        return current+1;
                   2371:     }
                   2372:     switch (*(current+1)&0xff) {
                   2373:     case DO:
                   2374:     case DONT:
                   2375:     case WILL:
                   2376:     case WONT:
                   2377:        return current+3;
                   2378:     case SB:           /* loop forever looking for the SE */
                   2379:        {
1.13      mpech    2380:            char *look = current+2;
1.1       deraadt  2381:
                   2382:            for (;;) {
                   2383:                if ((*look++&0xff) == IAC) {
                   2384:                    if ((*look++&0xff) == SE) {
                   2385:                        return look;
                   2386:                    }
                   2387:                }
                   2388:            }
                   2389:        }
                   2390:     default:
                   2391:        return current+2;
                   2392:     }
                   2393: }
                   2394: #endif /* 0 */
                   2395:
                   2396: /*
                   2397:  * netclear()
                   2398:  *
                   2399:  *     We are about to do a TELNET SYNCH operation.  Clear
                   2400:  * the path to the network.
                   2401:  *
                   2402:  *     Things are a bit tricky since we may have sent the first
                   2403:  * byte or so of a previous TELNET command into the network.
                   2404:  * So, we have to scan the network buffer from the beginning
                   2405:  * until we are up to where we want to be.
                   2406:  *
                   2407:  *     A side effect of what we do, just to keep things
                   2408:  * simple, is to clear the urgent data pointer.  The principal
                   2409:  * caller should be setting the urgent data pointer AFTER calling
                   2410:  * us in any case.
                   2411:  */
                   2412:
                   2413:     static void
                   2414: netclear()
                   2415: {
                   2416: #if    0       /* XXX */
1.13      mpech    2417:     char *thisitem, *next;
1.1       deraadt  2418:     char *good;
                   2419: #define        wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
                   2420:                                ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
                   2421:
                   2422:     thisitem = netobuf;
                   2423:
                   2424:     while ((next = nextitem(thisitem)) <= netobuf.send) {
                   2425:        thisitem = next;
                   2426:     }
                   2427:
                   2428:     /* Now, thisitem is first before/at boundary. */
                   2429:
                   2430:     good = netobuf;    /* where the good bytes go */
                   2431:
                   2432:     while (netoring.add > thisitem) {
                   2433:        if (wewant(thisitem)) {
                   2434:            int length;
                   2435:
                   2436:            next = thisitem;
                   2437:            do {
                   2438:                next = nextitem(next);
                   2439:            } while (wewant(next) && (nfrontp > next));
                   2440:            length = next-thisitem;
1.2       niklas   2441:            memmove(good, thisitem, length);
1.1       deraadt  2442:            good += length;
                   2443:            thisitem = next;
                   2444:        } else {
                   2445:            thisitem = nextitem(thisitem);
                   2446:        }
                   2447:     }
                   2448:
                   2449: #endif /* 0 */
                   2450: }
                   2451: 
                   2452: /*
                   2453:  * These routines add various telnet commands to the data stream.
                   2454:  */
                   2455:
                   2456:     static void
                   2457: doflush()
                   2458: {
                   2459:     NET2ADD(IAC, DO);
                   2460:     NETADD(TELOPT_TM);
                   2461:     flushline = 1;
                   2462:     flushout = 1;
                   2463:     (void) ttyflush(1);                        /* Flush/drop output */
                   2464:     /* do printoption AFTER flush, otherwise the output gets tossed... */
                   2465:     printoption("SENT", DO, TELOPT_TM);
                   2466: }
                   2467:
                   2468:     void
                   2469: xmitAO()
                   2470: {
                   2471:     NET2ADD(IAC, AO);
                   2472:     printoption("SENT", IAC, AO);
                   2473:     if (autoflush) {
                   2474:        doflush();
                   2475:     }
                   2476: }
                   2477:
                   2478:
                   2479:     void
                   2480: xmitEL()
                   2481: {
                   2482:     NET2ADD(IAC, EL);
                   2483:     printoption("SENT", IAC, EL);
                   2484: }
                   2485:
                   2486:     void
                   2487: xmitEC()
                   2488: {
                   2489:     NET2ADD(IAC, EC);
                   2490:     printoption("SENT", IAC, EC);
                   2491: }
                   2492:
                   2493:
                   2494:     int
                   2495: dosynch()
                   2496: {
                   2497:     netclear();                        /* clear the path to the network */
                   2498:     NETADD(IAC);
                   2499:     setneturg();
                   2500:     NETADD(DM);
                   2501:     printoption("SENT", IAC, DM);
                   2502:     return 1;
                   2503: }
                   2504:
                   2505: int want_status_response = 0;
                   2506:
                   2507:     int
                   2508: get_status()
                   2509: {
                   2510:     unsigned char tmp[16];
1.13      mpech    2511:     unsigned char *cp;
1.1       deraadt  2512:
                   2513:     if (my_want_state_is_dont(TELOPT_STATUS)) {
                   2514:        printf("Remote side does not support STATUS option\n");
                   2515:        return 0;
                   2516:     }
                   2517:     cp = tmp;
                   2518:
                   2519:     *cp++ = IAC;
                   2520:     *cp++ = SB;
                   2521:     *cp++ = TELOPT_STATUS;
                   2522:     *cp++ = TELQUAL_SEND;
                   2523:     *cp++ = IAC;
                   2524:     *cp++ = SE;
                   2525:     if (NETROOM() >= cp - tmp) {
                   2526:        ring_supply_data(&netoring, tmp, cp-tmp);
                   2527:        printsub('>', tmp+2, cp - tmp - 2);
                   2528:     }
                   2529:     ++want_status_response;
                   2530:     return 1;
                   2531: }
                   2532:
                   2533:     void
                   2534: intp()
                   2535: {
                   2536:     NET2ADD(IAC, IP);
                   2537:     printoption("SENT", IAC, IP);
                   2538:     flushline = 1;
                   2539:     if (autoflush) {
                   2540:        doflush();
                   2541:     }
                   2542:     if (autosynch) {
                   2543:        dosynch();
                   2544:     }
                   2545: }
                   2546:
                   2547:     void
                   2548: sendbrk()
                   2549: {
                   2550:     NET2ADD(IAC, BREAK);
                   2551:     printoption("SENT", IAC, BREAK);
                   2552:     flushline = 1;
                   2553:     if (autoflush) {
                   2554:        doflush();
                   2555:     }
                   2556:     if (autosynch) {
                   2557:        dosynch();
                   2558:     }
                   2559: }
                   2560:
                   2561:     void
                   2562: sendabort()
                   2563: {
                   2564:     NET2ADD(IAC, ABORT);
                   2565:     printoption("SENT", IAC, ABORT);
                   2566:     flushline = 1;
                   2567:     if (autoflush) {
                   2568:        doflush();
                   2569:     }
                   2570:     if (autosynch) {
                   2571:        dosynch();
                   2572:     }
                   2573: }
                   2574:
                   2575:     void
                   2576: sendsusp()
                   2577: {
                   2578:     NET2ADD(IAC, SUSP);
                   2579:     printoption("SENT", IAC, SUSP);
                   2580:     flushline = 1;
                   2581:     if (autoflush) {
                   2582:        doflush();
                   2583:     }
                   2584:     if (autosynch) {
                   2585:        dosynch();
                   2586:     }
                   2587: }
                   2588:
                   2589:     void
                   2590: sendeof()
                   2591: {
                   2592:     NET2ADD(IAC, xEOF);
                   2593:     printoption("SENT", IAC, xEOF);
                   2594: }
                   2595:
                   2596:     void
                   2597: sendayt()
                   2598: {
                   2599:     NET2ADD(IAC, AYT);
                   2600:     printoption("SENT", IAC, AYT);
                   2601: }
                   2602:
                   2603: /*
                   2604:  * Send a window size update to the remote system.
                   2605:  */
                   2606:
                   2607:     void
                   2608: sendnaws()
                   2609: {
                   2610:     long rows, cols;
                   2611:     unsigned char tmp[16];
1.13      mpech    2612:     unsigned char *cp;
1.1       deraadt  2613:
                   2614:     if (my_state_is_wont(TELOPT_NAWS))
                   2615:        return;
                   2616:
                   2617: #define        PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
                   2618:                            if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
                   2619:
                   2620:     if (TerminalWindowSize(&rows, &cols) == 0) {       /* Failed */
                   2621:        return;
                   2622:     }
                   2623:
                   2624:     cp = tmp;
                   2625:
                   2626:     *cp++ = IAC;
                   2627:     *cp++ = SB;
                   2628:     *cp++ = TELOPT_NAWS;
                   2629:     PUTSHORT(cp, cols);
                   2630:     PUTSHORT(cp, rows);
                   2631:     *cp++ = IAC;
                   2632:     *cp++ = SE;
                   2633:     if (NETROOM() >= cp - tmp) {
                   2634:        ring_supply_data(&netoring, tmp, cp-tmp);
                   2635:        printsub('>', tmp+2, cp - tmp - 2);
                   2636:     }
                   2637: }
                   2638:
                   2639:     void
                   2640: tel_enter_binary(rw)
                   2641:     int rw;
                   2642: {
                   2643:     if (rw&1)
                   2644:        send_do(TELOPT_BINARY, 1);
                   2645:     if (rw&2)
                   2646:        send_will(TELOPT_BINARY, 1);
                   2647: }
                   2648:
                   2649:     void
                   2650: tel_leave_binary(rw)
                   2651:     int rw;
                   2652: {
                   2653:     if (rw&1)
                   2654:        send_dont(TELOPT_BINARY, 1);
                   2655:     if (rw&2)
                   2656:        send_wont(TELOPT_BINARY, 1);
                   2657: }