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

Annotation of src/usr.bin/telnet/sys_bsd.c, Revision 1.17

1.17    ! guenther    1: /*     $OpenBSD: sys_bsd.c,v 1.16 2014/07/19 23:50:38 guenther Exp $   */
1.3       niklas      2: /*     $NetBSD: sys_bsd.c,v 1.11 1996/02/28 21:04:10 thorpej Exp $     */
                      3:
1.1       deraadt     4: /*
                      5:  * Copyright (c) 1988, 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
1.14      millert    16:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
1.5       art        33: #include "telnet_locl.h"
1.17    ! guenther   34: #include <sys/ioctl.h>
        !            35: #include <poll.h>
1.1       deraadt    36:
                     37: /*
                     38:  * The following routines try to encapsulate what is system dependent
                     39:  * (at least between 4.x and dos) which is used in telnet.c.
                     40:  */
                     41:
                     42: int
                     43:        tout,                   /* Output file descriptor */
                     44:        tin,                    /* Input file descriptor */
                     45:        net;
                     46:
1.15      millert    47: #define TELNET_FD_TOUT 0
                     48: #define TELNET_FD_TIN  1
                     49: #define TELNET_FD_NET  2
                     50: #define TELNET_FD_NUM  3
                     51:
1.5       art        52: struct termios old_tc = { 0 };
                     53: extern struct termios new_tc;
1.1       deraadt    54:
                     55:     void
                     56: init_sys()
                     57: {
                     58:     tout = fileno(stdout);
                     59:     tin = fileno(stdin);
                     60:
                     61:     errno = 0;
                     62: }
                     63:
                     64:
                     65:     int
                     66: TerminalWrite(buf, n)
                     67:     char *buf;
                     68:     int  n;
                     69: {
                     70:     return write(tout, buf, n);
                     71: }
                     72:
                     73:     int
                     74: TerminalRead(buf, n)
1.3       niklas     75:     unsigned char *buf;
1.1       deraadt    76:     int  n;
                     77: {
                     78:     return read(tin, buf, n);
                     79: }
                     80:
                     81: /*
                     82:  *
                     83:  */
                     84:
                     85:     int
                     86: TerminalAutoFlush()
                     87: {
                     88: #if    defined(LNOFLSH)
                     89:     int flush;
                     90:
                     91:     ioctl(0, TIOCLGET, (char *)&flush);
                     92:     return !(flush&LNOFLSH);   /* if LNOFLSH, no autoflush */
                     93: #else  /* LNOFLSH */
                     94:     return 1;
                     95: #endif /* LNOFLSH */
                     96: }
                     97:
                     98: #ifdef KLUDGELINEMODE
                     99: extern int kludgelinemode;
                    100: #endif
                    101: /*
                    102:  * TerminalSpecialChars()
                    103:  *
                    104:  * Look at an input character to see if it is a special character
                    105:  * and decide what to do.
                    106:  *
                    107:  * Output:
                    108:  *
                    109:  *     0       Don't add this character.
                    110:  *     1       Do add this character
                    111:  */
                    112:
                    113:     int
                    114: TerminalSpecialChars(c)
                    115:     int        c;
                    116: {
                    117:     if (c == termIntChar) {
                    118:        intp();
                    119:        return 0;
                    120:     } else if (c == termQuitChar) {
                    121: #ifdef KLUDGELINEMODE
                    122:        if (kludgelinemode)
                    123:            sendbrk();
                    124:        else
                    125: #endif
                    126:            sendabort();
                    127:        return 0;
                    128:     } else if (c == termEofChar) {
                    129:        if (my_want_state_is_will(TELOPT_LINEMODE)) {
                    130:            sendeof();
                    131:            return 0;
                    132:        }
                    133:        return 1;
                    134:     } else if (c == termSuspChar) {
                    135:        sendsusp();
                    136:        return(0);
                    137:     } else if (c == termFlushChar) {
                    138:        xmitAO();               /* Transmit Abort Output */
                    139:        return 0;
                    140:     } else if (!MODE_LOCAL_CHARS(globalmode)) {
                    141:        if (c == termKillChar) {
                    142:            xmitEL();
                    143:            return 0;
                    144:        } else if (c == termEraseChar) {
                    145:            xmitEC();           /* Transmit Erase Character */
                    146:            return 0;
                    147:        }
                    148:     }
                    149:     return 1;
                    150: }
                    151:
                    152:
                    153: /*
                    154:  * Flush output to the terminal
                    155:  */
