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

Annotation of src/usr.bin/telnet/sys_bsd.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[] = "@(#)sys_bsd.c 8.1 (Berkeley) 6/6/93"; */
        !            36: static char *rcsid = "$Id: sys_bsd.c,v 1.6 1995/03/17 18:03:08 mycroft Exp $";
        !            37: #endif /* not lint */
        !            38:
        !            39: /*
        !            40:  * The following routines try to encapsulate what is system dependent
        !            41:  * (at least between 4.x and dos) which is used in telnet.c.
        !            42:  */
        !            43:
        !            44:
        !            45: #include <fcntl.h>
        !            46: #include <sys/types.h>
        !            47: #include <sys/time.h>
        !            48: #include <sys/socket.h>
        !            49: #include <signal.h>
        !            50: #include <errno.h>
        !            51: #include <arpa/telnet.h>
        !            52:
        !            53: #include "ring.h"
        !            54:
        !            55: #include "fdset.h"
        !            56:
        !            57: #include "defines.h"
        !            58: #include "externs.h"
        !            59: #include "types.h"
        !            60:
        !            61: #if    defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
        !            62: #define        SIG_FUNC_RET    void
        !            63: #else
        !            64: #define        SIG_FUNC_RET    int
        !            65: #endif
        !            66:
        !            67: #ifdef SIGINFO
        !            68: extern SIG_FUNC_RET ayt_status();
        !            69: #endif
        !            70:
        !            71: int
        !            72:        tout,                   /* Output file descriptor */
        !            73:        tin,                    /* Input file descriptor */
        !            74:        net;
        !            75:
        !            76: #ifndef        USE_TERMIO
        !            77: struct tchars otc = { 0 }, ntc = { 0 };
        !            78: struct ltchars oltc = { 0 }, nltc = { 0 };
        !            79: struct sgttyb ottyb = { 0 }, nttyb = { 0 };
        !            80: int    olmode = 0;
        !            81: # define cfgetispeed(ptr)      (ptr)->sg_ispeed
        !            82: # define cfgetospeed(ptr)      (ptr)->sg_ospeed
        !            83: # define old_tc ottyb
        !            84:
        !            85: #else  /* USE_TERMIO */
        !            86: struct termio old_tc = { 0 };
        !            87: extern struct termio new_tc;
        !            88:
        !            89: # ifndef       TCSANOW
        !            90: #  ifdef TCSETS
        !            91: #   define     TCSANOW         TCSETS
        !            92: #   define     TCSADRAIN       TCSETSW
        !            93: #   define     tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
        !            94: #  else
        !            95: #   ifdef TCSETA
        !            96: #    define    TCSANOW         TCSETA
        !            97: #    define    TCSADRAIN       TCSETAW
        !            98: #    define    tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
        !            99: #   else
        !           100: #    define    TCSANOW         TIOCSETA
        !           101: #    define    TCSADRAIN       TIOCSETAW
        !           102: #    define    tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
        !           103: #   endif
        !           104: #  endif
        !           105: #  define      tcsetattr(f, a, t) ioctl(f, a, (char *)t)
        !           106: #  define      cfgetospeed(ptr)        ((ptr)->c_cflag&CBAUD)
        !           107: #  ifdef CIBAUD
        !           108: #   define     cfgetispeed(ptr)        (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
        !           109: #  else
        !           110: #   define     cfgetispeed(ptr)        cfgetospeed(ptr)
        !           111: #  endif
        !           112: # endif /* TCSANOW */
        !           113: # ifdef        sysV88
        !           114: # define TIOCFLUSH TC_PX_DRAIN
        !           115: # endif
        !           116: #endif /* USE_TERMIO */
        !           117:
        !           118: static fd_set ibits, obits, xbits;
        !           119:
        !           120:
        !           121:     void
        !           122: init_sys()
        !           123: {
        !           124:     tout = fileno(stdout);
        !           125:     tin = fileno(stdin);
        !           126:     FD_ZERO(&ibits);
        !           127:     FD_ZERO(&obits);
        !           128:     FD_ZERO(&xbits);
        !           129:
        !           130:     errno = 0;
        !           131: }
        !           132:
        !           133:
        !           134:     int
        !           135: TerminalWrite(buf, n)
        !           136:     char *buf;
        !           137:     int  n;
        !           138: {
        !           139:     return write(tout, buf, n);
        !           140: }
        !           141:
        !           142:     int
        !           143: TerminalRead(buf, n)
        !           144:     char *buf;
        !           145:     int  n;
        !           146: {
        !           147:     return read(tin, buf, n);
        !           148: }
        !           149:
        !           150: /*
        !           151:  *
        !           152:  */
        !           153:
        !           154:     int
        !           155: TerminalAutoFlush()
        !           156: {
        !           157: #if    defined(LNOFLSH)
        !           158:     int flush;
        !           159:
        !           160:     ioctl(0, TIOCLGET, (char *)&flush);
        !           161:     return !(flush&LNOFLSH);   /* if LNOFLSH, no autoflush */
        !           162: #else  /* LNOFLSH */
        !           163:     return 1;
        !           164: #endif /* LNOFLSH */
        !           165: }
        !           166:
        !           167: #ifdef KLUDGELINEMODE
        !           168: extern int kludgelinemode;
        !           169: #endif
        !           170: /*
        !           171:  * TerminalSpecialChars()
        !           172:  *
        !           173:  * Look at an input character to see if it is a special character
        !           174:  * and decide what to do.
        !           175:  *
        !           176:  * Output:
        !           177:  *
        !           178:  *     0       Don't add this character.
        !           179:  *     1       Do add this character
        !           180:  */
        !           181:
        !           182: extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
        !           183:
        !           184:     int
        !           185: TerminalSpecialChars(c)
        !           186:     int        c;
        !           187: {
        !           188:     if (c == termIntChar) {
        !           189:        intp();
        !           190:        return 0;
        !           191:     } else if (c == termQuitChar) {
        !           192: #ifdef KLUDGELINEMODE
        !           193:        if (kludgelinemode)
        !           194:            sendbrk();
        !           195:        else
        !           196: #endif
        !           197:            sendabort();
        !           198:        return 0;
        !           199:     } else if (c == termEofChar) {
        !           200:        if (my_want_state_is_will(TELOPT_LINEMODE)) {
        !           201:            sendeof();
        !           202:            return 0;
        !           203:        }
        !           204:        return 1;
        !           205:     } else if (c == termSuspChar) {
        !           206:        sendsusp();
        !           207:        return(0);
        !           208:     } else if (c == termFlushChar) {
        !           209:        xmitAO();               /* Transmit Abort Output */
        !           210:        return 0;
        !           211:     } else if (!MODE_LOCAL_CHARS(globalmode)) {
        !           212:        if (c == termKillChar) {
        !           213:            xmitEL();
        !           214:            return 0;
        !           215:        } else if (c == termEraseChar) {
        !           216:            xmitEC();           /* Transmit Erase Character */
        !           217:            return 0;
        !           218:        }
        !           219:     }
        !           220:     return 1;
        !           221: }
        !           222:
        !           223:
        !           224: /*
        !           225:  * Flush output to the terminal
        !           226:  */
        !           227:
        !           228:     void
        !           229: TerminalFlushOutput()
        !           230: {
        !           231: #ifdef TIOCFLUSH
        !           232:     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
        !           233: #else
        !           234:     (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
        !           235: #endif
        !           236: }
        !           237:
        !           238:     void
        !           239: TerminalSaveState()
        !           240: {
        !           241: #ifndef        USE_TERMIO
        !           242:     ioctl(0, TIOCGETP, (char *)&ottyb);
        !           243:     ioctl(0, TIOCGETC, (char *)&otc);
        !           244:     ioctl(0, TIOCGLTC, (char *)&oltc);
        !           245:     ioctl(0, TIOCLGET, (char *)&olmode);
        !           246:
        !           247:     ntc = otc;
        !           248:     nltc = oltc;
        !           249:     nttyb = ottyb;
        !           250:
        !           251: #else  /* USE_TERMIO */
        !           252:     tcgetattr(0, &old_tc);
        !           253:
        !           254:     new_tc = old_tc;
        !           255:
        !           256: #ifndef        VDISCARD
        !           257:     termFlushChar = CONTROL('O');
        !           258: #endif
        !           259: #ifndef        VWERASE
        !           260:     termWerasChar = CONTROL('W');
        !           261: #endif
        !           262: #ifndef        VREPRINT
        !           263:     termRprntChar = CONTROL('R');
        !           264: #endif
        !           265: #ifndef        VLNEXT
        !           266:     termLiteralNextChar = CONTROL('V');
        !           267: #endif
        !           268: #ifndef        VSTART
        !           269:     termStartChar = CONTROL('Q');
        !           270: #endif
        !           271: #ifndef        VSTOP
        !           272:     termStopChar = CONTROL('S');
        !           273: #endif
        !           274: #ifndef        VSTATUS
        !           275:     termAytChar = CONTROL('T');
        !           276: #endif
        !           277: #endif /* USE_TERMIO */
        !           278: }
        !           279:
        !           280:     cc_t *
        !           281: tcval(func)
        !           282:     register int func;
        !           283: {
        !           284:     switch(func) {
        !           285:     case SLC_IP:       return(&termIntChar);
        !           286:     case SLC_ABORT:    return(&termQuitChar);
        !           287:     case SLC_EOF:      return(&termEofChar);
        !           288:     case SLC_EC:       return(&termEraseChar);
        !           289:     case SLC_EL:       return(&termKillChar);
        !           290:     case SLC_XON:      return(&termStartChar);
        !           291:     case SLC_XOFF:     return(&termStopChar);
        !           292:     case SLC_FORW1:    return(&termForw1Char);
        !           293: #ifdef USE_TERMIO
        !           294:     case SLC_FORW2:    return(&termForw2Char);
        !           295: # ifdef        VDISCARD
        !           296:     case SLC_AO:       return(&termFlushChar);
        !           297: # endif
        !           298: # ifdef        VSUSP
        !           299:     case SLC_SUSP:     return(&termSuspChar);
        !           300: # endif
        !           301: # ifdef        VWERASE
        !           302:     case SLC_EW:       return(&termWerasChar);
        !           303: # endif
        !           304: # ifdef        VREPRINT
        !           305:     case SLC_RP:       return(&termRprntChar);
        !           306: # endif
        !           307: # ifdef        VLNEXT
        !           308:     case SLC_LNEXT:    return(&termLiteralNextChar);
        !           309: # endif
        !           310: # ifdef        VSTATUS
        !           311:     case SLC_AYT:      return(&termAytChar);
        !           312: # endif
        !           313: #endif
        !           314:
        !           315:     case SLC_SYNCH:
        !           316:     case SLC_BRK:
        !           317:     case SLC_EOR:
        !           318:     default:
        !           319:        return((cc_t *)0);
        !           320:     }
        !           321: }
        !           322:
        !           323:     void
        !           324: TerminalDefaultChars()
        !           325: {
        !           326: #ifndef        USE_TERMIO
        !           327:     ntc = otc;
        !           328:     nltc = oltc;
        !           329:     nttyb.sg_kill = ottyb.sg_kill;
        !           330:     nttyb.sg_erase = ottyb.sg_erase;
        !           331: #else  /* USE_TERMIO */
        !           332:     memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
        !           333: # ifndef       VDISCARD
        !           334:     termFlushChar = CONTROL('O');
        !           335: # endif
        !           336: # ifndef       VWERASE
        !           337:     termWerasChar = CONTROL('W');
        !           338: # endif
        !           339: # ifndef       VREPRINT
        !           340:     termRprntChar = CONTROL('R');
        !           341: # endif
        !           342: # ifndef       VLNEXT
        !           343:     termLiteralNextChar = CONTROL('V');
        !           344: # endif
        !           345: # ifndef       VSTART
        !           346:     termStartChar = CONTROL('Q');
        !           347: # endif
        !           348: # ifndef       VSTOP
        !           349:     termStopChar = CONTROL('S');
        !           350: # endif
        !           351: # ifndef       VSTATUS
        !           352:     termAytChar = CONTROL('T');
        !           353: # endif
        !           354: #endif /* USE_TERMIO */
        !           355: }
        !           356:
        !           357: #ifdef notdef
        !           358: void
        !           359: TerminalRestoreState()
        !           360: {
        !           361: }
        !           362: #endif
        !           363:
        !           364: /*
        !           365:  * TerminalNewMode - set up terminal to a specific mode.
        !           366:  *     MODE_ECHO: do local terminal echo
        !           367:  *     MODE_FLOW: do local flow control
        !           368:  *     MODE_TRAPSIG: do local mapping to TELNET IAC sequences
        !           369:  *     MODE_EDIT: do local line editing
        !           370:  *
        !           371:  *     Command mode:
        !           372:  *             MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
        !           373:  *             local echo
        !           374:  *             local editing
        !           375:  *             local xon/xoff
        !           376:  *             local signal mapping
        !           377:  *
        !           378:  *     Linemode:
        !           379:  *             local/no editing
        !           380:  *     Both Linemode and Single Character mode:
        !           381:  *             local/remote echo
        !           382:  *             local/no xon/xoff
        !           383:  *             local/no signal mapping
        !           384:  */
        !           385:
        !           386:
        !           387:     void
        !           388: TerminalNewMode(f)
        !           389:     register int f;
        !           390: {
        !           391:     static int prevmode = 0;
        !           392: #ifndef        USE_TERMIO
        !           393:     struct tchars tc;
        !           394:     struct ltchars ltc;
        !           395:     struct sgttyb sb;
        !           396:     int lmode;
        !           397: #else  /* USE_TERMIO */
        !           398:     struct termio tmp_tc;
        !           399: #endif /* USE_TERMIO */
        !           400:     int onoff;
        !           401:     int old;
        !           402:     cc_t esc;
        !           403:
        !           404:     globalmode = f&~MODE_FORCE;
        !           405:     if (prevmode == f)
        !           406:        return;
        !           407:
        !           408:     /*
        !           409:      * Write any outstanding data before switching modes
        !           410:      * ttyflush() returns 0 only when there is no more data
        !           411:      * left to write out, it returns -1 if it couldn't do
        !           412:      * anything at all, otherwise it returns 1 + the number
        !           413:      * of characters left to write.
        !           414: #ifndef        USE_TERMIO
        !           415:      * We would really like ask the kernel to wait for the output
        !           416:      * to drain, like we can do with the TCSADRAIN, but we don't have
        !           417:      * that option.  The only ioctl that waits for the output to
        !           418:      * drain, TIOCSETP, also flushes the input queue, which is NOT
        !           419:      * what we want (TIOCSETP is like TCSADFLUSH).
        !           420: #endif
        !           421:      */
        !           422:     old = ttyflush(SYNCHing|flushout);
        !           423:     if (old < 0 || old > 1) {
        !           424: #ifdef USE_TERMIO
        !           425:        tcgetattr(tin, &tmp_tc);
        !           426: #endif /* USE_TERMIO */
        !           427:        do {
        !           428:            /*
        !           429:             * Wait for data to drain, then flush again.
        !           430:             */
        !           431: #ifdef USE_TERMIO
        !           432:            tcsetattr(tin, TCSADRAIN, &tmp_tc);
        !           433: #endif /* USE_TERMIO */
        !           434:            old = ttyflush(SYNCHing|flushout);
        !           435:        } while (old < 0 || old > 1);
        !           436:     }
        !           437:
        !           438:     old = prevmode;
        !           439:     prevmode = f&~MODE_FORCE;
        !           440: #ifndef        USE_TERMIO
        !           441:     sb = nttyb;
        !           442:     tc = ntc;
        !           443:     ltc = nltc;
        !           444:     lmode = olmode;
        !           445: #else
        !           446:     tmp_tc = new_tc;
        !           447: #endif
        !           448:
        !           449:     if (f&MODE_ECHO) {
        !           450: #ifndef        USE_TERMIO
        !           451:        sb.sg_flags |= ECHO;
        !           452: #else
        !           453:        tmp_tc.c_lflag |= ECHO;
        !           454:        tmp_tc.c_oflag |= ONLCR;
        !           455:        if (crlf)
        !           456:                tmp_tc.c_iflag |= ICRNL;
        !           457: #endif
        !           458:     } else {
        !           459: #ifndef        USE_TERMIO
        !           460:        sb.sg_flags &= ~ECHO;
        !           461: #else
        !           462:        tmp_tc.c_lflag &= ~ECHO;
        !           463:        tmp_tc.c_oflag &= ~ONLCR;
        !           464: # ifdef notdef
        !           465:        if (crlf)
        !           466:                tmp_tc.c_iflag &= ~ICRNL;
        !           467: # endif
        !           468: #endif
        !           469:     }
        !           470:
        !           471:     if ((f&MODE_FLOW) == 0) {
        !           472: #ifndef        USE_TERMIO
        !           473:        tc.t_startc = _POSIX_VDISABLE;
        !           474:        tc.t_stopc = _POSIX_VDISABLE;
        !           475: #else
        !           476:        tmp_tc.c_iflag &= ~(IXOFF|IXON);        /* Leave the IXANY bit alone */
        !           477:     } else {
        !           478:        if (restartany < 0) {
        !           479:                tmp_tc.c_iflag |= IXOFF|IXON;   /* Leave the IXANY bit alone */
        !           480:        } else if (restartany > 0) {
        !           481:                tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
        !           482:        } else {
        !           483:                tmp_tc.c_iflag |= IXOFF|IXON;
        !           484:                tmp_tc.c_iflag &= ~IXANY;
        !           485:        }
        !           486: #endif
        !           487:     }
        !           488:
        !           489:     if ((f&MODE_TRAPSIG) == 0) {
        !           490: #ifndef        USE_TERMIO
        !           491:        tc.t_intrc = _POSIX_VDISABLE;
        !           492:        tc.t_quitc = _POSIX_VDISABLE;
        !           493:        tc.t_eofc = _POSIX_VDISABLE;
        !           494:        ltc.t_suspc = _POSIX_VDISABLE;
        !           495:        ltc.t_dsuspc = _POSIX_VDISABLE;
        !           496: #else
        !           497:        tmp_tc.c_lflag &= ~ISIG;
        !           498: #endif
        !           499:        localchars = 0;
        !           500:     } else {
        !           501: #ifdef USE_TERMIO
        !           502:        tmp_tc.c_lflag |= ISIG;
        !           503: #endif
        !           504:        localchars = 1;
        !           505:     }
        !           506:
        !           507:     if (f&MODE_EDIT) {
        !           508: #ifndef        USE_TERMIO
        !           509:        sb.sg_flags &= ~CBREAK;
        !           510:        sb.sg_flags |= CRMOD;
        !           511: #else
        !           512:        tmp_tc.c_lflag |= ICANON;
        !           513: #endif
        !           514:     } else {
        !           515: #ifndef        USE_TERMIO
        !           516:        sb.sg_flags |= CBREAK;
        !           517:        if (f&MODE_ECHO)
        !           518:            sb.sg_flags |= CRMOD;
        !           519:        else
        !           520:            sb.sg_flags &= ~CRMOD;
        !           521: #else
        !           522:        tmp_tc.c_lflag &= ~ICANON;
        !           523:        tmp_tc.c_iflag &= ~ICRNL;
        !           524:        tmp_tc.c_cc[VMIN] = 1;
        !           525:        tmp_tc.c_cc[VTIME] = 0;
        !           526: #endif
        !           527:     }
        !           528:
        !           529:     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
        !           530: #ifndef        USE_TERMIO
        !           531:        ltc.t_lnextc = _POSIX_VDISABLE;
        !           532: #else
        !           533: # ifdef VLNEXT
        !           534:        tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
        !           535: # endif
        !           536: #endif
        !           537:     }
        !           538:
        !           539:     if (f&MODE_SOFT_TAB) {
        !           540: #ifndef USE_TERMIO
        !           541:        sb.sg_flags |= XTABS;
        !           542: #else
        !           543: # ifdef        OXTABS
        !           544:        tmp_tc.c_oflag |= OXTABS;
        !           545: # endif
        !           546: # ifdef        TABDLY
        !           547:        tmp_tc.c_oflag &= ~TABDLY;
        !           548:        tmp_tc.c_oflag |= TAB3;
        !           549: # endif
        !           550: #endif
        !           551:     } else {
        !           552: #ifndef USE_TERMIO
        !           553:        sb.sg_flags &= ~XTABS;
        !           554: #else
        !           555: # ifdef        OXTABS
        !           556:        tmp_tc.c_oflag &= ~OXTABS;
        !           557: # endif
        !           558: # ifdef        TABDLY
        !           559:        tmp_tc.c_oflag &= ~TABDLY;
        !           560: # endif
        !           561: #endif
        !           562:     }
        !           563:
        !           564:     if (f&MODE_LIT_ECHO) {
        !           565: #ifndef USE_TERMIO
        !           566:        lmode &= ~LCTLECH;
        !           567: #else
        !           568: # ifdef        ECHOCTL
        !           569:        tmp_tc.c_lflag &= ~ECHOCTL;
        !           570: # endif
        !           571: #endif
        !           572:     } else {
        !           573: #ifndef USE_TERMIO
        !           574:        lmode |= LCTLECH;
        !           575: #else
        !           576: # ifdef        ECHOCTL
        !           577:        tmp_tc.c_lflag |= ECHOCTL;
        !           578: # endif
        !           579: #endif
        !           580:     }
        !           581:
        !           582:     if (f == -1) {
        !           583:        onoff = 0;
        !           584:     } else {
        !           585: #ifndef        USE_TERMIO
        !           586:        if (f & MODE_OUTBIN)
        !           587:                lmode |= LLITOUT;
        !           588:        else
        !           589:                lmode &= ~LLITOUT;
        !           590:
        !           591:        if (f & MODE_INBIN)
        !           592:                lmode |= LPASS8;
        !           593:        else
        !           594:                lmode &= ~LPASS8;
        !           595: #else
        !           596:        if (f & MODE_INBIN)
        !           597:                tmp_tc.c_iflag &= ~ISTRIP;
        !           598:        else
        !           599:                tmp_tc.c_iflag |= ISTRIP;
        !           600:        if (f & MODE_OUTBIN) {
        !           601:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
        !           602:                tmp_tc.c_cflag |= CS8;
        !           603:                tmp_tc.c_oflag &= ~OPOST;
        !           604:        } else {
        !           605:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
        !           606:                tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
        !           607:                tmp_tc.c_oflag |= OPOST;
        !           608:        }
        !           609: #endif
        !           610:        onoff = 1;
        !           611:     }
        !           612:
        !           613:     if (f != -1) {
        !           614: #ifdef SIGTSTP
        !           615:        SIG_FUNC_RET susp();
        !           616: #endif /* SIGTSTP */
        !           617: #ifdef SIGINFO
        !           618:        SIG_FUNC_RET ayt();
        !           619: #endif
        !           620:
        !           621: #ifdef SIGTSTP
        !           622:        (void) signal(SIGTSTP, susp);
        !           623: #endif /* SIGTSTP */
        !           624: #ifdef SIGINFO
        !           625:        (void) signal(SIGINFO, ayt);
        !           626: #endif
        !           627: #if    defined(USE_TERMIO) && defined(NOKERNINFO)
        !           628:        tmp_tc.c_lflag |= NOKERNINFO;
        !           629: #endif
        !           630:        /*
        !           631:         * We don't want to process ^Y here.  It's just another
        !           632:         * character that we'll pass on to the back end.  It has
        !           633:         * to process it because it will be processed when the
        !           634:         * user attempts to read it, not when we send it.
        !           635:         */
        !           636: #ifndef        USE_TERMIO
        !           637:        ltc.t_dsuspc = _POSIX_VDISABLE;
        !           638: #else
        !           639: # ifdef        VDSUSP
        !           640:        tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
        !           641: # endif
        !           642: #endif
        !           643: #ifdef USE_TERMIO
        !           644:        /*
        !           645:         * If the VEOL character is already set, then use VEOL2,
        !           646:         * otherwise use VEOL.
        !           647:         */
        !           648:        esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
        !           649:        if ((tmp_tc.c_cc[VEOL] != esc)
        !           650: # ifdef        VEOL2
        !           651:            && (tmp_tc.c_cc[VEOL2] != esc)
        !           652: # endif
        !           653:            ) {
        !           654:                if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
        !           655:                    tmp_tc.c_cc[VEOL] = esc;
        !           656: # ifdef        VEOL2
        !           657:                else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
        !           658:                    tmp_tc.c_cc[VEOL2] = esc;
        !           659: # endif
        !           660:        }
        !           661: #else
        !           662:        if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
        !           663:                tc.t_brkc = esc;
        !           664: #endif
        !           665:     } else {
        !           666: #ifdef SIGINFO
        !           667:        SIG_FUNC_RET ayt_status();
        !           668:
        !           669:        (void) signal(SIGINFO, ayt_status);
        !           670: #endif
        !           671: #ifdef SIGTSTP
        !           672:        (void) signal(SIGTSTP, SIG_DFL);
        !           673:        (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
        !           674: #endif /* SIGTSTP */
        !           675: #ifndef USE_TERMIO
        !           676:        ltc = oltc;
        !           677:        tc = otc;
        !           678:        sb = ottyb;
        !           679:        lmode = olmode;
        !           680: #else
        !           681:        tmp_tc = old_tc;
        !           682: #endif
        !           683:     }
        !           684: #ifndef USE_TERMIO
        !           685:     ioctl(tin, TIOCLSET, (char *)&lmode);
        !           686:     ioctl(tin, TIOCSLTC, (char *)&ltc);
        !           687:     ioctl(tin, TIOCSETC, (char *)&tc);
        !           688:     ioctl(tin, TIOCSETN, (char *)&sb);
        !           689: #else
        !           690:     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
        !           691:        tcsetattr(tin, TCSANOW, &tmp_tc);
        !           692: #endif
        !           693:
        !           694: #if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
        !           695: # if   !defined(sysV88)
        !           696:     ioctl(tin, FIONBIO, (char *)&onoff);
        !           697:     ioctl(tout, FIONBIO, (char *)&onoff);
        !           698: # endif
        !           699: #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
        !           700: #if    defined(TN3270)
        !           701:     if (noasynchtty == 0) {
        !           702:        ioctl(tin, FIOASYNC, (char *)&onoff);
        !           703:     }
        !           704: #endif /* defined(TN3270) */
        !           705:
        !           706: }
        !           707:
        !           708: #ifndef        B19200
        !           709: # define B19200 B9600
        !           710: #endif
        !           711:
        !           712: #ifndef        B38400
        !           713: # define B38400 B19200
        !           714: #endif
        !           715:
        !           716: /*
        !           717:  * This code assumes that the values B0, B50, B75...
        !           718:  * are in ascending order.  They do not have to be
        !           719:  * contiguous.
        !           720:  */
        !           721: struct termspeeds {
        !           722:        long speed;
        !           723:        long value;
        !           724: } termspeeds[] = {
        !           725:        { 0,     B0 },     { 50,    B50 },   { 75,    B75 },
        !           726:        { 110,   B110 },   { 134,   B134 },  { 150,   B150 },
        !           727:        { 200,   B200 },   { 300,   B300 },  { 600,   B600 },
        !           728:        { 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
        !           729:        { 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
        !           730:        { 38400, B38400 }, { -1,    B38400 }
        !           731: };
        !           732:
        !           733:     void
        !           734: TerminalSpeeds(ispeed, ospeed)
        !           735:     long *ispeed;
        !           736:     long *ospeed;
        !           737: {
        !           738:     register struct termspeeds *tp;
        !           739:     register long in, out;
        !           740:
        !           741:     out = cfgetospeed(&old_tc);
        !           742:     in = cfgetispeed(&old_tc);
        !           743:     if (in == 0)
        !           744:        in = out;
        !           745:
        !           746:     tp = termspeeds;
        !           747:     while ((tp->speed != -1) && (tp->value < in))
        !           748:        tp++;
        !           749:     *ispeed = tp->speed;
        !           750:
        !           751:     tp = termspeeds;
        !           752:     while ((tp->speed != -1) && (tp->value < out))
        !           753:        tp++;
        !           754:     *ospeed = tp->speed;
        !           755: }
        !           756:
        !           757:     int
        !           758: TerminalWindowSize(rows, cols)
        !           759:     long *rows, *cols;
        !           760: {
        !           761: #ifdef TIOCGWINSZ
        !           762:     struct winsize ws;
        !           763:
        !           764:     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
        !           765:        *rows = ws.ws_row;
        !           766:        *cols = ws.ws_col;
        !           767:        return 1;
        !           768:     }
        !           769: #endif /* TIOCGWINSZ */
        !           770:     return 0;
        !           771: }
        !           772:
        !           773:     int
        !           774: NetClose(fd)
        !           775:     int        fd;
        !           776: {
        !           777:     return close(fd);
        !           778: }
        !           779:
        !           780:
        !           781:     void
        !           782: NetNonblockingIO(fd, onoff)
        !           783:     int fd;
        !           784:     int onoff;
        !           785: {
        !           786:     ioctl(fd, FIONBIO, (char *)&onoff);
        !           787: }
        !           788:
        !           789: #if    defined(TN3270)
        !           790:     void
        !           791: NetSigIO(fd, onoff)
        !           792:     int fd;
        !           793:     int onoff;
        !           794: {
        !           795:     ioctl(fd, FIOASYNC, (char *)&onoff);       /* hear about input */
        !           796: }
        !           797:
        !           798:     void
        !           799: NetSetPgrp(fd)
        !           800:     int fd;
        !           801: {
        !           802:     int myPid;
        !           803:
        !           804:     myPid = getpid();
        !           805:     fcntl(fd, F_SETOWN, myPid);
        !           806: }
        !           807: #endif /*defined(TN3270)*/
        !           808: 
        !           809: /*
        !           810:  * Various signal handling routines.
        !           811:  */
        !           812:
        !           813:     /* ARGSUSED */
        !           814:     SIG_FUNC_RET
        !           815: deadpeer(sig)
        !           816:     int sig;
        !           817: {
        !           818:        setcommandmode();
        !           819:        longjmp(peerdied, -1);
        !           820: }
        !           821:
        !           822:     /* ARGSUSED */
        !           823:     SIG_FUNC_RET
        !           824: intr(sig)
        !           825:     int sig;
        !           826: {
        !           827:     if (localchars) {
        !           828:        intp();
        !           829:        return;
        !           830:     }
        !           831:     setcommandmode();
        !           832:     longjmp(toplevel, -1);
        !           833: }
        !           834:
        !           835:     /* ARGSUSED */
        !           836:     SIG_FUNC_RET
        !           837: intr2(sig)
        !           838:     int sig;
        !           839: {
        !           840:     if (localchars) {
        !           841: #ifdef KLUDGELINEMODE
        !           842:        if (kludgelinemode)
        !           843:            sendbrk();
        !           844:        else
        !           845: #endif
        !           846:            sendabort();
        !           847:        return;
        !           848:     }
        !           849: }
        !           850:
        !           851: #ifdef SIGTSTP
        !           852:     /* ARGSUSED */
        !           853:     SIG_FUNC_RET
        !           854: susp(sig)
        !           855:     int sig;
        !           856: {
        !           857:     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
        !           858:        return;
        !           859:     if (localchars)
        !           860:        sendsusp();
        !           861: }
        !           862: #endif
        !           863:
        !           864: #ifdef SIGWINCH
        !           865:     /* ARGSUSED */
        !           866:     SIG_FUNC_RET
        !           867: sendwin(sig)
        !           868:     int sig;
        !           869: {
        !           870:     if (connected) {
        !           871:        sendnaws();
        !           872:     }
        !           873: }
        !           874: #endif
        !           875:
        !           876: #ifdef SIGINFO
        !           877:     /* ARGSUSED */
        !           878:     SIG_FUNC_RET
        !           879: ayt(sig)
        !           880:     int sig;
        !           881: {
        !           882:     if (connected)
        !           883:        sendayt();
        !           884:     else
        !           885:        ayt_status();
        !           886: }
        !           887: #endif
        !           888:
        !           889: 
        !           890:     void
        !           891: sys_telnet_init()
        !           892: {
        !           893:     (void) signal(SIGINT, intr);
        !           894:     (void) signal(SIGQUIT, intr2);
        !           895:     (void) signal(SIGPIPE, deadpeer);
        !           896: #ifdef SIGWINCH
        !           897:     (void) signal(SIGWINCH, sendwin);
        !           898: #endif
        !           899: #ifdef SIGTSTP
        !           900:     (void) signal(SIGTSTP, susp);
        !           901: #endif
        !           902: #ifdef SIGINFO
        !           903:     (void) signal(SIGINFO, ayt);
        !           904: #endif
        !           905:
        !           906:     setconnmode(0);
        !           907:
        !           908:     NetNonblockingIO(net, 1);
        !           909:
        !           910: #if    defined(TN3270)
        !           911:     if (noasynchnet == 0) {                    /* DBX can't handle! */
        !           912:        NetSigIO(net, 1);
        !           913:        NetSetPgrp(net);
        !           914:     }
        !           915: #endif /* defined(TN3270) */
        !           916:
        !           917: #if    defined(SO_OOBINLINE)
        !           918:     if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
        !           919:        perror("SetSockOpt");
        !           920:     }
        !           921: #endif /* defined(SO_OOBINLINE) */
        !           922: }
        !           923:
        !           924: /*
        !           925:  * Process rings -
        !           926:  *
        !           927:  *     This routine tries to fill up/empty our various rings.
        !           928:  *
        !           929:  *     The parameter specifies whether this is a poll operation,
        !           930:  *     or a block-until-something-happens operation.
        !           931:  *
        !           932:  *     The return value is 1 if something happened, 0 if not.
        !           933:  */
        !           934:
        !           935:     int
        !           936: process_rings(netin, netout, netex, ttyin, ttyout, poll)
        !           937:     int poll;          /* If 0, then block until something to do */
        !           938: {
        !           939:     register int c;
        !           940:                /* One wants to be a bit careful about setting returnValue
        !           941:                 * to one, since a one implies we did some useful work,
        !           942:                 * and therefore probably won't be called to block next
        !           943:                 * time (TN3270 mode only).
        !           944:                 */
        !           945:     int returnValue = 0;
        !           946:     static struct timeval TimeValue = { 0 };
        !           947:
        !           948:     if (netout) {
        !           949:        FD_SET(net, &obits);
        !           950:     }
        !           951:     if (ttyout) {
        !           952:        FD_SET(tout, &obits);
        !           953:     }
        !           954: #if    defined(TN3270)
        !           955:     if (ttyin) {
        !           956:        FD_SET(tin, &ibits);
        !           957:     }
        !           958: #else  /* defined(TN3270) */
        !           959:     if (ttyin) {
        !           960:        FD_SET(tin, &ibits);
        !           961:     }
        !           962: #endif /* defined(TN3270) */
        !           963: #if    defined(TN3270)
        !           964:     if (netin) {
        !           965:        FD_SET(net, &ibits);
        !           966:     }
        !           967: #   else /* !defined(TN3270) */
        !           968:     if (netin) {
        !           969:        FD_SET(net, &ibits);
        !           970:     }
        !           971: #   endif /* !defined(TN3270) */
        !           972:     if (netex) {
        !           973:        FD_SET(net, &xbits);
        !           974:     }
        !           975:     if ((c = select(16, &ibits, &obits, &xbits,
        !           976:                        (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
        !           977:        if (c == -1) {
        !           978:                    /*
        !           979:                     * we can get EINTR if we are in line mode,
        !           980:                     * and the user does an escape (TSTP), or
        !           981:                     * some other signal generator.
        !           982:                     */
        !           983:            if (errno == EINTR) {
        !           984:                return 0;
        !           985:            }
        !           986: #          if defined(TN3270)
        !           987:                    /*
        !           988:                     * we can get EBADF if we were in transparent
        !           989:                     * mode, and the transcom process died.
        !           990:                    */
        !           991:            if (errno == EBADF) {
        !           992:                        /*
        !           993:                         * zero the bits (even though kernel does it)
        !           994:                         * to make sure we are selecting on the right
        !           995:                         * ones.
        !           996:                        */
        !           997:                FD_ZERO(&ibits);
        !           998:                FD_ZERO(&obits);
        !           999:                FD_ZERO(&xbits);
        !          1000:                return 0;
        !          1001:            }
        !          1002: #          endif /* defined(TN3270) */
        !          1003:                    /* I don't like this, does it ever happen? */
        !          1004:            printf("sleep(5) from telnet, after select\r\n");
        !          1005:            sleep(5);
        !          1006:        }
        !          1007:        return 0;
        !          1008:     }
        !          1009:
        !          1010:     /*
        !          1011:      * Any urgent data?
        !          1012:      */
        !          1013:     if (FD_ISSET(net, &xbits)) {
        !          1014:        FD_CLR(net, &xbits);
        !          1015:        SYNCHing = 1;
        !          1016:        (void) ttyflush(1);     /* flush already enqueued data */
        !          1017:     }
        !          1018:
        !          1019:     /*
        !          1020:      * Something to read from the network...
        !          1021:      */
        !          1022:     if (FD_ISSET(net, &ibits)) {
        !          1023:        int canread;
        !          1024:
        !          1025:        FD_CLR(net, &ibits);
        !          1026:        canread = ring_empty_consecutive(&netiring);
        !          1027: #if    !defined(SO_OOBINLINE)
        !          1028:            /*
        !          1029:             * In 4.2 (and some early 4.3) systems, the
        !          1030:             * OOB indication and data handling in the kernel
        !          1031:             * is such that if two separate TCP Urgent requests
        !          1032:             * come in, one byte of TCP data will be overlaid.
        !          1033:             * This is fatal for Telnet, but we try to live
        !          1034:             * with it.
        !          1035:             *
        !          1036:             * In addition, in 4.2 (and...), a special protocol
        !          1037:             * is needed to pick up the TCP Urgent data in
        !          1038:             * the correct sequence.
        !          1039:             *
        !          1040:             * What we do is:  if we think we are in urgent
        !          1041:             * mode, we look to see if we are "at the mark".
        !          1042:             * If we are, we do an OOB receive.  If we run
        !          1043:             * this twice, we will do the OOB receive twice,
        !          1044:             * but the second will fail, since the second
        !          1045:             * time we were "at the mark", but there wasn't
        !          1046:             * any data there (the kernel doesn't reset
        !          1047:             * "at the mark" until we do a normal read).
        !          1048:             * Once we've read the OOB data, we go ahead
        !          1049:             * and do normal reads.
        !          1050:             *
        !          1051:             * There is also another problem, which is that
        !          1052:             * since the OOB byte we read doesn't put us
        !          1053:             * out of OOB state, and since that byte is most
        !          1054:             * likely the TELNET DM (data mark), we would
        !          1055:             * stay in the TELNET SYNCH (SYNCHing) state.
        !          1056:             * So, clocks to the rescue.  If we've "just"
        !          1057:             * received a DM, then we test for the
        !          1058:             * presence of OOB data when the receive OOB
        !          1059:             * fails (and AFTER we did the normal mode read
        !          1060:             * to clear "at the mark").
        !          1061:             */
        !          1062:        if (SYNCHing) {
        !          1063:            int atmark;
        !          1064:            static int bogus_oob = 0, first = 1;
        !          1065:
        !          1066:            ioctl(net, SIOCATMARK, (char *)&atmark);
        !          1067:            if (atmark) {
        !          1068:                c = recv(net, netiring.supply, canread, MSG_OOB);
        !          1069:                if ((c == -1) && (errno == EINVAL)) {
        !          1070:                    c = recv(net, netiring.supply, canread, 0);
        !          1071:                    if (clocks.didnetreceive < clocks.gotDM) {
        !          1072:                        SYNCHing = stilloob(net);
        !          1073:                    }
        !          1074:                } else if (first && c > 0) {
        !          1075:                    /*
        !          1076:                     * Bogosity check.  Systems based on 4.2BSD
        !          1077:                     * do not return an error if you do a second
        !          1078:                     * recv(MSG_OOB).  So, we do one.  If it
        !          1079:                     * succeeds and returns exactly the same
        !          1080:                     * data, then assume that we are running
        !          1081:                     * on a broken system and set the bogus_oob
        !          1082:                     * flag.  (If the data was different, then
        !          1083:                     * we probably got some valid new data, so
        !          1084:                     * increment the count...)
        !          1085:                     */
        !          1086:                    int i;
        !          1087:                    i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
        !          1088:                    if (i == c &&
        !          1089:                          bcmp(netiring.supply, netiring.supply + c, i) == 0) {
        !          1090:                        bogus_oob = 1;
        !          1091:                        first = 0;
        !          1092:                    } else if (i < 0) {
        !          1093:                        bogus_oob = 0;
        !          1094:                        first = 0;
        !          1095:                    } else
        !          1096:                        c += i;
        !          1097:                }
        !          1098:                if (bogus_oob && c > 0) {
        !          1099:                    int i;
        !          1100:                    /*
        !          1101:                     * Bogosity.  We have to do the read
        !          1102:                     * to clear the atmark to get out of
        !          1103:                     * an infinate loop.
        !          1104:                     */
        !          1105:                    i = read(net, netiring.supply + c, canread - c);
        !          1106:                    if (i > 0)
        !          1107:                        c += i;
        !          1108:                }
        !          1109:            } else {
        !          1110:                c = recv(net, netiring.supply, canread, 0);
        !          1111:            }
        !          1112:        } else {
        !          1113:            c = recv(net, netiring.supply, canread, 0);
        !          1114:        }
        !          1115:        settimer(didnetreceive);
        !          1116: #else  /* !defined(SO_OOBINLINE) */
        !          1117:        c = recv(net, (char *)netiring.supply, canread, 0);
        !          1118: #endif /* !defined(SO_OOBINLINE) */
        !          1119:        if (c < 0 && errno == EWOULDBLOCK) {
        !          1120:            c = 0;
        !          1121:        } else if (c <= 0) {
        !          1122:            return -1;
        !          1123:        }
        !          1124:        if (netdata) {
        !          1125:            Dump('<', netiring.supply, c);
        !          1126:        }
        !          1127:        if (c)
        !          1128:            ring_supplied(&netiring, c);
        !          1129:        returnValue = 1;
        !          1130:     }
        !          1131:
        !          1132:     /*
        !          1133:      * Something to read from the tty...
        !          1134:      */
        !          1135:     if (FD_ISSET(tin, &ibits)) {
        !          1136:        FD_CLR(tin, &ibits);
        !          1137:        c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
        !          1138:        if (c < 0 && errno == EWOULDBLOCK) {
        !          1139:            c = 0;
        !          1140:        } else {
        !          1141:            if (c < 0) {
        !          1142:                return -1;
        !          1143:            }
        !          1144:            if (c == 0) {
        !          1145:                /* must be an EOF... */
        !          1146:                if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
        !          1147:                    *ttyiring.supply = termEofChar;
        !          1148:                    c = 1;
        !          1149:                } else {
        !          1150:                    clienteof = 1;
        !          1151:                    shutdown(net, 1);
        !          1152:                    return 0;
        !          1153:                }
        !          1154:            }
        !          1155:            if (termdata) {
        !          1156:                Dump('<', ttyiring.supply, c);
        !          1157:            }
        !          1158:            ring_supplied(&ttyiring, c);
        !          1159:        }
        !          1160:        returnValue = 1;                /* did something useful */
        !          1161:     }
        !          1162:
        !          1163:     if (FD_ISSET(net, &obits)) {
        !          1164:        FD_CLR(net, &obits);
        !          1165:        returnValue |= netflush();
        !          1166:     }
        !          1167:     if (FD_ISSET(tout, &obits)) {
        !          1168:        FD_CLR(tout, &obits);
        !          1169:        returnValue |= (ttyflush(SYNCHing|flushout) > 0);
        !          1170:     }
        !          1171:
        !          1172:     return returnValue;
        !          1173: }