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

1.27    ! jsg         1: /*     $OpenBSD: sys_bsd.c,v 1.26 2014/07/20 12:08:55 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.18      guenther   34:
1.17      guenther   35: #include <sys/ioctl.h>
1.20      guenther   36: #include <sys/socket.h>
                     37: #include <arpa/telnet.h>
                     38: #include <errno.h>
1.17      guenther   39: #include <poll.h>
1.20      guenther   40: #include <string.h>
1.18      guenther   41: #include <unistd.h>
1.1       deraadt    42:
                     43: /*
                     44:  * The following routines try to encapsulate what is system dependent
                     45:  * (at least between 4.x and dos) which is used in telnet.c.
                     46:  */
                     47:
                     48: int
                     49:        tout,                   /* Output file descriptor */
                     50:        tin,                    /* Input file descriptor */
                     51:        net;
                     52:
1.15      millert    53: #define TELNET_FD_TOUT 0
                     54: #define TELNET_FD_TIN  1
                     55: #define TELNET_FD_NET  2
                     56: #define TELNET_FD_NUM  3
                     57:
1.5       art        58: struct termios old_tc = { 0 };
1.1       deraadt    59:
1.27    ! jsg        60: void
        !            61: init_sys(void)
1.1       deraadt    62: {
                     63:     tout = fileno(stdout);
                     64:     tin = fileno(stdin);
                     65:
                     66:     errno = 0;
                     67: }
                     68:
                     69:
                     70: /*
                     71:  * TerminalSpecialChars()
                     72:  *
                     73:  * Look at an input character to see if it is a special character
                     74:  * and decide what to do.
                     75:  *
                     76:  * Output:
                     77:  *
                     78:  *     0       Don't add this character.
                     79:  *     1       Do add this character
                     80:  */
                     81:
1.27    ! jsg        82: int
        !            83: TerminalSpecialChars(int c)
1.1       deraadt    84: {
                     85:     if (c == termIntChar) {
                     86:        intp();
                     87:        return 0;
                     88:     } else if (c == termQuitChar) {
                     89: #ifdef KLUDGELINEMODE
                     90:        if (kludgelinemode)
                     91:            sendbrk();
                     92:        else
                     93: #endif
                     94:            sendabort();
                     95:        return 0;
                     96:     } else if (c == termEofChar) {
                     97:        if (my_want_state_is_will(TELOPT_LINEMODE)) {
                     98:            sendeof();
                     99:            return 0;
                    100:        }
                    101:        return 1;
                    102:     } else if (c == termSuspChar) {
                    103:        sendsusp();
                    104:        return(0);
                    105:     } else if (c == termFlushChar) {
                    106:        xmitAO();               /* Transmit Abort Output */
                    107:        return 0;
                    108:     } else if (!MODE_LOCAL_CHARS(globalmode)) {
                    109:        if (c == termKillChar) {
                    110:            xmitEL();
                    111:            return 0;
                    112:        } else if (c == termEraseChar) {
                    113:            xmitEC();           /* Transmit Erase Character */
                    114:            return 0;
                    115:        }
                    116:     }
                    117:     return 1;
                    118: }
                    119:
1.27    ! jsg       120: void
        !           121: TerminalSaveState(void)
1.1       deraadt   122: {
                    123:     tcgetattr(0, &old_tc);
                    124:
                    125:     new_tc = old_tc;
                    126:
                    127: #ifndef        VDISCARD
                    128:     termFlushChar = CONTROL('O');
                    129: #endif
                    130: #ifndef        VWERASE
                    131:     termWerasChar = CONTROL('W');
                    132: #endif
                    133: #ifndef        VREPRINT
                    134:     termRprntChar = CONTROL('R');
                    135: #endif
                    136: #ifndef        VLNEXT
                    137:     termLiteralNextChar = CONTROL('V');
                    138: #endif
                    139: #ifndef        VSTART
                    140:     termStartChar = CONTROL('Q');
                    141: #endif
                    142: #ifndef        VSTOP
                    143:     termStopChar = CONTROL('S');
                    144: #endif
                    145: #ifndef        VSTATUS
                    146:     termAytChar = CONTROL('T');
                    147: #endif
                    148: }
                    149:
1.27    ! jsg       150: cc_t *
        !           151: tcval(int func)
1.1       deraadt   152: {
                    153:     switch(func) {
                    154:     case SLC_IP:       return(&termIntChar);
                    155:     case SLC_ABORT:    return(&termQuitChar);
                    156:     case SLC_EOF:      return(&termEofChar);
                    157:     case SLC_EC:       return(&termEraseChar);
                    158:     case SLC_EL:       return(&termKillChar);
                    159:     case SLC_XON:      return(&termStartChar);
                    160:     case SLC_XOFF:     return(&termStopChar);
                    161:     case SLC_FORW1:    return(&termForw1Char);
                    162:     case SLC_FORW2:    return(&termForw2Char);
1.22      guenther  163:     case SLC_SUSP:     return(&termSuspChar);
1.1       deraadt   164: # ifdef        VDISCARD
                    165:     case SLC_AO:       return(&termFlushChar);
                    166: # endif
                    167: # ifdef        VWERASE
                    168:     case SLC_EW:       return(&termWerasChar);
                    169: # endif
                    170: # ifdef        VREPRINT
                    171:     case SLC_RP:       return(&termRprntChar);
                    172: # endif
                    173: # ifdef        VLNEXT
                    174:     case SLC_LNEXT:    return(&termLiteralNextChar);
                    175: # endif
                    176: # ifdef        VSTATUS
                    177:     case SLC_AYT:      return(&termAytChar);
                    178: # endif
                    179:
                    180:     case SLC_SYNCH:
                    181:     case SLC_BRK:
                    182:     case SLC_EOR:
                    183:     default:
                    184:        return((cc_t *)0);
                    185:     }
                    186: }
                    187:
1.27    ! jsg       188: void
        !           189: TerminalDefaultChars(void)
1.1       deraadt   190: {
1.23      guenther  191:     memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
1.1       deraadt   192: # ifndef       VDISCARD
                    193:     termFlushChar = CONTROL('O');
                    194: # endif
                    195: # ifndef       VWERASE
                    196:     termWerasChar = CONTROL('W');
                    197: # endif
                    198: # ifndef       VREPRINT
                    199:     termRprntChar = CONTROL('R');
                    200: # endif
                    201: # ifndef       VLNEXT
                    202:     termLiteralNextChar = CONTROL('V');
                    203: # endif
                    204: # ifndef       VSTART
                    205:     termStartChar = CONTROL('Q');
                    206: # endif
                    207: # ifndef       VSTOP
                    208:     termStopChar = CONTROL('S');
                    209: # endif
                    210: # ifndef       VSTATUS
                    211:     termAytChar = CONTROL('T');
                    212: # endif
                    213: }
                    214:
                    215: /*
                    216:  * TerminalNewMode - set up terminal to a specific mode.
                    217:  *     MODE_ECHO: do local terminal echo
                    218:  *     MODE_FLOW: do local flow control
                    219:  *     MODE_TRAPSIG: do local mapping to TELNET IAC sequences
                    220:  *     MODE_EDIT: do local line editing
                    221:  *
                    222:  *     Command mode:
                    223:  *             MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
                    224:  *             local echo
                    225:  *             local editing
                    226:  *             local xon/xoff
                    227:  *             local signal mapping
                    228:  *
                    229:  *     Linemode:
                    230:  *             local/no editing
                    231:  *     Both Linemode and Single Character mode:
                    232:  *             local/remote echo
                    233:  *             local/no xon/xoff
                    234:  *             local/no signal mapping
                    235:  */
                    236:
1.5       art       237: static void susp();
                    238: #ifdef SIGINFO
                    239: static void ayt();
                    240: #endif
1.1       deraadt   241:
1.27    ! jsg       242: void
        !           243: TerminalNewMode(int f)