1.3       niklas    156:
1.1       deraadt   157:     void
                    158: TerminalFlushOutput()
                    159: {
                    160: #ifdef TIOCFLUSH
1.7       deraadt   161:     int com = FWRITE;
                    162:     (void) ioctl(fileno(stdout), TIOCFLUSH, (int *) &com);
1.1       deraadt   163: #else
1.7       deraadt   164:     (void) ioctl(fileno(stdout), TCFLSH, (int *) 0);
1.1       deraadt   165: #endif
                    166: }
                    167:
                    168:     void
                    169: TerminalSaveState()
                    170: {
                    171:     tcgetattr(0, &old_tc);
                    172:
                    173:     new_tc = old_tc;
                    174:
                    175: #ifndef        VDISCARD
                    176:     termFlushChar = CONTROL('O');
                    177: #endif
                    178: #ifndef        VWERASE
                    179:     termWerasChar = CONTROL('W');
                    180: #endif
                    181: #ifndef        VREPRINT
                    182:     termRprntChar = CONTROL('R');
                    183: #endif
                    184: #ifndef        VLNEXT
                    185:     termLiteralNextChar = CONTROL('V');
                    186: #endif
                    187: #ifndef        VSTART
                    188:     termStartChar = CONTROL('Q');
                    189: #endif
                    190: #ifndef        VSTOP
                    191:     termStopChar = CONTROL('S');
                    192: #endif
                    193: #ifndef        VSTATUS
                    194:     termAytChar = CONTROL('T');
                    195: #endif
                    196: }
                    197:
                    198:     cc_t *
                    199: tcval(func)
1.10      mpech     200:     int func;
1.1       deraadt   201: {
                    202:     switch(func) {
                    203:     case SLC_IP:       return(&termIntChar);
                    204:     case SLC_ABORT:    return(&termQuitChar);
                    205:     case SLC_EOF:      return(&termEofChar);
                    206:     case SLC_EC:       return(&termEraseChar);
                    207:     case SLC_EL:       return(&termKillChar);
                    208:     case SLC_XON:      return(&termStartChar);
                    209:     case SLC_XOFF:     return(&termStopChar);
                    210:     case SLC_FORW1:    return(&termForw1Char);
                    211:     case SLC_FORW2:    return(&termForw2Char);
                    212: # ifdef        VDISCARD
                    213:     case SLC_AO:       return(&termFlushChar);
                    214: # endif
                    215: # ifdef        VSUSP
                    216:     case SLC_SUSP:     return(&termSuspChar);
                    217: # endif
                    218: # ifdef        VWERASE
                    219:     case SLC_EW:       return(&termWerasChar);
                    220: # endif
                    221: # ifdef        VREPRINT
                    222:     case SLC_RP:       return(&termRprntChar);
                    223: # endif
                    224: # ifdef        VLNEXT
                    225:     case SLC_LNEXT:    return(&termLiteralNextChar);
                    226: # endif
                    227: # ifdef        VSTATUS
                    228:     case SLC_AYT:      return(&termAytChar);
                    229: # endif
                    230:
                    231:     case SLC_SYNCH:
                    232:     case SLC_BRK:
                    233:     case SLC_EOR:
                    234:     default:
                    235:        return((cc_t *)0);
                    236:     }
                    237: }
                    238:
                    239:     void
                    240: TerminalDefaultChars()
                    241: {
1.3       niklas    242:     memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
1.1       deraadt   243: # ifndef       VDISCARD
                    244:     termFlushChar = CONTROL('O');
                    245: # endif
                    246: # ifndef       VWERASE
                    247:     termWerasChar = CONTROL('W');
                    248: # endif
                    249: # ifndef       VREPRINT
                    250:     termRprntChar = CONTROL('R');
                    251: # endif
                    252: # ifndef       VLNEXT
                    253:     termLiteralNextChar = CONTROL('V');
                    254: # endif
                    255: # ifndef       VSTART
                    256:     termStartChar = CONTROL('Q');
                    257: # endif
                    258: # ifndef       VSTOP
                    259:     termStopChar = CONTROL('S');
                    260: # endif
                    261: # ifndef       VSTATUS
                    262:     termAytChar = CONTROL('T');
                    263: # endif
                    264: }
                    265:
                    266: /*
                    267:  * TerminalNewMode - set up terminal to a specific mode.
                    268:  *     MODE_ECHO: do local terminal echo
                    269:  *     MODE_FLOW: do local flow control
                    270:  *     MODE_TRAPSIG: do local mapping to TELNET IAC sequences
                    271:  *     MODE_EDIT: do local line editing
                    272:  *
                    273:  *     Command mode:
                    274:  *             MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
                    275:  *             local echo
                    276:  *             local editing
                    277:  *             local xon/xoff
                    278:  *             local signal mapping
                    279:  *
                    280:  *     Linemode:
                    281:  *             local/no editing
                    282:  *     Both Linemode and Single Character mode:
                    283:  *             local/remote echo
                    284:  *             local/no xon/xoff
                    285:  *             local/no signal mapping
                    286:  */
                    287:
