Annotation of 43BSDReno/usr.bin/telnet/sys_bsd.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.