1.1       deraadt   244: {
                    245:     static int prevmode = 0;
1.5       art       246:     struct termios tmp_tc;
1.1       deraadt   247:     int onoff;
                    248:     int old;
                    249:     cc_t esc;
                    250:
                    251:     globalmode = f&~MODE_FORCE;
                    252:     if (prevmode == f)
                    253:        return;
                    254:
                    255:     /*
                    256:      * Write any outstanding data before switching modes
                    257:      * ttyflush() returns 0 only when there is no more data
                    258:      * left to write out, it returns -1 if it couldn't do
                    259:      * anything at all, otherwise it returns 1 + the number
                    260:      * of characters left to write.
                    261:      */
                    262:     old = ttyflush(SYNCHing|flushout);
                    263:     if (old < 0 || old > 1) {
                    264:        tcgetattr(tin, &tmp_tc);
                    265:        do {
                    266:            /*
                    267:             * Wait for data to drain, then flush again.
                    268:             */
                    269:            tcsetattr(tin, TCSADRAIN, &tmp_tc);
                    270:            old = ttyflush(SYNCHing|flushout);
                    271:        } while (old < 0 || old > 1);
                    272:     }
                    273:
                    274:     old = prevmode;
                    275:     prevmode = f&~MODE_FORCE;
                    276:     tmp_tc = new_tc;
                    277:
                    278:     if (f&MODE_ECHO) {
                    279:        tmp_tc.c_lflag |= ECHO;
                    280:        tmp_tc.c_oflag |= ONLCR;
                    281:        if (crlf)
                    282:                tmp_tc.c_iflag |= ICRNL;
                    283:     } else {
                    284:        tmp_tc.c_lflag &= ~ECHO;
                    285:        tmp_tc.c_oflag &= ~ONLCR;
                    286:     }
                    287:
                    288:     if ((f&MODE_FLOW) == 0) {
                    289:        tmp_tc.c_iflag &= ~(IXOFF|IXON);        /* Leave the IXANY bit alone */
                    290:     } else {
                    291:        if (restartany < 0) {
                    292:                tmp_tc.c_iflag |= IXOFF|IXON;   /* Leave the IXANY bit alone */
                    293:        } else if (restartany > 0) {
                    294:                tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
                    295:        } else {
                    296:                tmp_tc.c_iflag |= IXOFF|IXON;
                    297:                tmp_tc.c_iflag &= ~IXANY;
                    298:        }
                    299:     }
                    300:
                    301:     if ((f&MODE_TRAPSIG) == 0) {
                    302:        tmp_tc.c_lflag &= ~ISIG;
                    303:        localchars = 0;
                    304:     } else {
                    305:        tmp_tc.c_lflag |= ISIG;
                    306:        localchars = 1;
                    307:     }
                    308:
                    309:     if (f&MODE_EDIT) {
                    310:        tmp_tc.c_lflag |= ICANON;
                    311:     } else {
                    312:        tmp_tc.c_lflag &= ~ICANON;
                    313:        tmp_tc.c_iflag &= ~ICRNL;
                    314:        tmp_tc.c_cc[VMIN] = 1;
                    315:        tmp_tc.c_cc[VTIME] = 0;
                    316:     }
                    317:
                    318:     if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
1.2       niklas    319:        tmp_tc.c_lflag &= ~IEXTEN;
1.1       deraadt   320:     }
                    321:
                    322:     if (f&MODE_SOFT_TAB) {
                    323: # ifdef        OXTABS
                    324:        tmp_tc.c_oflag |= OXTABS;
                    325: # endif
                    326: # ifdef        TABDLY
                    327:        tmp_tc.c_oflag &= ~TABDLY;
                    328:        tmp_tc.c_oflag |= TAB3;
                    329: # endif
                    330:     } else {
                    331: # ifdef        OXTABS
                    332:        tmp_tc.c_oflag &= ~OXTABS;
                    333: # endif
                    334: # ifdef        TABDLY
                    335:        tmp_tc.c_oflag &= ~TABDLY;
                    336: # endif
                    337:     }
                    338:
                    339:     if (f&MODE_LIT_ECHO) {
                    340: # ifdef        ECHOCTL
                    341:        tmp_tc.c_lflag &= ~ECHOCTL;
                    342: # endif
                    343:     } else {
                    344: # ifdef        ECHOCTL
                    345:        tmp_tc.c_lflag |= ECHOCTL;
                    346: # endif
                    347:     }
                    348:
                    349:     if (f == -1) {
                    350:        onoff = 0;
                    351:     } else {
                    352:        if (f & MODE_INBIN)
                    353:                tmp_tc.c_iflag &= ~ISTRIP;
                    354:        else
                    355:                tmp_tc.c_iflag |= ISTRIP;
1.5       art       356:        if ((f & MODE_OUTBIN) || (f & MODE_OUT8)) {
1.1       deraadt   357:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
                    358:                tmp_tc.c_cflag |= CS8;
1.5       art       359:                if(f & MODE_OUTBIN)
                    360:                        tmp_tc.c_oflag &= ~OPOST;
                    361:                else
                    362:                        tmp_tc.c_oflag |= OPOST;
                    363:
1.1       deraadt   364:        } else {
                    365:                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
                    366:                tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
                    367:                tmp_tc.c_oflag |= OPOST;
                    368:        }
                    369:        onoff = 1;
                    370:     }
                    371:
                    372:     if (f != -1) {
                    373:        (void) signal(SIGTSTP, susp);
                    374: #ifdef SIGINFO
                    375:        (void) signal(SIGINFO, ayt);
                    376: #endif
1.16      guenther  377: #if    defined(NOKERNINFO)
1.1       deraadt   378:        tmp_tc.c_lflag |= NOKERNINFO;
                    379: #endif
                    380:        /*
                    381:         * We don't want to process ^Y here.  It's just another
                    382:         * character that we'll pass on to the back end.  It has
                    383:         * to process it because it will be processed when the
                    384:         * user attempts to read it, not when we send it.
                    385:         */
                    386: # ifdef        VDSUSP
                    387:        tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
                    388: # endif
                    389:        /*
                    390:         * If the VEOL character is already set, then use VEOL2,
                    391:         * otherwise use VEOL.
                    392:         */
                    393:        esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
                    394:        if ((tmp_tc.c_cc[VEOL] != esc)
                    395: # ifdef        VEOL2
                    396:            && (tmp_tc.c_cc[VEOL2] != esc)
                    397: # endif
                    398:            ) {
                    399:                if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
                    400:                    tmp_tc.c_cc[VEOL] = esc;
                    401: # ifdef        VEOL2
                    402:                else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
                    403:                    tmp_tc.c_cc[VEOL2] = esc;
                    404: # endif
                    405:        }
                    406:     } else {
1.9       millert   407:        sigset_t mask;
1.1       deraadt   408: #ifdef SIGINFO
1.26      guenther  409:        (void) signal(SIGINFO, ayt_status);
1.1       deraadt   410: #endif
                    411:        (void) signal(SIGTSTP, SIG_DFL);
1.9       millert   412:        sigemptyset(&mask);
                    413:        sigaddset(&mask, SIGTSTP);
                    414:        sigprocmask(SIG_UNBLOCK, &mask, NULL);
1.1       deraadt   415:        tmp_tc = old_tc;
                    416:     }
                    417:     if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
                    418:        tcsetattr(tin, TCSANOW, &tmp_tc);
                    419:
                    420:     ioctl(tin, FIONBIO, (char *)&onoff);
                    421:     ioctl(tout, FIONBIO, (char *)&onoff);
                    422: }
                    423:
1.3       niklas    424: /*
                    425:  * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
                    426:  */
                    427: #if B4800 != 4800
                    428: #define        DECODE_BAUD
                    429: #endif
                    430:
                    431: #ifdef DECODE_BAUD
                    432: #ifndef        B7200
                    433: #define B7200   B4800
                    434: #endif
                    435:
                    436: #ifndef        B14400
                    437: #define B14400  B9600
                    438: #endif
                    439:
1.1       deraadt   440: #ifndef        B19200
1.3       niklas    441: # define B19200 B14400
                    442: #endif
                    443:
                    444: #ifndef        B28800
                    445: #define B28800  B19200
1.1       deraadt   446: #endif
                    447:
                    448: #ifndef        B38400
1.3       niklas    449: # define B38400 B28800
                    450: #endif
                    451:
                    452: #ifndef B57600
                    453: #define B57600  B38400
1.1       deraadt   454: #endif
                    455:
1.3       niklas    456: #ifndef B76800
                    457: #define B76800  B57600
                    458: #endif
                    459:
                    460: #ifndef B115200
                    461: #define B115200 B76800
                    462: #endif
                    463:
                    464: #ifndef B230400
                    465: #define B230400 B115200
                    466: #endif
                    467:
                    468:
1.1       deraadt   469: /*
                    470:  * This code assumes that the values B0, B50, B75...
                    471:  * are in ascending order.  They do not have to be
                    472:  * contiguous.
                    473:  */
                    474: struct termspeeds {
                    475:        long speed;
                    476:        long value;
                    477: } termspeeds[] = {
1.3       niklas    478:        { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
                    479:        { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
                    480:        { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
                    481:        { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
                    482:        { 4800,   B4800 },   { 7200,  B7200 },  { 9600,   B9600 },
                    483:        { 14400,  B14400 },  { 19200, B19200 }, { 28800,  B28800 },
                    484:        { 38400,  B38400 },  { 57600, B57600 }, { 115200, B115200 },
                    485:        { 230400, B230400 }, { -1,    B230400 }
1.1       deraadt   486: };
1.3       niklas    487: #endif /* DECODE_BAUD */
1.1       deraadt   488:
1.27    ! jsg       489: void
        !           490: TerminalSpeeds(long *ispeed, long *ospeed)
1.1       deraadt   491: {
1.3       niklas    492: #ifdef DECODE_BAUD
1.10      mpech     493:     struct termspeeds *tp;
1.3       niklas    494: #endif /* DECODE_BAUD */
1.10      mpech     495:     long in, out;
1.1       deraadt   496:
                    497:     out = cfgetospeed(&old_tc);
                    498:     in = cfgetispeed(&old_tc);
                    499:     if (in == 0)
                    500:        in = out;
                    501:
1.3       niklas    502: #ifdef DECODE_BAUD
1.1       deraadt   503:     tp = termspeeds;
                    504:     while ((tp->speed != -1) && (tp->value < in))
                    505:        tp++;
                    506:     *ispeed = tp->speed;
                    507:
                    508:     tp = termspeeds;
                    509:     while ((tp->speed != -1) && (tp->value < out))
                    510:        tp++;
                    511:     *ospeed = tp->speed;
1.3       niklas    512: #else  /* DECODE_BAUD */
                    513:        *ispeed = in;
                    514:        *ospeed = out;
                    515: #endif /* DECODE_BAUD */
1.1       deraadt   516: }
                    517:
1.27    ! jsg       518: int
        !           519: TerminalWindowSize(long *rows, long *cols)
1.1       deraadt   520: {
                    521: #ifdef TIOCGWINSZ
                    522:     struct winsize ws;
                    523:
                    524:     if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
                    525:        *rows = ws.ws_row;
                    526:        *cols = ws.ws_col;
                    527:        return 1;
                    528:     }
                    529: #endif /* TIOCGWINSZ */
                    530:     return 0;
                    531: }
                    532:
                    533: /*
                    534:  * Various signal handling routines.
                    535:  */
                    536:
1.27    ! jsg       537: void
        !           538: deadpeer(int sig)
1.1       deraadt   539: {
                    540:        setcommandmode();
                    541:        longjmp(peerdied, -1);
                    542: }
                    543:
1.27    ! jsg       544: void
        !           545: intr(int sig)
1.1       deraadt   546: {
                    547:     if (localchars) {
                    548:        intp();
                    549:        return;
                    550:     }
                    551:     setcommandmode();
                    552:     longjmp(toplevel, -1);
                    553: }
                    554:
1.27    ! jsg       555: void
        !           556: intr2(int sig)
1.1       deraadt   557: {
                    558:     if (localchars) {
                    559: #ifdef KLUDGELINEMODE
                    560:        if (kludgelinemode)
                    561:            sendbrk();
                    562:        else
                    563: #endif
                    564:            sendabort();
                    565:        return;
                    566:     }
                    567: }
                    568:
1.27    ! jsg       569: void
        !           570: susp(int sig)
1.1       deraadt   571: {
                    572:     if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
                    573:        return;
                    574:     if (localchars)
                    575:        sendsusp();
                    576: }
                    577:
                    578: #ifdef SIGWINCH
1.27    ! jsg       579: void
        !           580: sendwin(int sig)
1.1       deraadt   581: {
                    582:     if (connected) {
                    583:        sendnaws();
                    584:     }
                    585: }
                    586: #endif
                    587:
                    588: #ifdef SIGINFO
1.27    ! jsg       589: void
        !           590: ayt(int sig)
1.1       deraadt   591: {
                    592:     if (connected)
                    593:        sendayt();
                    594:     else
1.26      guenther  595:        ayt_status(sig);
1.1       deraadt   596: }
                    597: #endif
                    598:
                    599: 
1.27    ! jsg       600: void
        !           601: sys_telnet_init(void)
1.1       deraadt   602: {
1.16      guenther  603:     int one = 1;
                    604:
1.1       deraadt   605:     (void) signal(SIGINT, intr);
                    606:     (void) signal(SIGQUIT, intr2);
                    607:     (void) signal(SIGPIPE, deadpeer);
                    608: #ifdef SIGWINCH
                    609:     (void) signal(SIGWINCH, sendwin);
                    610: #endif
                    611:     (void) signal(SIGTSTP, susp);
                    612: #ifdef SIGINFO
                    613:     (void) signal(SIGINFO, ayt);
                    614: #endif
                    615:
                    616:     setconnmode(0);
                    617:
1.25      guenther  618:     /*
                    619:      * Mark the socket as non-blocking and receive urgent data inline.
                    620:      * (The latter is required for correct telnet operation when a
                    621:      * second urgent is sent before telnet can process the first.)
                    622:      */
                    623:     ioctl(net, FIONBIO, &one);
1.16      guenther  624:     if (setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &one, sizeof(one)) == -1) {
                    625:        perror("setsockopt");
1.1       deraadt   626:     }
                    627: }
                    628:
                    629: /*
                    630:  * Process rings -
                    631:  *
                    632:  *     This routine tries to fill up/empty our various rings.
                    633:  *
                    634:  *     The parameter specifies whether this is a poll operation,
                    635:  *     or a block-until-something-happens operation.
                    636:  *
                    637:  *     The return value is 1 if something happened, 0 if not.
                    638:  */
                    639:
1.27    ! jsg       640: int
        !           641: process_rings(int netin, int netout, int netex, int ttyin, int ttyout,
        !           642:     int dopoll)                /* If 0, then block until something to do */
1.1       deraadt   643: {
1.10      mpech     644:     int c;
1.1       deraadt   645:                /* One wants to be a bit careful about setting returnValue
                    646:                 * to one, since a one implies we did some useful work,
                    647:                 * and therefore probably won't be called to block next
                    648:                 * time (TN3270 mode only).
                    649:                 */
                    650:     int returnValue = 0;
1.15      millert   651:     struct pollfd pfd[TELNET_FD_NUM];
                    652:
                    653:     if (ttyout) {
                    654:        pfd[TELNET_FD_TOUT].fd = tout;
                    655:        pfd[TELNET_FD_TOUT].events = POLLOUT;
                    656:     } else {
                    657:        pfd[TELNET_FD_TOUT].fd = -1;
                    658:     }
                    659:     if (ttyin) {
                    660:        pfd[TELNET_FD_TIN].fd = tin;
                    661:        pfd[TELNET_FD_TIN].events = POLLIN;
                    662:     } else {
                    663:        pfd[TELNET_FD_TIN].fd = -1;
                    664:     }
                    665:     if (netout || netin || netex) {
                    666:        pfd[TELNET_FD_NET].fd = net;
                    667:        pfd[TELNET_FD_NET].events = 0;
                    668:        if (netout)
                    669:            pfd[TELNET_FD_NET].events |= POLLOUT;
                    670:        if (netin)
                    671:            pfd[TELNET_FD_NET].events |= POLLIN;
                    672:        if (netex)
                    673:            pfd[TELNET_FD_NET].events |= POLLRDBAND;
                    674:     } else {
                    675:        pfd[TELNET_FD_NET].fd = -1;
                    676:     }
1.1       deraadt   677:
1.21      guenther  678:     if ((c = poll(pfd, TELNET_FD_NUM, dopoll ? 0 : INFTIM)) < 0) {
1.1       deraadt   679:        return 0;
                    680:     }
                    681:
                    682:     /*
                    683:      * Any urgent data?
                    684:      */
1.15      millert   685:     if (pfd[TELNET_FD_NET].revents & POLLRDBAND) {
1.1       deraadt   686:        SYNCHing = 1;
                    687:        (void) ttyflush(1);     /* flush already enqueued data */
                    688:     }
                    689:
                    690:     /*
                    691:      * Something to read from the network...
                    692:      */
1.15      millert   693:     if (pfd[TELNET_FD_NET].revents & (POLLIN|POLLHUP)) {
1.1       deraadt   694:        int canread;
                    695:
                    696:        canread = ring_empty_consecutive(&netiring);
                    697:        c = recv(net, (char *)netiring.supply, canread, 0);
                    698:        if (c < 0 && errno == EWOULDBLOCK) {
                    699:            c = 0;
                    700:        } else if (c <= 0) {
                    701:            return -1;
                    702:        }
                    703:        if (netdata) {
                    704:            Dump('<', netiring.supply, c);
                    705:        }
                    706:        if (c)
                    707:            ring_supplied(&netiring, c);
                    708:        returnValue = 1;
                    709:     }
                    710:
                    711:     /*
                    712:      * Something to read from the tty...
                    713:      */
1.15      millert   714:     if (pfd[TELNET_FD_TIN].revents & (POLLIN|POLLHUP)) {
1.19      guenther  715:        c = read(tin, ttyiring.supply, ring_empty_consecutive(&ttyiring));
1.3       niklas    716:        if (c < 0 && errno == EIO)
                    717:            c = 0;
1.1       deraadt   718:        if (c < 0 && errno == EWOULDBLOCK) {
                    719:            c = 0;
                    720:        } else {
1.5       art       721:            /* EOF detection for line mode!!!! */
                    722:            if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
                    723:                /* must be an EOF... */
                    724:                *ttyiring.supply = termEofChar;
                    725:                c = 1;
                    726:            }
                    727:            if (c <= 0) {
1.1       deraadt   728:                return -1;
                    729:            }
                    730:            if (termdata) {
                    731:                Dump('<', ttyiring.supply, c);
                    732:            }
                    733:            ring_supplied(&ttyiring, c);
                    734:        }
                    735:        returnValue = 1;                /* did something useful */
                    736:     }
                    737:
1.15      millert   738:     if (pfd[TELNET_FD_NET].revents & POLLOUT) {
1.1       deraadt   739:        returnValue |= netflush();
                    740:     }
1.15      millert   741:     if (pfd[TELNET_FD_TOUT].revents & POLLOUT) {
1.1       deraadt   742:        returnValue |= (ttyflush(SYNCHing|flushout) > 0);
                    743:     }
                    744:
                    745:     return returnValue;
                    746: }