1.5       art       288: #ifdef SIGTSTP
                    289: static void susp();
                    290: #endif /* SIGTSTP */
                    291: #ifdef SIGINFO
                    292: static void ayt();
                    293: #endif
1.1       deraadt   294:
                    295:     void
                    296: TerminalNewMode(f)
1.10      mpech     297:     int f;
1.1       deraadt   298: {
                    299:     static int prevmode = 0;
1.5       art       300:     struct termios tmp_tc;
1.1       deraadt   301:     int onoff;
                    302:     int old;
                    303:     cc_t esc;
                    304:
                    305:     globalmode = f&~MODE_FORCE;
                    306:     if (prevmode == f)
                    307:        return;
                    308:
                    309:     /*
                    310:      * Write any outstanding data before switching modes
                    311:      * ttyflush() returns 0 only when there is no more data
                    312:      * left to write out, it returns -1 if it couldn't do
                    313:      * anything at all, otherwise it returns 1 + the number
                    314:      * of characters left to write.
                    315:      */
                    316:     old = ttyflush(SYNCHing|flushout);
                    317:     if (old < 0 || old > 1) {
                    318:        tcgetattr(tin, &tmp_tc);
                    319:        do {
                    320:            /*
                    321:             * Wait for data to drain, then flush again.
                    322:             */
                    323:            tcsetattr(tin, TCSADRAIN, &tmp_tc);
                    324:            old = ttyflush(SYNCHing|flushout);
                    325:        } while (old < 0 || old > 1);
                    326:     }
                    327:
                    328:     old = prevmode;
                    329:     prevmode = f&~MODE_FORCE;
                    330:     tmp_tc = new_tc;
                    331:
                    332:     if (f&MODE_ECHO) {
                    333:        tmp_tc.c_lflag |= ECHO;
                    334:        tmp_tc.c_oflag |= ONLCR;
                    335:        if (crlf)
                    336:                tmp_tc.c_iflag |= ICRNL;
                    337:     } else {
                    338:        tmp_tc.c_lflag &= ~ECHO;
                    339:        tmp_tc.c_oflag &= ~ONLCR;
                    340:     }
                    341:
                    342:     if ((f&MODE_FLOW) == 0) {
                    343:        tmp_tc.c_iflag &= ~(IXOFF|IXON);        /* Leave the IXANY bit alone */
                    344:     } else {
                    345:        if (restartany < 0) {
                    346:                tmp_tc.c_iflag |= IXOFF|IXON;   /* Leave the IXANY bit alone */
                    347:        } else if (restartany > 0) {
                    348:                tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
                    349:        } else {
                    350:                tmp_tc.c_iflag |= IXOFF|IXON;
                    351:                tmp_tc.c_iflag &= ~IXANY;
                    352:        }
                    353:     }
                    354:
                    355:     if ((f&MODE_TRAPSIG) == 0) {
                    356:        tmp_tc.c_lflag &= ~ISIG;
                    357:        localchars = 0;
                    358:     } else {
                    359:        tmp_tc.c_lflag |= ISIG;
                    360:        localchars = 1;
                    361:     }
                    362:
                    363:     if (f&MODE_EDIT) {
                    364:        tmp_tc.c_lflag |= ICANON;
                    365:     } else {
                    366:        tmp_tc.c_lflag &= ~ICANON;
                    367:        tmp_tc.c_iflag &= ~ICRNL;
                    368:        tmp_tc.c_cc[VMIN] = 1;
                    369:        tmp_tc.c_cc[VTIME] = 0;
                    370:     }
                    371:
                    372:     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
1.2       niklas    373:        tmp_tc.c_lflag &= ~IEXTEN;
1.1       deraadt   374:     }
                    375:
                    376:     if (f&MODE_SOFT_TAB) {
                    377: # ifdef        OXTABS
                    378:        tmp_tc.c_oflag |= OXTABS;
                    379: # endif
                    380: # ifdef        TABDLY
                    381:        tmp_tc.c_oflag &= ~TABDLY;
                    382:        tmp_tc.c_oflag |= TAB3;
                    383: # endif
                    384:     } else {
                    385: # ifdef        OXTABS
                    386:        tmp_tc.c_oflag &= ~OXTABS;
                    387: # endif
                    388: # ifdef        TABDLY
                    389:        tmp_tc.c_oflag &= ~TABDLY;
                    390: # endif
                    391:     }
                    392:
                    393:     if (f&MODE_LIT_ECHO) {
                    394: # ifdef        ECHOCTL
                    395:        tmp_tc.c_lflag &= ~ECHOCTL;
                    396: # endif
                    397:     } else {
                    398: # ifdef        ECHOCTL
                    399:        tmp_tc.c_lflag |= ECHOCTL;
                    400: # endif
                    401:     }
                    402:
                    403:     if (f == -1) {
                    404:        onoff = 0;
                    405:     } else {
                    406:        if (f & MODE_INBIN)
                    407:                tmp_tc.c_iflag &= ~ISTRIP;
                    408:        else
                    409:                tmp_tc.c_iflag |= ISTRIP;
1.5       art       410:        if ((f & MODE_OUTBIN) || (f & MODE_OUT8)) {
1.1       deraadt   411:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
                    412:                tmp_tc.c_cflag |= CS8;
1.5       art       413:                if(f & MODE_OUTBIN)
                    414:                        tmp_tc.c_oflag &= ~OPOST;
                    415:                else
                    416:                        tmp_tc.c_oflag |= OPOST;
                    417:
1.1       deraadt   418:        } else {
                    419:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
                    420:                tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
                    421:                tmp_tc.c_oflag |= OPOST;
                    422:        }
                    423:        onoff = 1;
                    424:     }
                    425:
                    426:     if (f != -1) {
                    427: #ifdef SIGTSTP
                    428:        (void) signal(SIGTSTP, susp);
                    429: #endif /* SIGTSTP */
                    430: #ifdef SIGINFO
                    431:        (void) signal(SIGINFO, ayt);
                    432: #endif
1.16      guenther  433: #if    defined(NOKERNINFO)
1.1       deraadt   434:        tmp_tc.c_lflag |= NOKERNINFO;
                    435: #endif
                    436:        /*
                    437:         * We don't want to process ^Y here.  It's just another
                    438:         * character that we'll pass on to the back end.  It has
                    439:         * to process it because it will be processed when the
                    440:         * user attempts to read it, not when we send it.
                    441:         */
                    442: # ifdef        VDSUSP
                    443:        tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
                    444: # endif
                    445:        /*
                    446:         * If the VEOL character is already set, then use VEOL2,
                    447:         * otherwise use VEOL.
                    448:         */
                    449:        esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
                    450:        if ((tmp_tc.c_cc[VEOL] != esc)
                    451: # ifdef        VEOL2
                    452:            && (tmp_tc.c_cc[VEOL2] != esc)
                    453: # endif
                    454:            ) {
                    455:                if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
                    456:                    tmp_tc.c_cc[VEOL] = esc;
                    457: # ifdef        VEOL2
                    458:                else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
                    459:                    tmp_tc.c_cc[VEOL2] = esc;
                    460: # endif
                    461:        }
                    462:     } else {
1.9       millert   463: #ifdef SIGTSTP
                    464:        sigset_t mask;
                    465: #endif /* SIGTSTP */
1.1       deraadt   466: #ifdef SIGINFO
1.5       art       467:        void ayt_status();
1.1       deraadt   468:
1.5       art       469:        (void) signal(SIGINFO, (void (*)(int))ayt_status);
1.1       deraadt   470: #endif
                    471: #ifdef SIGTSTP
                    472:        (void) signal(SIGTSTP, SIG_DFL);
1.9       millert   473:        sigemptyset(&mask);
                    474:        sigaddset(&mask, SIGTSTP);
                    475:        sigprocmask(SIG_UNBLOCK, &mask, NULL);
1.1       deraadt   476: #endif /* SIGTSTP */
                    477:        tmp_tc = old_tc;
                    478:     }
                    479:     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
                    480:        tcsetattr(tin, TCSANOW, &tmp_tc);
                    481:
                    482:     ioctl(tin, FIONBIO, (char *)&onoff);
                    483:     ioctl(tout, FIONBIO, (char *)&onoff);
                    484: }
                    485:
