[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.2

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