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

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