1.3       niklas    486: /*
                    487:  * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
                    488:  */
                    489: #if B4800 != 4800
                    490: #define        DECODE_BAUD
                    491: #endif
                    492:
                    493: #ifdef DECODE_BAUD
                    494: #ifndef        B7200
                    495: #define B7200   B4800
                    496: #endif
                    497:
                    498: #ifndef        B14400
                    499: #define B14400  B9600
                    500: #endif
                    501:
1.1       deraadt   502: #ifndef        B19200
1.3       niklas    503: # define B19200 B14400
                    504: #endif
                    505:
                    506: #ifndef        B28800
                    507: #define B28800  B19200
1.1       deraadt   508: #endif
                    509:
                    510: #ifndef        B38400
1.3       niklas    511: # define B38400 B28800
                    512: #endif
                    513:
                    514: #ifndef B57600
                    515: #define B57600  B38400
1.1       deraadt   516: #endif
                    517:
1.3       niklas    518: #ifndef B76800
                    519: #define B76800  B57600
                    520: #endif
                    521:
                    522: #ifndef B115200
                    523: #define B115200 B76800
                    524: #endif
                    525:
                    526: #ifndef B230400
                    527: #define B230400 B115200
                    528: #endif
                    529:
                    530:
1.1       deraadt   531: /*
                    532:  * This code assumes that the values B0, B50, B75...
                    533:  * are in ascending order.  They do not have to be
                    534:  * contiguous.
                    535:  */
                    536: struct termspeeds {
                    537:        long speed;
                    538:        long value;
                    539: } termspeeds[] = {
1.3       niklas    540:        { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
                    541:        { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
                    542:        { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
                    543:        { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
                    544:        { 4800,   B4800 },   { 7200,  B7200 },  { 9600,   B9600 },
                    545:        { 14400,  B14400 },  { 19200, B19200 }, { 28800,  B28800 },
                    546:        { 38400,  B38400 },  { 57600, B57600 }, { 115200, B115200 },
                    547:        { 230400, B230400 }, { -1,    B230400 }
1.1       deraadt   548: };
1.3       niklas    549: #endif /* DECODE_BAUD */
1.1       deraadt   550:
                    551:     void
                    552: TerminalSpeeds(ispeed, ospeed)
                    553:     long *ispeed;
                    554:     long *ospeed;
                    555: {
1.3       niklas    556: #ifdef DECODE_BAUD
1.10      mpech     557:     struct termspeeds *tp;
1.3       niklas    558: #endif /* DECODE_BAUD */
1.10      mpech     559:     long in, out;
1.1       deraadt   560:
                    561:     out = cfgetospeed(&old_tc);
                    562:     in = cfgetispeed(&old_tc);
                    563:     if (in == 0)
                    564:        in = out;
                    565:
1.3       niklas    566: #ifdef DECODE_BAUD
1.1       deraadt   567:     tp = termspeeds;
                    568:     while ((tp->speed != -1) && (tp->value < in))
                    569:        tp++;
                    570:     *ispeed = tp->speed;
                    571:
                    572:     tp = termspeeds;
                    573:     while ((tp->speed != -1) && (tp->value < out))
                    574:        tp++;
                    575:     *ospeed = tp->speed;
1.3       niklas    576: #else  /* DECODE_BAUD */
                    577:        *ispeed = in;
                    578:        *ospeed = out;
                    579: #endif /* DECODE_BAUD */
1.1       deraadt   580: }
                    581:
                    582:     int
                    583: TerminalWindowSize(rows, cols)
                    584:     long *rows, *cols;
                    585: {
                    586: #ifdef TIOCGWINSZ
                    587:     struct winsize ws;
                    588:
                    589:     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
                    590:        *rows = ws.ws_row;
                    591:        *cols = ws.ws_col;
                    592:        return 1;
                    593:     }
                    594: #endif /* TIOCGWINSZ */
                    595:     return 0;
                    596: }
                    597:
                    598:     int
                    599: NetClose(fd)
                    600:     int        fd;
                    601: {
                    602:     return close(fd);
                    603: }
                    604:
                    605:
                    606:     void
                    607: NetNonblockingIO(fd, onoff)
                    608:     int fd;
                    609:     int onoff;
                    610: {
                    611:     ioctl(fd, FIONBIO, (char *)&onoff);
                    612: }
                    613:
                    614: 
                    615: /*
                    616:  * Various signal handling routines.
                    617:  */
                    618:
                    619:     /* ARGSUSED */
1.5       art       620:     void
1.1       deraadt   621: deadpeer(sig)
                    622:     int sig;
                    623: {
                    624:        setcommandmode();
                    625:        longjmp(peerdied, -1);
                    626: }
                    627:
1.12      hin       628: volatile sig_atomic_t intr_happened = 0;
                    629: volatile sig_atomic_t intr_waiting = 0;
1.11      hin       630:
1.1       deraadt   631:     /* ARGSUSED */
1.5       art       632:     void
1.1       deraadt   633: intr(sig)
                    634:     int sig;
                    635: {
1.11      hin       636:     if (intr_waiting) {
                    637:        intr_happened = 1;
                    638:        return;
                    639:     }
1.1       deraadt   640:     if (localchars) {
                    641:        intp();
                    642:        return;
                    643:     }
                    644:     setcommandmode();
                    645:     longjmp(toplevel, -1);
                    646: }
                    647:
                    648:     /* ARGSUSED */
1.5       art       649:     void
1.1       deraadt   650: intr2(sig)
                    651:     int sig;
                    652: {
                    653:     if (localchars) {
                    654: #ifdef KLUDGELINEMODE
                    655:        if (kludgelinemode)
                    656:            sendbrk();
                    657:        else
                    658: #endif
                    659:            sendabort();
                    660:        return;
                    661:     }
                    662: }
                    663:
                    664: #ifdef SIGTSTP
                    665:     /* ARGSUSED */
1.5       art       666:     void
1.1       deraadt   667: susp(sig)
                    668:     int sig;
                    669: {
                    670:     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
                    671:        return;
                    672:     if (localchars)
                    673:        sendsusp();
                    674: }
                    675: #endif
                    676:
                    677: #ifdef SIGWINCH
                    678:     /* ARGSUSED */
1.5       art       679:     void
1.1       deraadt   680: sendwin(sig)
                    681:     int sig;
                    682: {
                    683:     if (connected) {
                    684:        sendnaws();
                    685:     }
                    686: }
                    687: #endif
                    688:
                    689: #ifdef SIGINFO
                    690:     /* ARGSUSED */
1.5       art       691:     void
1.1       deraadt   692: ayt(sig)
                    693:     int sig;
                    694: {
                    695:     if (connected)
                    696:        sendayt();
                    697:     else
                    698:        ayt_status();
                    699: }
                    700: #endif
                    701:
                    702: 
                    703:     void
                    704: sys_telnet_init()
                    705: {
1.16      guenther  706:     int one = 1;
                    707:
1.1       deraadt   708:     (void) signal(SIGINT, intr);
                    709:     (void) signal(SIGQUIT, intr2);
                    710:     (void) signal(SIGPIPE, deadpeer);
                    711: #ifdef SIGWINCH
                    712:     (void) signal(SIGWINCH, sendwin);
                    713: #endif
                    714: #ifdef SIGTSTP
                    715:     (void) signal(SIGTSTP, susp);
                    716: #endif
                    717: #ifdef SIGINFO
                    718:     (void) signal(SIGINFO, ayt);
                    719: #endif
                    720:
                    721:     setconnmode(0);
                    722:
                    723:     NetNonblockingIO(net, 1);
                    724:
1.16      guenther  725:     if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
                    726:        perror("setsockopt");
1.1       deraadt   727:     }
                    728: }
                    729:
                    730: /*
                    731:  * Process rings -
                    732:  *
                    733:  *     This routine tries to fill up/empty our various rings.
                    734:  *
                    735:  *     The parameter specifies whether this is a poll operation,
                    736:  *     or a block-until-something-happens operation.
                    737:  *
                    738:  *     The return value is 1 if something happened, 0 if not.
                    739:  */
                    740:
                    741:     int
1.15      millert   742: process_rings(netin, netout, netex, ttyin, ttyout, dopoll)
                    743:     int dopoll;                /* If 0, then block until something to do */
1.1       deraadt   744: {
1.10      mpech     745:     int c;
1.1       deraadt   746:                /* One wants to be a bit careful about setting returnValue
                    747:                 * to one, since a one implies we did some useful work,
                    748:                 * and therefore probably won't be called to block next
                    749:                 * time (TN3270 mode only).
                    750:                 */
                    751:     int returnValue = 0;
1.15      millert   752:     struct pollfd pfd[TELNET_FD_NUM];
                    753:
                    754:     if (ttyout) {
                    755:        pfd[TELNET_FD_TOUT].fd = tout;
                    756:        pfd[TELNET_FD_TOUT].events = POLLOUT;
                    757:     } else {
                    758:        pfd[TELNET_FD_TOUT].fd = -1;
                    759:     }
                    760:     if (ttyin) {
                    761:        pfd[TELNET_FD_TIN].fd = tin;
                    762:        pfd[TELNET_FD_TIN].events = POLLIN;
                    763:     } else {
                    764:        pfd[TELNET_FD_TIN].fd = -1;
                    765:     }
                    766:     if (netout || netin || netex) {
                    767:        pfd[TELNET_FD_NET].fd = net;
                    768:        pfd[TELNET_FD_NET].events = 0;
                    769:        if (netout)
                    770:            pfd[TELNET_FD_NET].events |= POLLOUT;
                    771:        if (netin)
                    772:            pfd[TELNET_FD_NET].events |= POLLIN;
                    773:        if (netex)
                    774:            pfd[TELNET_FD_NET].events |= POLLRDBAND;
                    775:     } else {
                    776:        pfd[TELNET_FD_NET].fd = -1;
                    777:     }
1.1       deraadt   778:
1.15      millert   779:     if ((c = poll(pfd, TELNET_FD_NUM, dopoll ? 0 : -1)) < 0) {
1.1       deraadt   780:        if (c == -1) {
                    781:                    /*
                    782:                     * we can get EINTR if we are in line mode,
                    783:                     * and the user does an escape (TSTP), or
                    784:                     * some other signal generator.
                    785:                     */
                    786:            if (errno == EINTR) {
                    787:                return 0;
                    788:            }
                    789:                    /* I don't like this, does it ever happen? */
1.15      millert   790:            printf("sleep(5) from telnet, after poll\r\n");
1.1       deraadt   791:            sleep(5);
                    792:        }
                    793:        return 0;
                    794:     }
                    795:
                    796:     /*
                    797:      * Any urgent data?
                    798:      */
1.15      millert   799:     if (pfd[TELNET_FD_NET].revents & POLLRDBAND) {
1.1       deraadt   800:        SYNCHing = 1;
                    801:        (void) ttyflush(1);     /* flush already enqueued data */
                    802:     }
                    803:
                    804:     /*
                    805:      * Something to read from the network...
                    806:      */
1.15      millert   807:     if (pfd[TELNET_FD_NET].revents & (POLLIN|POLLHUP)) {
1.1       deraadt   808:        int canread;
                    809:
                    810:        canread = ring_empty_consecutive(&netiring);
                    811:        c = recv(net, (char *)netiring.supply, canread, 0);
                    812:        if (c < 0 && errno == EWOULDBLOCK) {
                    813:            c = 0;
                    814:        } else if (c <= 0) {
                    815:            return -1;
                    816:        }
                    817:        if (netdata) {
                    818:            Dump('<', netiring.supply, c);
                    819:        }
                    820:        if (c)
                    821:            ring_supplied(&netiring, c);
                    822:        returnValue = 1;
                    823:     }
                    824:
                    825:     /*
                    826:      * Something to read from the tty...
                    827:      */
1.15      millert   828:     if (pfd[TELNET_FD_TIN].revents & (POLLIN|POLLHUP)) {
1.1       deraadt   829:        c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
1.3       niklas    830:        if (c < 0 && errno == EIO)
                    831:            c = 0;
1.1       deraadt   832:        if (c < 0 && errno == EWOULDBLOCK) {
                    833:            c = 0;
                    834:        } else {
1.5       art       835:            /* EOF detection for line mode!!!! */
                    836:            if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
                    837:                /* must be an EOF... */
                    838:                *ttyiring.supply = termEofChar;
                    839:                c = 1;
                    840:            }
                    841:            if (c <= 0) {
1.1       deraadt   842:                return -1;
                    843:            }
                    844:            if (termdata) {
                    845:                Dump('<', ttyiring.supply, c);
                    846:            }
                    847:            ring_supplied(&ttyiring, c);
                    848:        }
                    849:        returnValue = 1;                /* did something useful */
                    850:     }
                    851:
1.15      millert   852:     if (pfd[TELNET_FD_NET].revents & POLLOUT) {
1.1       deraadt   853:        returnValue |= netflush();
                    854:     }
1.15      millert   855:     if (pfd[TELNET_FD_TOUT].revents & POLLOUT) {
1.1       deraadt   856:        returnValue |= (ttyflush(SYNCHing|flushout) > 0);
                    857:     }
                    858:
                    859:     return returnValue;
                    860: }