Annotation of 43BSDReno/usr.bin/telnet/sys_bsd.c, revision 1.1.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.