Annotation of 43BSDTahoe/ucb/tn3270/telnet.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms are permitted
        !             6:  * provided that this notice is preserved and that due credit is given
        !             7:  * to the University of California at Berkeley. The name of the University
        !             8:  * may not be used to endorse or promote products derived from this
        !             9:  * software without specific prior written permission. This software
        !            10:  * is provided ``as is'' without express or implied warranty.
        !            11:  */
        !            12: 
        !            13: #ifndef lint
        !            14: char copyright[] =
        !            15: "@(#) Copyright (c) 1988 Regents of the University of California.\n\
        !            16:  All rights reserved.\n";
        !            17: #endif /* not lint */
        !            18: 
        !            19: #ifndef lint
        !            20: static char sccsid[] = "@(#)telnet.c   6.9 (Berkeley) 3/28/88";
        !            21: #endif /* not lint */
        !            22: 
        !            23: /*
        !            24:  * User telnet program, modified for use by tn3270.c.
        !            25:  *
        !            26:  * Many of the FUNCTIONAL changes in this newest version of TELNET
        !            27:  * were suggested by Dave Borman of Cray Research, Inc.
        !            28:  *
        !            29:  * Other changes in the tn3270 side come from Alan Crosswell (Columbia),
        !            30:  * Bob Braden (ISI), Steve Jacobson (Berkeley), and Cliff Frost (Berkeley).
        !            31:  *
        !            32:  * This code is common between telnet(1c) and tn3270(1c).  There are the
        !            33:  * following defines used to generate the various versions:
        !            34:  *
        !            35:  *     TN3270          -       This is to be linked with tn3270.
        !            36:  *
        !            37:  *     NOT43           -       Allows the program to compile and run on
        !            38:  *                             a 4.2BSD system.
        !            39:  *
        !            40:  *     PUTCHAR         -       Within tn3270, on a NOT43 system,
        !            41:  *                             allows the use of the 4.3 curses
        !            42:  *                             (greater speed updating the screen).
        !            43:  *                             You need the 4.3 curses for this to work.
        !            44:  *
        !            45:  *     FD_SETSIZE      -       On whichever system, if this isn't defined,
        !            46:  *                             we patch over the FD_SET, etc., macros with
        !            47:  *                             some homebrewed ones.
        !            48:  *
        !            49:  *     SO_OOBINLINE    -       This is a socket option which we would like
        !            50:  *                             to set to allow TCP urgent data to come
        !            51:  *                             to us "inline".  This is NECESSARY for
        !            52:  *                             CORRECT operation, and desireable for
        !            53:  *                             simpler operation.
        !            54:  *
        !            55:  *     LNOFLSH         -       Detects the presence of the LNOFLSH bit
        !            56:  *                             in the tty structure.
        !            57:  *
        !            58:  *     unix            -       Compiles in unix specific stuff.
        !            59:  *
        !            60:  *     MSDOS           -       Compiles in MSDOS specific stuff.
        !            61:  *
        !            62:  */
        !            63: 
        !            64: #if    !defined(TN3270)
        !            65: #define        ExitString(f,s,r)       { fprintf(f, s); exit(r); }
        !            66: #define        Exit(x)                 exit(x)
        !            67: #define        SetIn3270()
        !            68: 
        !            69: void   setcommandmode(), command();    /* forward declarations */
        !            70: #endif /* !defined(TN3270) */
        !            71: 
        !            72: #include <sys/types.h>
        !            73: 
        !            74: #if     defined(pyr)
        !            75: #define fd_set fdset_t
        !            76: #endif  /* defined(pyr) */
        !            77:  
        !            78: #include <sys/socket.h>
        !            79: 
        !            80: #include <netinet/in.h>
        !            81: 
        !            82: #if    defined(unix)
        !            83: /* By the way, we need to include curses.h before telnet.h since,
        !            84:  * among other things, telnet.h #defines 'DO', which is a variable
        !            85:  * declared in curses.h.
        !            86:  */
        !            87: #include <curses.h>
        !            88: #endif /* defined(unix) */
        !            89: 
        !            90: #define        TELOPTS
        !            91: #include <arpa/telnet.h>
        !            92: 
        !            93: #if    !defined(NOT43)
        !            94: #include <arpa/inet.h>
        !            95: #else  /* !defined(NOT43) */
        !            96: extern unsigned long inet_addr();
        !            97: extern char    *inet_ntoa();
        !            98: #endif /* !defined(NOT43) */
        !            99: 
        !           100: #include <stdio.h>
        !           101: #include <ctype.h>
        !           102: #include <errno.h>
        !           103: #include <setjmp.h>
        !           104: #include <netdb.h>
        !           105: 
        !           106: #if    defined(unix)
        !           107: #include <strings.h>
        !           108: #else  /* defined(unix) */
        !           109: #include <string.h>
        !           110: #endif /* defined(unix) */
        !           111: 
        !           112: #if    defined(TN3270)
        !           113: #include "ascii/termin.ext"
        !           114: #include "ctlr/screen.h"
        !           115: #include "ctlr/oia.h"
        !           116: #include "ctlr/options.ext"
        !           117: #include "ctlr/outbound.ext"
        !           118: #include "general/globals.h"
        !           119: #include "telnet.ext"
        !           120: #endif /* defined(TN3270) */
        !           121: 
        !           122: #include "general/general.h"
        !           123: 
        !           124: 
        !           125: 
        !           126: #ifndef        FD_SETSIZE
        !           127: /*
        !           128:  * The following is defined just in case someone should want to run
        !           129:  * this telnet on a 4.2 system.
        !           130:  *
        !           131:  */
        !           132: 
        !           133: #define        FD_SET(n, p)    ((p)->fds_bits[0] |= (1<<(n)))
        !           134: #define        FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1<<(n)))
        !           135: #define        FD_ISSET(n, p)  ((p)->fds_bits[0] & (1<<(n)))
        !           136: #define FD_ZERO(p)     ((p)->fds_bits[0] = 0)
        !           137: 
        !           138: #endif
        !           139: 
        !           140: #define        strip(x)        ((x)&0x7f)
        !           141: #define min(x,y)       ((x<y)? x:y)
        !           142: 
        !           143: #if    defined(TN3270)
        !           144: static char    Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
        !           145: #endif /* defined(TN3270) */
        !           146: 
        !           147: static char    ttyobuf[2*BUFSIZ], *tfrontp, *tbackp;
        !           148: #define        TTYADD(c)       { if (!(SYNCHing||flushout)) { *tfrontp++ = c; } }
        !           149: #define        TTYLOC()        (tfrontp)
        !           150: #define        TTYMAX()        (ttyobuf+sizeof ttyobuf-1)
        !           151: #define        TTYMIN()        (netobuf)
        !           152: #define        TTYBYTES()      (tfrontp-tbackp)
        !           153: #define        TTYROOM()       (TTYMAX()-TTYLOC()+1)
        !           154: 
        !           155: static char    netobuf[2*BUFSIZ], *nfrontp, *nbackp;
        !           156: #define        NETADD(c)       { *nfrontp++ = c; }
        !           157: #define        NET2ADD(c1,c2)  { NETADD(c1); NETADD(c2); }
        !           158: #define NETLOC()       (nfrontp)
        !           159: #define        NETMAX()        (netobuf+sizeof netobuf-1)
        !           160: #define        NETBYTES()      (nfrontp-nbackp)
        !           161: #define        NETROOM()       (NETMAX()-NETLOC()+1)
        !           162: static char    *neturg;                /* one past last byte of urgent data */
        !           163: 
        !           164: static char    subbuffer[100],
        !           165:                *subpointer, *subend;    /* buffer for sub-options */
        !           166: #define        SB_CLEAR()      subpointer = subbuffer;
        !           167: #define        SB_TERM()       subend = subpointer;
        !           168: #define        SB_ACCUM(c)     if (subpointer < (subbuffer+sizeof subbuffer)) { \
        !           169:                                *subpointer++ = (c); \
        !           170:                        }
        !           171: 
        !           172: static char    sb_terminal[] = { IAC, SB,
        !           173:                        TELOPT_TTYPE, TELQUAL_IS,
        !           174:                        'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
        !           175:                        IAC, SE };
        !           176: #define        SBTERMMODEL     13
        !           177: 
        !           178: 
        !           179: static char    hisopts[256];
        !           180: static char    myopts[256];
        !           181: 
        !           182: static char    doopt[] = { IAC, DO, '%', 'c', 0 };
        !           183: static char    dont[] = { IAC, DONT, '%', 'c', 0 };
        !           184: static char    will[] = { IAC, WILL, '%', 'c', 0 };
        !           185: static char    wont[] = { IAC, WONT, '%', 'c', 0 };
        !           186: 
        !           187: struct cmd {
        !           188:        char    *name;          /* command name */
        !           189:        char    *help;          /* help string */
        !           190:        int     (*handler)();   /* routine which executes command */
        !           191:        int     dohelp;         /* Should we give general help information? */
        !           192:        int     needconnect;    /* Do we need to be connected to execute? */
        !           193: };
        !           194: 
        !           195: static char    sibuf[BUFSIZ], *sbp;
        !           196: static char    tibuf[BUFSIZ], *tbp;
        !           197: static fd_set ibits, obits, xbits;
        !           198: 
        !           199: 
        !           200: static int
        !           201:        connected,
        !           202:        net,
        !           203:        scc,
        !           204:        tcc,
        !           205:        showoptions,
        !           206:        In3270,         /* Are we in 3270 mode? */
        !           207:        ISend,          /* trying to send network data in */
        !           208:        debug = 0,
        !           209:        crmod,
        !           210:        netdata,        /* Print out network data flow */
        !           211:        crlf,           /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
        !           212:        noasynch = 0,   /* User specified "-noasynch" on command line */
        !           213:        askedSGA = 0,   /* We have talked about suppress go ahead */
        !           214:        telnetport = 1;
        !           215: 
        !           216: static FILE    *NetTrace = 0;          /* Not in bss, since needs to stay */
        !           217: 
        !           218: #define        CONTROL(x)      ((x)&0x1f)              /* CTRL(x) is not portable */
        !           219: 
        !           220: static char
        !           221:        *prompt = 0,
        !           222:        escape,
        !           223:        echoc;
        !           224: 
        !           225: static int
        !           226:        SYNCHing,               /* we are in TELNET SYNCH mode */
        !           227:        flushout,               /* flush output */
        !           228:        autoflush = 0,          /* flush output when interrupting? */
        !           229:        autosynch,              /* send interrupt characters with SYNCH? */
        !           230:        localchars,             /* we recognize interrupt/quit */
        !           231:        donelclchars,           /* the user has set "localchars" */
        !           232:        donebinarytoggle,       /* the user has put us in binary */
        !           233:        dontlecho,              /* do we suppress local echoing right now? */
        !           234:        globalmode;
        !           235: 
        !           236: /*     The following are some tn3270 specific flags */
        !           237: #if    defined(TN3270)
        !           238: 
        !           239: static int
        !           240:        Sent3270TerminalType;   /* Have we said we are a 3270? */
        !           241: 
        !           242: /* Some real, live, globals. */
        !           243: int
        !           244:        tout,                   /* Output file descriptor */
        !           245:        tin;                    /* Input file descriptor */
        !           246: 
        !           247: #else  /* defined(TN3270) */
        !           248: static int tin, tout;          /* file descriptors */
        !           249: #endif /* defined(TN3270) */
        !           250: 
        !           251: 
        !           252: /*
        !           253:  * Telnet receiver states for fsm
        !           254:  */
        !           255: #define        TS_DATA         0
        !           256: #define        TS_IAC          1
        !           257: #define        TS_WILL         2
        !           258: #define        TS_WONT         3
        !           259: #define        TS_DO           4
        !           260: #define        TS_DONT         5
        !           261: #define        TS_CR           6
        !           262: #define        TS_SB           7               /* sub-option collection */
        !           263: #define        TS_SE           8               /* looking for sub-option end */
        !           264: 
        !           265: static int     telrcv_state = TS_DATA;
        !           266: 
        !           267: static char    line[200];
        !           268: static int     margc;
        !           269: static char    *margv[20];
        !           270: 
        !           271: static jmp_buf toplevel = { 0 };
        !           272: static jmp_buf peerdied;
        !           273: 
        !           274: extern int errno;
        !           275: 
        !           276: 
        !           277: static struct sockaddr_in sin;
        !           278: 
        !           279: static struct  servent *sp = 0;
        !           280: 
        !           281: static int     flushline;
        !           282: 
        !           283: static char    *hostname;
        !           284: static char    hnamebuf[32];
        !           285: 
        !           286: /*
        !           287:  * The following are some clocks used to decide how to interpret
        !           288:  * the relationship between various variables.
        !           289:  */
        !           290: 
        !           291: static struct {
        !           292:     int
        !           293:        system,                 /* what the current time is */
        !           294:        echotoggle,             /* last time user entered echo character */
        !           295:        modenegotiated,         /* last time operating mode negotiated */
        !           296:        didnetreceive,          /* last time we read data from network */
        !           297:        gotDM;                  /* when did we last see a data mark */
        !           298: } clocks;
        !           299: 
        !           300: #define        settimer(x)     clocks.x = clocks.system++
        !           301: 
        !           302: /*     Various modes */
        !           303: #define        MODE_LINE(m)    (modelist[m].modetype & LINE)
        !           304: #define        MODE_LOCAL_CHARS(m)     (modelist[m].modetype &  LOCAL_CHARS)
        !           305: #define        MODE_LOCAL_ECHO(m)      (modelist[m].modetype & LOCAL_ECHO)
        !           306: #define        MODE_COMMAND_LINE(m)    (modelist[m].modetype & COMMAND_LINE)
        !           307: 
        !           308: #define        LOCAL_CHARS     0x01            /* Characters processed locally */
        !           309: #define        LINE            0x02            /* Line-by-line mode of operation */
        !           310: #define        LOCAL_ECHO      0x04            /* Echoing locally */
        !           311: #define        COMMAND_LINE    0x08            /* Command line mode */
        !           312: 
        !           313: static struct {
        !           314:     char *modedescriptions;
        !           315:     char modetype;
        !           316: } modelist[] = {
        !           317:        { "telnet command mode", COMMAND_LINE },
        !           318:        { "character-at-a-time mode", 0 },
        !           319:        { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
        !           320:        { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
        !           321:        { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
        !           322:        { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
        !           323:        { "3270 mode", 0 },
        !           324: };
        !           325: 
        !           326: 
        !           327: /*
        !           328:  * The following routines try to encapsulate what is system dependent
        !           329:  * (at least between 4.x and dos) which is used in telnet.c.
        !           330:  */
        !           331: 
        !           332: #if    defined(unix)
        !           333: #include <sys/ioctl.h>
        !           334: #include <sys/time.h>
        !           335: #include <signal.h>
        !           336: 
        !           337: int
        !           338:        HaveInput;              /* There is input available to scan */
        !           339: 
        !           340: #if    defined(TN3270)
        !           341: static char    tline[200];
        !           342: char   *transcom = 0;  /* transparent mode command (default: none) */
        !           343: #endif /* defined(TN3270) */
        !           344: 
        !           345: static struct  tchars otc = { 0 }, ntc = { 0 };
        !           346: static struct  ltchars oltc = { 0 }, nltc = { 0 };
        !           347: static struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
        !           348: 
        !           349: 
        !           350: #define        TerminalWrite(fd,buf,n) write(fd,buf,n)
        !           351: #define        TerminalRead(fd,buf,n)  read(fd,buf,n)
        !           352: 
        !           353: /*
        !           354:  *
        !           355:  */
        !           356: 
        !           357: static int
        !           358: TerminalAutoFlush()                                    /* unix */
        !           359: {
        !           360: #if    defined(LNOFLSH)
        !           361:     ioctl(0, TIOCLGET, (char *)&autoflush);
        !           362:     return !(autoflush&LNOFLSH);       /* if LNOFLSH, no autoflush */
        !           363: #else  /* LNOFLSH */
        !           364:     return 1;
        !           365: #endif /* LNOFLSH */
        !           366: }
        !           367: 
        !           368: /*
        !           369:  * TerminalSpecialChars()
        !           370:  *
        !           371:  * Look at an input character to see if it is a special character
        !           372:  * and decide what to do.
        !           373:  *
        !           374:  * Output:
        !           375:  *
        !           376:  *     0       Don't add this character.
        !           377:  *     1       Do add this character
        !           378:  */
        !           379: 
        !           380: int
        !           381: TerminalSpecialChars(c)                        /* unix */
        !           382: int    c;
        !           383: {
        !           384:     void doflush(), intp(), sendbrk();
        !           385: 
        !           386:     if (c == ntc.t_intrc) {
        !           387:        intp();
        !           388:        return 0;
        !           389:     } else if (c == ntc.t_quitc) {
        !           390:        sendbrk();
        !           391:        return 0;
        !           392:     } else if (c == nltc.t_flushc) {
        !           393:        NET2ADD(IAC, AO);
        !           394:        if (autoflush) {
        !           395:            doflush();
        !           396:        }
        !           397:        return 0;
        !           398:     } else if (!MODE_LOCAL_CHARS(globalmode)) {
        !           399:        if (c == nttyb.sg_kill) {
        !           400:            NET2ADD(IAC, EL);
        !           401:            return 0;
        !           402:        } else if (c == nttyb.sg_erase) {
        !           403:            NET2ADD(IAC, EC);
        !           404:            return 0;
        !           405:        }
        !           406:     }
        !           407:     return 1;
        !           408: }
        !           409: 
        !           410: 
        !           411: /*
        !           412:  * Flush output to the terminal
        !           413:  */
        !           414:  
        !           415: static void
        !           416: TerminalFlushOutput()                          /* unix */
        !           417: {
        !           418:     (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
        !           419: }
        !           420: 
        !           421: static void
        !           422: TerminalSaveState()                            /* unix */
        !           423: {
        !           424:     ioctl(0, TIOCGETP, (char *)&ottyb);
        !           425:     ioctl(0, TIOCGETC, (char *)&otc);
        !           426:     ioctl(0, TIOCGLTC, (char *)&oltc);
        !           427: 
        !           428:     ntc = otc;
        !           429:     nltc = oltc;
        !           430:     nttyb = ottyb;
        !           431: }
        !           432: 
        !           433: static void
        !           434: TerminalRestoreState()                         /* unix */
        !           435: {
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * TerminalNewMode - set up terminal to a specific mode.
        !           440:  */
        !           441: 
        !           442: 
        !           443: static void
        !           444: TerminalNewMode(f)                                     /* unix */
        !           445: register int f;
        !           446: {
        !           447:     static int prevmode = 0;
        !           448:     struct tchars *tc;
        !           449:     struct tchars tc3;
        !           450:     struct ltchars *ltc;
        !           451:     struct sgttyb sb;
        !           452:     int onoff;
        !           453:     int old;
        !           454:     struct     tchars notc2;
        !           455:     struct     ltchars noltc2;
        !           456:     static struct      tchars notc =   { -1, -1, -1, -1, -1, -1 };
        !           457:     static struct      ltchars noltc = { -1, -1, -1, -1, -1, -1 };
        !           458: 
        !           459:     globalmode = f;
        !           460:     if (prevmode == f)
        !           461:        return;
        !           462:     old = prevmode;
        !           463:     prevmode = f;
        !           464:     sb = nttyb;
        !           465: 
        !           466:     switch (f) {
        !           467: 
        !           468:     case 0:
        !           469:        onoff = 0;
        !           470:        tc = &otc;
        !           471:        ltc = &oltc;
        !           472:        break;
        !           473: 
        !           474:     case 1:            /* remote character processing, remote echo */
        !           475:     case 2:            /* remote character processing, local echo */
        !           476:     case 6:            /* 3270 mode - like 1, but with xon/xoff local */
        !           477:                    /* (might be nice to have "6" in telnet also...) */
        !           478:            sb.sg_flags |= CBREAK;
        !           479:            if ((f == 1) || (f == 6)) {
        !           480:                sb.sg_flags &= ~(ECHO|CRMOD);
        !           481:            } else {
        !           482:                sb.sg_flags |= ECHO|CRMOD;
        !           483:            }
        !           484:            sb.sg_erase = sb.sg_kill = -1;
        !           485:            if (f == 6) {
        !           486:                tc = &tc3;
        !           487:                tc3 = notc;
        !           488:                    /* get XON, XOFF characters */
        !           489:                tc3.t_startc = otc.t_startc;
        !           490:                tc3.t_stopc = otc.t_stopc;
        !           491:            } else {
        !           492:                /*
        !           493:                 * If user hasn't specified one way or the other,
        !           494:                 * then default to not trapping signals.
        !           495:                 */
        !           496:                if (!donelclchars) {
        !           497:                    localchars = 0;
        !           498:                }
        !           499:                if (localchars) {
        !           500:                    notc2 = notc;
        !           501:                    notc2.t_intrc = ntc.t_intrc;
        !           502:                    notc2.t_quitc = ntc.t_quitc;
        !           503:                    tc = &notc2;
        !           504:                } else {
        !           505:                    tc = &notc;
        !           506:                }
        !           507:            }
        !           508:            ltc = &noltc;
        !           509:            onoff = 1;
        !           510:            break;
        !           511:     case 3:            /* local character processing, remote echo */
        !           512:     case 4:            /* local character processing, local echo */
        !           513:     case 5:            /* local character processing, no echo */
        !           514:            sb.sg_flags &= ~CBREAK;
        !           515:            sb.sg_flags |= CRMOD;
        !           516:            if (f == 4)
        !           517:                sb.sg_flags |= ECHO;
        !           518:            else
        !           519:                sb.sg_flags &= ~ECHO;
        !           520:            notc2 = ntc;
        !           521:            tc = &notc2;
        !           522:            noltc2 = oltc;
        !           523:            ltc = &noltc2;
        !           524:            /*
        !           525:             * If user hasn't specified one way or the other,
        !           526:             * then default to trapping signals.
        !           527:             */
        !           528:            if (!donelclchars) {
        !           529:                localchars = 1;
        !           530:            }
        !           531:            if (localchars) {
        !           532:                notc2.t_brkc = nltc.t_flushc;
        !           533:                noltc2.t_flushc = -1;
        !           534:            } else {
        !           535:                notc2.t_intrc = notc2.t_quitc = -1;
        !           536:            }
        !           537:            noltc2.t_suspc = escape;
        !           538:            noltc2.t_dsuspc = -1;
        !           539:            onoff = 1;
        !           540:            break;
        !           541: 
        !           542:     default:
        !           543:            return;
        !           544:     }
        !           545:     ioctl(tin, TIOCSLTC, (char *)ltc);
        !           546:     ioctl(tin, TIOCSETC, (char *)tc);
        !           547:     ioctl(tin, TIOCSETP, (char *)&sb);
        !           548: #if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
        !           549:     ioctl(tin, FIONBIO, (char *)&onoff);
        !           550:     ioctl(tout, FIONBIO, (char *)&onoff);
        !           551: #endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
        !           552: #if    defined(TN3270)
        !           553:     if (noasynch == 0) {
        !           554:        ioctl(tin, FIOASYNC, (char *)&onoff);
        !           555:     }
        !           556: #endif /* defined(TN3270) */
        !           557: 
        !           558:     if (MODE_LINE(f)) {
        !           559:        void doescape();
        !           560: 
        !           561:        signal(SIGTSTP, doescape);
        !           562:     } else if (MODE_LINE(old)) {
        !           563:        signal(SIGTSTP, SIG_DFL);
        !           564:        sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
        !           565:     }
        !           566: }
        !           567: 
        !           568: 
        !           569: int
        !           570: NetClose(net)
        !           571: int    net;
        !           572: {
        !           573:     return close(net);
        !           574: }
        !           575: 
        !           576: 
        !           577: static void
        !           578: NetNonblockingIO(fd, onoff)                            /* unix */
        !           579: int
        !           580:        fd,
        !           581:        onoff;
        !           582: {
        !           583:     ioctl(net, FIONBIO, (char *)&onoff);
        !           584: }
        !           585: 
        !           586: static void
        !           587: NetSigIO(fd, onoff)                            /* unix */
        !           588: int
        !           589:        fd,
        !           590:        onoff;
        !           591: {
        !           592:     ioctl(net, FIOASYNC, (char *)&onoff);      /* hear about input */
        !           593: }
        !           594: 
        !           595: static void
        !           596: NetSetPgrp(fd)                         /* unix */
        !           597: int fd;
        !           598: {
        !           599:     int myPid;
        !           600: 
        !           601:     myPid = getpid();
        !           602: #if    defined(NOT43)
        !           603:     myPid = -myPid;
        !           604: #endif /* defined(NOT43) */
        !           605:     ioctl(net, SIOCSPGRP, (char *)&myPid);     /* set my pid */
        !           606: }
        !           607: 
        !           608: 
        !           609: #endif /* defined(unix) */
        !           610: 
        !           611: #if    defined(MSDOS)
        !           612: #include <time.h>
        !           613: #include <signal.h>
        !           614: #include <process.h>
        !           615: #include <fcntl.h>
        !           616: #include <io.h>
        !           617: #include <dos.h>
        !           618: 
        !           619: #if    !defined(SO_OOBINLINE)
        !           620: #define        SO_OOBINLINE
        !           621: #endif /* !defined(SO_OOBINLINE) */
        !           622: 
        !           623: 
        !           624: static char
        !           625:     termEofChar,
        !           626:     termEraseChar,
        !           627:     termFlushChar,
        !           628:     termIntChar,
        !           629:     termKillChar,
        !           630:     termLiteralNextChar,
        !           631:     termQuitChar;
        !           632: 
        !           633: static char
        !           634:     savedInState, savedOutState;
        !           635: 
        !           636: /*
        !           637:  * MSDOS doesn't have anyway of deciding whether a full-edited line
        !           638:  * is ready to be read in, so we need to do character-by-character
        !           639:  * reads, and then do the editing in the program (in the case where
        !           640:  * we are supporting line-by-line mode).
        !           641:  *
        !           642:  * The following routines, which are internal to the MSDOS-specific
        !           643:  * code, accomplish this miracle.
        !           644:  */
        !           645: 
        !           646: #define Hex(c) HEX[(c)&0xff]
        !           647: 
        !           648: static survivorSetup = 0;              /* Do we have ^C hooks in? */
        !           649: 
        !           650: static int
        !           651:        lineend = 0,            /* There is a line terminator */
        !           652:        ctrlCCount = 0;
        !           653: 
        !           654: static char    linein[200],            /* Where input line is assembled */
        !           655:                *nextin = linein,       /* Next input character */
        !           656:                *nextout = linein;      /* Next character to be consumed */
        !           657: 
        !           658: #define consumechar() \
        !           659:     if ((++nextout) >= nextin) { \
        !           660:        nextout = nextin = linein; \
        !           661:        lineend = 0; \
        !           662:     }
        !           663: 
        !           664: #define        characteratatime()      (!MODE_LINE(globalmode))        /* one by one */
        !           665: 
        !           666: 
        !           667: /*
        !           668:  * killone()
        !           669:  *
        !           670:  *  Erase the last character on the line.
        !           671:  */
        !           672: 
        !           673: static void
        !           674: killone()
        !           675: {
        !           676:     if (lineend) {
        !           677:        return;                 /* ??? XXX */
        !           678:     }
        !           679:     if (nextin == linein) {
        !           680:        return;                 /* Nothing to do */
        !           681:     }
        !           682:     nextin--;
        !           683:     if (!(isspace(*nextin) || isprint(*nextin))) {
        !           684:        putchar('\b');
        !           685:        putchar(' ');
        !           686:        putchar('\b');
        !           687:     }
        !           688:     putchar('\b');
        !           689:     putchar(' ');
        !           690:     putchar('\b');
        !           691: }
        !           692: 
        !           693: 
        !           694: /*
        !           695:  * setlineend()
        !           696:  *
        !           697:  *  Decide if it's time to send the current line up to the user
        !           698:  * process.
        !           699:  */
        !           700: 
        !           701: static void
        !           702: setlineend()
        !           703: {
        !           704:     if (nextin == nextout) {
        !           705:        return;
        !           706:     }
        !           707:     if (characteratatime()) {
        !           708:        lineend = 1;
        !           709:     } else if (nextin >= (linein+sizeof linein)) {
        !           710:        lineend = 1;
        !           711:     } else {
        !           712:        int c = *(nextin-1);
        !           713:        if ((c == termIntChar)
        !           714:                || (c == termQuitChar)
        !           715:                || (c == termEofChar)) {
        !           716:            lineend = 1;
        !           717:        } else if (c == termFlushChar) {
        !           718:            lineend = 1;
        !           719:        } else if ((c == '\n') || (c == '\r')) {
        !           720:            lineend = 1;
        !           721:        }
        !           722:     }
        !           723:     /* Otherwise, leave it alone (reset by 'consumechar') */
        !           724: }
        !           725: 
        !           726: /*
        !           727:  * OK, what we do here is:
        !           728:  *
        !           729:  *   o  If we are echoing, then
        !           730:  *     o  Look for character erase, line kill characters
        !           731:  *     o  Echo the character (using '^' if a control character)
        !           732:  *   o  Put the character in the input buffer
        !           733:  *   o  Set 'lineend' as necessary
        !           734:  */
        !           735: 
        !           736: static void
        !           737: DoNextChar(c)
        !           738: int    c;                      /* Character to process */
        !           739: {
        !           740:     static char literalnextcharacter = 0;
        !           741: 
        !           742:     if (nextin >= (linein+sizeof linein)) {
        !           743:        putchar('\7');          /* Ring bell */
        !           744:        setlineend();
        !           745:        return;
        !           746:     }
        !           747:     if (MODE_LOCAL_CHARS(globalmode)) {
        !           748:        /* Look for some special character */
        !           749:        if (!literalnextcharacter) {
        !           750:            if (c == termEraseChar) {
        !           751:                killone();
        !           752:                setlineend();
        !           753:                return;
        !           754:            } else if (c == termKillChar) {
        !           755:                while (nextin != linein) {
        !           756:                    killone();
        !           757:                }
        !           758:                setlineend();
        !           759:                return;
        !           760:            } else if (c == termLiteralNextChar) {
        !           761:                literalnextcharacter = 1;
        !           762:                return;
        !           763:            }
        !           764:        }
        !           765: 
        !           766:        if (MODE_LOCAL_ECHO(globalmode)) {
        !           767:            if ((literalnextcharacter == 0) && ((c == '\r') || (c == '\n'))) {
        !           768:                putchar('\r');
        !           769:                putchar('\n');
        !           770:                c = '\n';
        !           771:            } else if (!isprint(c) && !isspace(c)) {
        !           772:                putchar('^');
        !           773:                putchar(c^0x40);
        !           774:            } else {
        !           775:                putchar(c);
        !           776:            }
        !           777:        }
        !           778:        literalnextcharacter = 0;
        !           779:     }
        !           780:     *nextin++ = c;
        !           781:     setlineend();
        !           782: }
        !           783: 
        !           784: static int
        !           785: inputExists()
        !           786: {
        !           787:     int input;
        !           788:     static state = 0;
        !           789: 
        !           790:     while (ctrlCCount) {
        !           791:        DoNextChar(0x03);
        !           792:        ctrlCCount--;
        !           793:     }
        !           794:     if (lineend) {
        !           795:        return 1;
        !           796:     }
        !           797: #if    1       /* For BIOS variety of calls */
        !           798:     if (kbhit() == 0) {
        !           799:        return lineend;
        !           800:     }
        !           801:     input = getch();                   /* MSC - get console character */
        !           802:     if ((input&0xff) == 0) {
        !           803:        DoNextChar(0x01);               /* ^A */
        !           804:     } else {
        !           805:        DoNextChar(input&0xff);
        !           806:     }
        !           807: #else  /* 0 */
        !           808:     if ((input = dirconio()) == -1) {
        !           809:        return lineend;
        !           810:     }
        !           811:     if ((input&0xff) == 0) {
        !           812:        if ((input&0xff00) == 0x0300) {         /* Null */
        !           813:            DoNextChar(0);
        !           814:        } else {
        !           815:            DoNextChar(0x01);
        !           816:            if (input&0x8000) {
        !           817:                DoNextChar(0x01);
        !           818:                DoNextChar((input>>8)&0x7f);
        !           819:            } else {
        !           820:                DoNextChar((input>>8)&0xff);
        !           821:            }
        !           822:        }
        !           823:     } else {
        !           824:        DoNextChar(input&0xff);
        !           825:     }
        !           826: #endif /* 0 */
        !           827:     return lineend;
        !           828: }
        !           829: 
        !           830: 
        !           831: void
        !           832: CtrlCInterrupt()
        !           833: {
        !           834:     if (!MODE_COMMAND_LINE(globalmode)) {
        !           835:        char far *Bios_Break = (char far *) (((long)0x40<<16)|0x71);
        !           836: 
        !           837:        *Bios_Break = 0;
        !           838:        ctrlCCount++;           /* XXX */
        !           839:        signal(SIGINT, CtrlCInterrupt);
        !           840:     } else {
        !           841:        closeallsockets();
        !           842:        exit(1);
        !           843:     }
        !           844: }
        !           845: 
        !           846: int
        !           847: dosbinary(fd, onoff)
        !           848: int    fd;
        !           849: int    onoff;
        !           850: {
        !           851:     union REGS regs;
        !           852:     int oldstate;
        !           853: 
        !           854:     /* Get old stuff */
        !           855:     regs.h.ah = 0x44;
        !           856:     regs.h.al = 0;
        !           857:     regs.x.bx = fd;
        !           858:     intdos(&regs, &regs);
        !           859:     oldstate = regs.h.dl&(1<<5);               /* Save state */
        !           860: 
        !           861:     /* Set correct bits in new mode */
        !           862:     regs.h.dh = 0;
        !           863:     if (onoff) {
        !           864:        regs.h.dl |= 1<<5;
        !           865:     } else {
        !           866:        regs.h.dl &= ~(1<<5);
        !           867:     }
        !           868: 
        !           869:     /* Set in new mode */
        !           870:     regs.h.ah = 0x44;
        !           871:     regs.h.al = 1;
        !           872:     regs.x.bx = fd;
        !           873:     intdos(&regs, &regs);
        !           874: 
        !           875:     return oldstate;
        !           876: }
        !           877: 
        !           878: /*
        !           879:  * The MSDOS routines, called from elsewhere.
        !           880:  */
        !           881: 
        !           882: 
        !           883: static int
        !           884: TerminalAutoFlush()                            /* MSDOS */
        !           885: {
        !           886:     return 1;
        !           887: }
        !           888: 
        !           889: static int
        !           890: TerminalCanRead()
        !           891: {
        !           892:     return inputExists();
        !           893: }
        !           894: 
        !           895: 
        !           896: /*
        !           897:  * Flush output to the terminal
        !           898:  */
        !           899:  
        !           900: static void
        !           901: TerminalFlushOutput()                          /* MSDOS */
        !           902: {
        !           903: }
        !           904: 
        !           905: 
        !           906: static void
        !           907: TerminalNewMode(f)                             /* MSDOS */
        !           908: register int f;
        !           909: {
        !           910:     union REGS inregs;
        !           911:     struct SREGS segregs;
        !           912:     static old_1b_offset = 0, old_1b_segment = 0;
        !           913: 
        !           914:     globalmode = f;
        !           915:     if (MODE_COMMAND_LINE(f)) {
        !           916:        signal(SIGINT, SIG_DFL);
        !           917:        if (old_1b_segment|old_1b_offset) {
        !           918:            inregs.h.ah = 0x25;
        !           919:            inregs.h.al = 0x1b;
        !           920:            inregs.x.dx = old_1b_offset;
        !           921:            segregs.ds = old_1b_segment;
        !           922:            intdosx(&inregs, &inregs, &segregs);
        !           923:            old_1b_segment = old_1b_offset = 0;
        !           924:        }
        !           925:        if (setmode(fileno(stdout), O_TEXT) == -1) {
        !           926:            ExitPerror("setmode (text)", 1);
        !           927:        }
        !           928:        (void) dosbinary(fileno(stdout), 0);
        !           929:        if (setmode(fileno(stdin), O_TEXT) == -1) {
        !           930:            ExitPerror("setmode (text)", 1);
        !           931:        }
        !           932:        (void) dosbinary(fileno(stdin), 0);
        !           933:     } else {
        !           934:        signal(SIGINT, CtrlCInterrupt);
        !           935:        if ((old_1b_segment|old_1b_offset) == 0) {
        !           936:            extern void iret_subr();
        !           937:            void (far *foo_subr)() = iret_subr;
        !           938: 
        !           939:            inregs.h.ah = 0x35;
        !           940:            inregs.h.al = 0x1b;
        !           941:            intdosx(&inregs, &inregs, &segregs);
        !           942:            old_1b_segment = segregs.es;
        !           943:            old_1b_offset = inregs.x.bx;
        !           944:            inregs.h.ah = 0x25;
        !           945:            inregs.h.al = 0x1b;
        !           946:            inregs.x.dx = FP_OFF(foo_subr);
        !           947:            segregs.ds = FP_SEG(foo_subr);
        !           948:            intdosx(&inregs, &inregs, &segregs);
        !           949:        }
        !           950:        if (MODE_LOCAL_CHARS(f)) {
        !           951:            if (setmode(fileno(stdout), O_TEXT) == -1) {
        !           952:                ExitPerror("setmode (text)", 1);
        !           953:            }
        !           954:            (void) dosbinary(fileno(stdout), 0);
        !           955:            if (setmode(fileno(stdin), O_TEXT) == -1) {
        !           956:                ExitPerror("setmode (text)", 1);
        !           957:            }
        !           958:            (void) dosbinary(fileno(stdin), 0);
        !           959:        } else {
        !           960:            if (setmode(fileno(stdout), O_BINARY) == -1) {
        !           961:                ExitPerror("setmode (binary)", 1);
        !           962:            }
        !           963:            (void) dosbinary(fileno(stdout), 1);
        !           964:            if (setmode(fileno(stdin), O_BINARY) == -1) {
        !           965:                ExitPerror("setmode (binary)", 1);
        !           966:            }
        !           967:            (void) dosbinary(fileno(stdin), 1);
        !           968:        }
        !           969:     }
        !           970: }
        !           971: 
        !           972: 
        !           973: int
        !           974: TerminalRead(fd, buffer, count)
        !           975: int    fd;
        !           976: char   *buffer;
        !           977: int    count;
        !           978: {
        !           979:     int done = 0;
        !           980: 
        !           981:     for (;;) {
        !           982:        while (inputExists() && (done < count)) {
        !           983:            *buffer++ = *nextout;
        !           984:            consumechar();
        !           985:            done++;
        !           986:        }
        !           987:        if (done) {
        !           988:            return(done);
        !           989:        } else {
        !           990:            return 0;
        !           991:        }
        !           992:     }
        !           993: }
        !           994: 
        !           995: 
        !           996: static void
        !           997: TerminalSaveState()                            /* MSDOS */
        !           998: {
        !           999:     savedInState = dosbinary(fileno(stdin), 0);
        !          1000:     savedOutState = dosbinary(fileno(stdout), 0);
        !          1001: }
        !          1002: 
        !          1003: int
        !          1004: TerminalSpecialChars(c)                        /* MSDOS */
        !          1005: {
        !          1006:     return 1;
        !          1007: }
        !          1008: 
        !          1009: 
        !          1010: static void
        !          1011: TerminalRestoreState()                         /* MSDOS */
        !          1012: {
        !          1013:     (void) dosbinary(fileno(stdin), savedInState);
        !          1014:     (void) dosbinary(fileno(stdout), savedOutState);
        !          1015: }
        !          1016: 
        !          1017: 
        !          1018: static int
        !          1019: TerminalWrite(fd, buffer, count)               /* MSDOS */
        !          1020: int    fd;
        !          1021: char   *buffer;
        !          1022: int    count;
        !          1023: {
        !          1024:     return fwrite(buffer, sizeof (char), count, stdout);
        !          1025: }
        !          1026: 
        !          1027: 
        !          1028: static int
        !          1029: NetClose(fd)
        !          1030: {
        !          1031:     return closesocket(fd);
        !          1032: }
        !          1033: 
        !          1034: static void
        !          1035: NetNonblockingIO(fd, onoff)                            /* MSDOS */
        !          1036: int
        !          1037:        fd,
        !          1038:        onoff;
        !          1039: {
        !          1040:     if (SetSockOpt(net, SOL_SOCKET, SO_NONBLOCKING, onoff)) {
        !          1041:        perror("setsockop (SO_NONBLOCKING) ");
        !          1042:        ExitString(stderr, "exiting\n", 1);
        !          1043:     }
        !          1044: }
        !          1045: 
        !          1046: static void
        !          1047: NetSigIO(fd)                           /* MSDOS */
        !          1048: int fd;
        !          1049: {
        !          1050: }
        !          1051: 
        !          1052: static void
        !          1053: NetSetPgrp(fd)                         /* MSDOS */
        !          1054: int fd;
        !          1055: {
        !          1056: }
        !          1057: 
        !          1058: 
        !          1059: #endif /* defined(MSDOS) */
        !          1060: 
        !          1061: /*
        !          1062:  * Initialize variables.
        !          1063:  */
        !          1064: 
        !          1065: static void
        !          1066: tninit()
        !          1067: {
        !          1068: #if    defined(TN3270)
        !          1069:     Sent3270TerminalType = 0;
        !          1070:     Ifrontp = Ibackp = Ibuf;
        !          1071: #endif /* defined(TN3270) */
        !          1072: 
        !          1073:     tfrontp = tbackp = ttyobuf;
        !          1074:     nfrontp = nbackp = netobuf;
        !          1075:     
        !          1076:     /* Don't change telnetport */
        !          1077:     SB_CLEAR();
        !          1078:     ClearArray(hisopts);
        !          1079:     ClearArray(myopts);
        !          1080:     sbp = sibuf;
        !          1081:     tbp = tibuf;
        !          1082: 
        !          1083:     connected = net = scc = tcc = In3270 = ISend = donebinarytoggle = 0;
        !          1084:     telnetport = 0;
        !          1085: #if    defined(unix)
        !          1086:     HaveInput = 0;
        !          1087: #endif /* defined(unix) */
        !          1088: 
        !          1089:     SYNCHing = 0;
        !          1090: 
        !          1091:     errno = 0;
        !          1092: 
        !          1093:     flushline = 0;
        !          1094: 
        !          1095:     /* Don't change NetTrace */
        !          1096: 
        !          1097:     escape = CONTROL(']');
        !          1098:     echoc = CONTROL('E');
        !          1099: 
        !          1100:     flushline = 1;
        !          1101:     sp = getservbyname("telnet", "tcp");
        !          1102:     if (sp == 0) {
        !          1103:        ExitString(stderr, "telnet: tcp/telnet: unknown service\n",1);
        !          1104:        /*NOTREACHED*/
        !          1105:     }
        !          1106: 
        !          1107: #if    defined(TN3270)
        !          1108:     init_ctlr();               /* Initialize some things */
        !          1109:     init_keyboard();
        !          1110:     init_screen();
        !          1111:     init_system();
        !          1112: #endif /* defined(TN3270) */
        !          1113: }
        !          1114: 
        !          1115: /*
        !          1116:  * Various utility routines.
        !          1117:  */
        !          1118: 
        !          1119: static void
        !          1120: makeargv()
        !          1121: {
        !          1122:     register char *cp;
        !          1123:     register char **argp = margv;
        !          1124: 
        !          1125:     margc = 0;
        !          1126:     cp = line;
        !          1127:     if (*cp == '!') {          /* Special case shell escape */
        !          1128:        *argp++ = "!";          /* No room in string to get this */
        !          1129:        margc++;
        !          1130:        cp++;
        !          1131:     }
        !          1132:     while (*cp) {
        !          1133:        while (isspace(*cp))
        !          1134:            cp++;
        !          1135:        if (*cp == '\0')
        !          1136:            break;
        !          1137:        *argp++ = cp;
        !          1138:        margc += 1;
        !          1139:        while (*cp != '\0' && !isspace(*cp))
        !          1140:            cp++;
        !          1141:        if (*cp == '\0')
        !          1142:            break;
        !          1143:        *cp++ = '\0';
        !          1144:     }
        !          1145:     *argp++ = 0;
        !          1146: }
        !          1147: 
        !          1148: static char *ambiguous;                /* special return value */
        !          1149: #define Ambiguous(t)   ((t)&ambiguous)
        !          1150: 
        !          1151: 
        !          1152: static char **
        !          1153: genget(name, table, next)
        !          1154: char   *name;          /* name to match */
        !          1155: char   **table;                /* name entry in table */
        !          1156: char   **(*next)();    /* routine to return next entry in table */
        !          1157: {
        !          1158:        register char *p, *q;
        !          1159:        register char **c, **found;
        !          1160:        register int nmatches, longest;
        !          1161: 
        !          1162:        if (name == 0) {
        !          1163:            return 0;
        !          1164:        }
        !          1165:        longest = 0;
        !          1166:        nmatches = 0;
        !          1167:        found = 0;
        !          1168:        for (c = table; (p = *c) != 0; c = (*next)(c)) {
        !          1169:                for (q = name;
        !          1170:                    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
        !          1171:                        if (*q == 0)            /* exact match? */
        !          1172:                                return (c);
        !          1173:                if (!*q) {                      /* the name was a prefix */
        !          1174:                        if (q - name > longest) {
        !          1175:                                longest = q - name;
        !          1176:                                nmatches = 1;
        !          1177:                                found = c;
        !          1178:                        } else if (q - name == longest)
        !          1179:                                nmatches++;
        !          1180:                }
        !          1181:        }
        !          1182:        if (nmatches > 1)
        !          1183:                return Ambiguous(char **);
        !          1184:        return (found);
        !          1185: }
        !          1186: 
        !          1187: /*
        !          1188:  * Make a character string into a number.
        !          1189:  *
        !          1190:  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
        !          1191:  */
        !          1192: 
        !          1193: static
        !          1194: special(s)
        !          1195: register char *s;
        !          1196: {
        !          1197:        register char c;
        !          1198:        char b;
        !          1199: 
        !          1200:        switch (*s) {
        !          1201:        case '^':
        !          1202:                b = *++s;
        !          1203:                if (b == '?') {
        !          1204:                    c = b | 0x40;               /* DEL */
        !          1205:                } else {
        !          1206:                    c = b & 0x1f;
        !          1207:                }
        !          1208:                break;
        !          1209:        default:
        !          1210:                c = *s;
        !          1211:                break;
        !          1212:        }
        !          1213:        return c;
        !          1214: }
        !          1215: 
        !          1216: /*
        !          1217:  * Construct a control character sequence
        !          1218:  * for a special character.
        !          1219:  */
        !          1220: static char *
        !          1221: control(c)
        !          1222:        register int c;
        !          1223: {
        !          1224:        static char buf[3];
        !          1225: 
        !          1226:        if (c == 0x7f)
        !          1227:                return ("^?");
        !          1228:        if (c == '\377') {
        !          1229:                return "off";
        !          1230:        }
        !          1231:        if (c >= 0x20) {
        !          1232:                buf[0] = c;
        !          1233:                buf[1] = 0;
        !          1234:        } else {
        !          1235:                buf[0] = '^';
        !          1236:                buf[1] = '@'+c;
        !          1237:                buf[2] = 0;
        !          1238:        }
        !          1239:        return (buf);
        !          1240: }
        !          1241: 
        !          1242: 
        !          1243: /*
        !          1244:  * upcase()
        !          1245:  *
        !          1246:  *     Upcase (in place) the argument.
        !          1247:  */
        !          1248: 
        !          1249: static void
        !          1250: upcase(argument)
        !          1251: register char *argument;
        !          1252: {
        !          1253:     register int c;
        !          1254: 
        !          1255:     while ((c = *argument) != 0) {
        !          1256:        if (islower(c)) {
        !          1257:            *argument = toupper(c);
        !          1258:        }
        !          1259:        argument++;
        !          1260:     }
        !          1261: }
        !          1262: 
        !          1263: /*
        !          1264:  * SetSockOpt()
        !          1265:  *
        !          1266:  * Compensate for differences in 4.2 and 4.3 systems.
        !          1267:  */
        !          1268: 
        !          1269: static int
        !          1270: SetSockOpt(fd, level, option, yesno)
        !          1271: int
        !          1272:        fd,
        !          1273:        level,
        !          1274:        option,
        !          1275:        yesno;
        !          1276: {
        !          1277: #ifndef        NOT43
        !          1278:     return setsockopt(fd, level, option,
        !          1279:                                (char *)&yesno, sizeof yesno);
        !          1280: #else  /* NOT43 */
        !          1281:     if (yesno == 0) {          /* Can't do that in 4.2! */
        !          1282:        fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
        !          1283:                                option);
        !          1284:        return -1;
        !          1285:     }
        !          1286:     return setsockopt(fd, level, option, 0, 0);
        !          1287: #endif /* NOT43 */
        !          1288: }
        !          1289: 
        !          1290: /*
        !          1291:  * The following are routines used to print out debugging information.
        !          1292:  */
        !          1293: 
        !          1294: 
        !          1295: static void
        !          1296: Dump(direction, buffer, length)
        !          1297: char   direction;
        !          1298: char   *buffer;
        !          1299: int    length;
        !          1300: {
        !          1301: #   define BYTES_PER_LINE      32
        !          1302: #   define min(x,y)    ((x<y)? x:y)
        !          1303:     char *pThis;
        !          1304:     int offset;
        !          1305: 
        !          1306:     offset = 0;
        !          1307: 
        !          1308:     while (length) {
        !          1309:        /* print one line */
        !          1310:        fprintf(NetTrace, "%c 0x%x\t", direction, offset);
        !          1311:        pThis = buffer;
        !          1312:        buffer = buffer+min(length, BYTES_PER_LINE);
        !          1313:        while (pThis < buffer) {
        !          1314:            fprintf(NetTrace, "%.2x", (*pThis)&0xff);
        !          1315:            pThis++;
        !          1316:        }
        !          1317:        fprintf(NetTrace, "\n");
        !          1318:        length -= BYTES_PER_LINE;
        !          1319:        offset += BYTES_PER_LINE;
        !          1320:        if (length < 0) {
        !          1321:            return;
        !          1322:        }
        !          1323:        /* find next unique line */
        !          1324:     }
        !          1325: }
        !          1326: 
        !          1327: 
        !          1328: /*VARARGS*/
        !          1329: static void
        !          1330: printoption(direction, fmt, option, what)
        !          1331:        char *direction, *fmt;
        !          1332:        int option, what;
        !          1333: {
        !          1334:        if (!showoptions)
        !          1335:                return;
        !          1336:        fprintf(NetTrace, "%s ", direction+1);
        !          1337:        if (fmt == doopt)
        !          1338:                fmt = "do";
        !          1339:        else if (fmt == dont)
        !          1340:                fmt = "dont";
        !          1341:        else if (fmt == will)
        !          1342:                fmt = "will";
        !          1343:        else if (fmt == wont)
        !          1344:                fmt = "wont";
        !          1345:        else
        !          1346:                fmt = "???";
        !          1347:        if (option < (sizeof telopts/sizeof telopts[0]))
        !          1348:                fprintf(NetTrace, "%s %s", fmt, telopts[option]);
        !          1349:        else
        !          1350:                fprintf(NetTrace, "%s %d", fmt, option);
        !          1351:        if (*direction == '<') {
        !          1352:                fprintf(NetTrace, "\r\n");
        !          1353:                return;
        !          1354:        }
        !          1355:        fprintf(NetTrace, " (%s)\r\n", what ? "reply" : "don't reply");
        !          1356: }
        !          1357: 
        !          1358: static void
        !          1359: printsub(direction, pointer, length)
        !          1360: char   *direction,             /* "<" or ">" */
        !          1361:        *pointer;               /* where suboption data sits */
        !          1362: int    length;                 /* length of suboption data */
        !          1363: {
        !          1364:     if (showoptions) {
        !          1365:        fprintf(NetTrace, "%s suboption ",
        !          1366:                                (direction[0] == '<')? "Received":"Sent");
        !          1367:        switch (pointer[0]) {
        !          1368:        case TELOPT_TTYPE:
        !          1369:            fprintf(NetTrace, "Terminal type ");
        !          1370:            switch (pointer[1]) {
        !          1371:            case TELQUAL_IS:
        !          1372:                {
        !          1373:                    char tmpbuf[sizeof subbuffer];
        !          1374:                    int minlen = min(length-4, sizeof tmpbuf-1);
        !          1375: 
        !          1376:                    memcpy(tmpbuf, pointer+2, minlen);
        !          1377:                    tmpbuf[minlen] = 0;
        !          1378:                    fprintf(NetTrace, "is %s.\n", tmpbuf);
        !          1379:                }
        !          1380:                break;
        !          1381:            case TELQUAL_SEND:
        !          1382:                fprintf(NetTrace, "- request to send.\n");
        !          1383:                break;
        !          1384:            default:
        !          1385:                fprintf(NetTrace,
        !          1386:                                "- unknown qualifier %d (0x%x).\n", pointer[1]);
        !          1387:            }
        !          1388:            break;
        !          1389:        default:
        !          1390:            fprintf(NetTrace, "Unknown option %d (0x%x)\n",
        !          1391:                                        pointer[0], pointer[0]);
        !          1392:        }
        !          1393:     }
        !          1394: }
        !          1395: 
        !          1396: /*
        !          1397:  * Check to see if any out-of-band data exists on a socket (for
        !          1398:  * Telnet "synch" processing).
        !          1399:  */
        !          1400: 
        !          1401: static int
        !          1402: stilloob(s)
        !          1403: int    s;              /* socket number */
        !          1404: {
        !          1405:     static struct timeval timeout = { 0 };
        !          1406:     fd_set     excepts;
        !          1407:     int value;
        !          1408: 
        !          1409:     do {
        !          1410:        FD_ZERO(&excepts);
        !          1411:        FD_SET(s, &excepts);
        !          1412:        value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout);
        !          1413:     } while ((value == -1) && (errno == EINTR));
        !          1414: 
        !          1415:     if (value < 0) {
        !          1416:        perror("select");
        !          1417:        quit();
        !          1418:     }
        !          1419:     if (FD_ISSET(s, &excepts)) {
        !          1420:        return 1;
        !          1421:     } else {
        !          1422:        return 0;
        !          1423:     }
        !          1424: }
        !          1425: 
        !          1426: 
        !          1427: /*
        !          1428:  *  netflush
        !          1429:  *             Send as much data as possible to the network,
        !          1430:  *     handling requests for urgent data.
        !          1431:  *
        !          1432:  *             The return value indicates whether we did any
        !          1433:  *     useful work.
        !          1434:  */
        !          1435: 
        !          1436: 
        !          1437: int
        !          1438: netflush()
        !          1439: {
        !          1440:     int n;
        !          1441: 
        !          1442:     if ((n = nfrontp - nbackp) > 0) {
        !          1443:        if (!neturg) {
        !          1444:            n = send(net, nbackp, n, 0);        /* normal write */
        !          1445:        } else {
        !          1446:            n = neturg - nbackp;
        !          1447:            /*
        !          1448:             * In 4.2 (and 4.3) systems, there is some question about
        !          1449:             * what byte in a sendOOB operation is the "OOB" data.
        !          1450:             * To make ourselves compatible, we only send ONE byte
        !          1451:             * out of band, the one WE THINK should be OOB (though
        !          1452:             * we really have more the TCP philosophy of urgent data
        !          1453:             * rather than the Unix philosophy of OOB data).
        !          1454:             */
        !          1455:            if (n > 1) {
        !          1456:                n = send(net, nbackp, n-1, 0);  /* send URGENT all by itself */
        !          1457:            } else {
        !          1458:                n = send(net, nbackp, n, MSG_OOB);      /* URGENT data */
        !          1459:            }
        !          1460:        }
        !          1461:     }
        !          1462:     if (n < 0) {
        !          1463:        if (errno != ENOBUFS && errno != EWOULDBLOCK) {
        !          1464:            setcommandmode();
        !          1465:            perror(hostname);
        !          1466:            NetClose(net);
        !          1467:            neturg = 0;
        !          1468:            longjmp(peerdied, -1);
        !          1469:            /*NOTREACHED*/
        !          1470:        }
        !          1471:        n = 0;
        !          1472:     }
        !          1473:     if (netdata && n) {
        !          1474:        Dump('>', nbackp, n);
        !          1475:     }
        !          1476:     nbackp += n;
        !          1477:     if (nbackp >= neturg) {
        !          1478:        neturg = 0;
        !          1479:     }
        !          1480:     if (nbackp == nfrontp) {
        !          1481:        nbackp = nfrontp = netobuf;
        !          1482:     }
        !          1483:     return n > 0;
        !          1484: }
        !          1485: 
        !          1486: /*
        !          1487:  * nextitem()
        !          1488:  *
        !          1489:  *     Return the address of the next "item" in the TELNET data
        !          1490:  * stream.  This will be the address of the next character if
        !          1491:  * the current address is a user data character, or it will
        !          1492:  * be the address of the character following the TELNET command
        !          1493:  * if the current address is a TELNET IAC ("I Am a Command")
        !          1494:  * character.
        !          1495:  */
        !          1496: 
        !          1497: static char *
        !          1498: nextitem(current)
        !          1499: char   *current;
        !          1500: {
        !          1501:     if ((*current&0xff) != IAC) {
        !          1502:        return current+1;
        !          1503:     }
        !          1504:     switch (*(current+1)&0xff) {
        !          1505:     case DO:
        !          1506:     case DONT:
        !          1507:     case WILL:
        !          1508:     case WONT:
        !          1509:        return current+3;
        !          1510:     case SB:           /* loop forever looking for the SE */
        !          1511:        {
        !          1512:            register char *look = current+2;
        !          1513: 
        !          1514:            for (;;) {
        !          1515:                if ((*look++&0xff) == IAC) {
        !          1516:                    if ((*look++&0xff) == SE) {
        !          1517:                        return look;
        !          1518:                    }
        !          1519:                }
        !          1520:            }
        !          1521:        }
        !          1522:     default:
        !          1523:        return current+2;
        !          1524:     }
        !          1525: }
        !          1526: /*
        !          1527:  * netclear()
        !          1528:  *
        !          1529:  *     We are about to do a TELNET SYNCH operation.  Clear
        !          1530:  * the path to the network.
        !          1531:  *
        !          1532:  *     Things are a bit tricky since we may have sent the first
        !          1533:  * byte or so of a previous TELNET command into the network.
        !          1534:  * So, we have to scan the network buffer from the beginning
        !          1535:  * until we are up to where we want to be.
        !          1536:  *
        !          1537:  *     A side effect of what we do, just to keep things
        !          1538:  * simple, is to clear the urgent data pointer.  The principal
        !          1539:  * caller should be setting the urgent data pointer AFTER calling
        !          1540:  * us in any case.
        !          1541:  */
        !          1542: 
        !          1543: static void
        !          1544: netclear()
        !          1545: {
        !          1546:     register char *thisitem, *next;
        !          1547:     char *good;
        !          1548: #define        wewant(p)       ((nfrontp > p) && ((*p&0xff) == IAC) && \
        !          1549:                                ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
        !          1550: 
        !          1551:     thisitem = netobuf;
        !          1552: 
        !          1553:     while ((next = nextitem(thisitem)) <= nbackp) {
        !          1554:        thisitem = next;
        !          1555:     }
        !          1556: 
        !          1557:     /* Now, thisitem is first before/at boundary. */
        !          1558: 
        !          1559:     good = netobuf;    /* where the good bytes go */
        !          1560: 
        !          1561:     while (nfrontp > thisitem) {
        !          1562:        if (wewant(thisitem)) {
        !          1563:            int length;
        !          1564: 
        !          1565:            next = thisitem;
        !          1566:            do {
        !          1567:                next = nextitem(next);
        !          1568:            } while (wewant(next) && (nfrontp > next));
        !          1569:            length = next-thisitem;
        !          1570:            memcpy(good, thisitem, length);
        !          1571:            good += length;
        !          1572:            thisitem = next;
        !          1573:        } else {
        !          1574:            thisitem = nextitem(thisitem);
        !          1575:        }
        !          1576:     }
        !          1577: 
        !          1578:     nbackp = netobuf;
        !          1579:     nfrontp = good;            /* next byte to be sent */
        !          1580:     neturg = 0;
        !          1581: }
        !          1582: 
        !          1583: /*
        !          1584:  * These routines add various telnet commands to the data stream.
        !          1585:  */
        !          1586: 
        !          1587: #if    defined(NOT43)
        !          1588: static int
        !          1589: #else  /* defined(NOT43) */
        !          1590: static void
        !          1591: #endif /* defined(NOT43) */
        !          1592: dosynch()
        !          1593: {
        !          1594:     netclear();                        /* clear the path to the network */
        !          1595:     NET2ADD(IAC, DM);
        !          1596:     neturg = NETLOC()-1;       /* Some systems are off by one XXX */
        !          1597: 
        !          1598: #if    defined(NOT43)
        !          1599:     return 0;
        !          1600: #endif /* defined(NOT43) */
        !          1601: }
        !          1602: 
        !          1603: static void
        !          1604: doflush()
        !          1605: {
        !          1606:     NET2ADD(IAC, DO);
        !          1607:     NETADD(TELOPT_TM);
        !          1608:     flushline = 1;
        !          1609:     flushout = 1;
        !          1610:     ttyflush();
        !          1611:     /* do printoption AFTER flush, otherwise the output gets tossed... */
        !          1612:     printoption("<SENT", doopt, TELOPT_TM, 0);
        !          1613: }
        !          1614: 
        !          1615: static void
        !          1616: intp()
        !          1617: {
        !          1618:     NET2ADD(IAC, IP);
        !          1619:     if (autoflush) {
        !          1620:        doflush();
        !          1621:     }
        !          1622:     if (autosynch) {
        !          1623:        dosynch();
        !          1624:     }
        !          1625: }
        !          1626: 
        !          1627: static void
        !          1628: sendbrk()
        !          1629: {
        !          1630:     NET2ADD(IAC, BREAK);
        !          1631:     if (autoflush) {
        !          1632:        doflush();
        !          1633:     }
        !          1634:     if (autosynch) {
        !          1635:        dosynch();
        !          1636:     }
        !          1637: }
        !          1638: 
        !          1639: /*
        !          1640:  *             Send as much data as possible to the terminal.
        !          1641:  *
        !          1642:  *             The return value indicates whether we did any
        !          1643:  *     useful work.
        !          1644:  */
        !          1645: 
        !          1646: 
        !          1647: static int
        !          1648: ttyflush()
        !          1649: {
        !          1650:     int n;
        !          1651: 
        !          1652:     if ((n = tfrontp - tbackp) > 0) {
        !          1653:        if (!(SYNCHing||flushout)) {
        !          1654:            n = TerminalWrite(tout, tbackp, n);
        !          1655:        } else {
        !          1656:            TerminalFlushOutput();
        !          1657:            /* we leave 'n' alone! */
        !          1658:        }
        !          1659:     }
        !          1660:     if (n >= 0) {
        !          1661:        tbackp += n;
        !          1662:        if (tbackp == tfrontp) {
        !          1663:            tbackp = tfrontp = ttyobuf;
        !          1664:        }
        !          1665:     }
        !          1666:     return n > 0;
        !          1667: }
        !          1668: 
        !          1669: #if    defined(TN3270)
        !          1670: 
        !          1671: #if    defined(unix)
        !          1672: static void
        !          1673: inputAvailable()
        !          1674: {
        !          1675:     HaveInput = 1;
        !          1676: }
        !          1677: #endif /* defined(unix) */
        !          1678: 
        !          1679: void
        !          1680: outputPurge()
        !          1681: {
        !          1682:     int tmp = flushout;
        !          1683: 
        !          1684:     flushout = 1;
        !          1685: 
        !          1686:     ttyflush();
        !          1687: 
        !          1688:     flushout = tmp;
        !          1689: }
        !          1690: 
        !          1691: #endif /* defined(TN3270) */
        !          1692: 
        !          1693: #if    defined(unix)
        !          1694: /*
        !          1695:  * Various signal handling routines.
        !          1696:  */
        !          1697: 
        !          1698: static void
        !          1699: deadpeer()
        !          1700: {
        !          1701:        setcommandmode();
        !          1702:        longjmp(peerdied, -1);
        !          1703: }
        !          1704: 
        !          1705: static void
        !          1706: intr()
        !          1707: {
        !          1708:     if (localchars) {
        !          1709:        intp();
        !          1710:        return;
        !          1711:     }
        !          1712:     setcommandmode();
        !          1713:     longjmp(toplevel, -1);
        !          1714: }
        !          1715: 
        !          1716: static void
        !          1717: intr2()
        !          1718: {
        !          1719:     if (localchars) {
        !          1720:        sendbrk();
        !          1721:        return;
        !          1722:     }
        !          1723: }
        !          1724: 
        !          1725: static void
        !          1726: doescape()
        !          1727: {
        !          1728:     command(0);
        !          1729: }
        !          1730: #endif /* defined(unix) */
        !          1731: 
        !          1732: /*
        !          1733:  * These routines decides on what the mode should be (based on the values
        !          1734:  * of various global variables).
        !          1735:  */
        !          1736: 
        !          1737: 
        !          1738: static
        !          1739: getconnmode()
        !          1740: {
        !          1741:     static char newmode[16] =
        !          1742:                        { 4, 5, 3, 3, 2, 2, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6 };
        !          1743:     int modeindex = 0;
        !          1744: 
        !          1745:     if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
        !          1746:        modeindex += 1;
        !          1747:     }
        !          1748:     if (hisopts[TELOPT_ECHO]) {
        !          1749:        modeindex += 2;
        !          1750:     }
        !          1751:     if (hisopts[TELOPT_SGA]) {
        !          1752:        modeindex += 4;
        !          1753:     }
        !          1754:     if (In3270) {
        !          1755:        modeindex += 8;
        !          1756:     }
        !          1757:     return newmode[modeindex];
        !          1758: }
        !          1759: 
        !          1760: void
        !          1761: setconnmode()
        !          1762: {
        !          1763:     TerminalNewMode(getconnmode());
        !          1764: }
        !          1765: 
        !          1766: 
        !          1767: void
        !          1768: setcommandmode()
        !          1769: {
        !          1770:     TerminalNewMode(0);
        !          1771: }
        !          1772: 
        !          1773: static void
        !          1774: willoption(option, reply)
        !          1775:        int option, reply;
        !          1776: {
        !          1777:        char *fmt;
        !          1778: 
        !          1779:        switch (option) {
        !          1780: 
        !          1781:        case TELOPT_ECHO:
        !          1782: #      if defined(TN3270)
        !          1783:            /*
        !          1784:             * The following is a pain in the rear-end.
        !          1785:             * Various IBM servers (some versions of Wiscnet,
        !          1786:             * possibly Fibronics/Spartacus, and who knows who
        !          1787:             * else) will NOT allow us to send "DO SGA" too early
        !          1788:             * in the setup proceedings.  On the other hand,
        !          1789:             * 4.2 servers (telnetd) won't set SGA correctly.
        !          1790:             * So, we are stuck.  Empirically (but, based on
        !          1791:             * a VERY small sample), the IBM servers don't send
        !          1792:             * out anything about ECHO, so we postpone our sending
        !          1793:             * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
        !          1794:             * DO send).
        !          1795:             */
        !          1796:            {
        !          1797:                if (askedSGA == 0) {
        !          1798:                    askedSGA = 1;
        !          1799:                    if (!hisopts[TELOPT_SGA]) {
        !          1800:                        willoption(TELOPT_SGA, 0);
        !          1801:                    }
        !          1802:                }
        !          1803:            }
        !          1804:                /* Fall through */
        !          1805:        case TELOPT_EOR:
        !          1806:        case TELOPT_BINARY:
        !          1807: #endif /* defined(TN3270) */
        !          1808:        case TELOPT_SGA:
        !          1809:                settimer(modenegotiated);
        !          1810:                hisopts[option] = 1;
        !          1811:                fmt = doopt;
        !          1812:                setconnmode();          /* possibly set new tty mode */
        !          1813:                break;
        !          1814: 
        !          1815:        case TELOPT_TM:
        !          1816:                return;                 /* Never reply to TM will's/wont's */
        !          1817: 
        !          1818:        default:
        !          1819:                fmt = dont;
        !          1820:                break;
        !          1821:        }
        !          1822:        sprintf(nfrontp, fmt, option);
        !          1823:        nfrontp += sizeof (dont) - 2;
        !          1824:        if (reply)
        !          1825:                printoption(">SENT", fmt, option, reply);
        !          1826:        else
        !          1827:                printoption("<SENT", fmt, option, reply);
        !          1828: }
        !          1829: 
        !          1830: static void
        !          1831: wontoption(option, reply)
        !          1832:        int option, reply;
        !          1833: {
        !          1834:        char *fmt;
        !          1835: 
        !          1836:        switch (option) {
        !          1837: 
        !          1838:        case TELOPT_ECHO:
        !          1839:        case TELOPT_SGA:
        !          1840:                settimer(modenegotiated);
        !          1841:                hisopts[option] = 0;
        !          1842:                fmt = dont;
        !          1843:                setconnmode();                  /* Set new tty mode */
        !          1844:                break;
        !          1845: 
        !          1846:        case TELOPT_TM:
        !          1847:                return;         /* Never reply to TM will's/wont's */
        !          1848: 
        !          1849:        default:
        !          1850:                fmt = dont;
        !          1851:                hisopts[option] = 0;
        !          1852:                break;
        !          1853:        }
        !          1854:        sprintf(nfrontp, fmt, option);
        !          1855:        nfrontp += sizeof (doopt) - 2;
        !          1856:        if (reply)
        !          1857:                printoption(">SENT", fmt, option, reply);
        !          1858:        else
        !          1859:                printoption("<SENT", fmt, option, reply);
        !          1860: }
        !          1861: 
        !          1862: static void
        !          1863: dooption(option)
        !          1864:        int option;
        !          1865: {
        !          1866:        char *fmt;
        !          1867: 
        !          1868:        switch (option) {
        !          1869: 
        !          1870:        case TELOPT_TM:
        !          1871:                fmt = will;
        !          1872:                break;
        !          1873: 
        !          1874: #      if defined(TN3270)
        !          1875:        case TELOPT_EOR:
        !          1876:        case TELOPT_BINARY:
        !          1877: #      endif   /* defined(TN3270) */
        !          1878:        case TELOPT_TTYPE:              /* terminal type option */
        !          1879:        case TELOPT_SGA:                /* no big deal */
        !          1880:                fmt = will;
        !          1881:                myopts[option] = 1;
        !          1882:                break;
        !          1883: 
        !          1884:        case TELOPT_ECHO:               /* We're never going to echo... */
        !          1885:        default:
        !          1886:                fmt = wont;
        !          1887:                break;
        !          1888:        }
        !          1889:        sprintf(nfrontp, fmt, option);
        !          1890:        nfrontp += sizeof (doopt) - 2;
        !          1891:        printoption(">SENT", fmt, option, 0);
        !          1892: }
        !          1893: 
        !          1894: /*
        !          1895:  * suboption()
        !          1896:  *
        !          1897:  *     Look at the sub-option buffer, and try to be helpful to the other
        !          1898:  * side.
        !          1899:  *
        !          1900:  *     Currently we recognize:
        !          1901:  *
        !          1902:  *             Terminal type, send request.
        !          1903:  */
        !          1904: 
        !          1905: static void
        !          1906: suboption()
        !          1907: {
        !          1908:     printsub("<", subbuffer, subend-subbuffer+1);
        !          1909:     switch (subbuffer[0]&0xff) {
        !          1910:     case TELOPT_TTYPE:
        !          1911:        if ((subbuffer[1]&0xff) != TELQUAL_SEND) {
        !          1912:            ;
        !          1913:        } else {
        !          1914:            char *name;
        !          1915:            char namebuf[41];
        !          1916:            extern char *getenv();
        !          1917:            int len;
        !          1918: 
        !          1919: #if    defined(TN3270)
        !          1920:            /*
        !          1921:             * Try to send a 3270 type terminal name.  Decide which one based
        !          1922:             * on the format of our screen, and (in the future) color
        !          1923:             * capaiblities.
        !          1924:             */
        !          1925: #if    defined(unix)
        !          1926:            if (initscr() != ERR) {     /* Initialize curses to get line size */
        !          1927:                MaxNumberLines = LINES;
        !          1928:                MaxNumberColumns = COLS;
        !          1929:            }
        !          1930: #else  /* defined(unix) */
        !          1931:            InitTerminal();
        !          1932: #endif /* defined(unix) */
        !          1933:            if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
        !          1934:                Sent3270TerminalType = 1;
        !          1935:                if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
        !          1936:                    MaxNumberLines = 27;
        !          1937:                    MaxNumberColumns = 132;
        !          1938:                    sb_terminal[SBTERMMODEL] = '5';
        !          1939:                } else if (MaxNumberLines >= 43) {
        !          1940:                    MaxNumberLines = 43;
        !          1941:                    MaxNumberColumns = 80;
        !          1942:                    sb_terminal[SBTERMMODEL] = '4';
        !          1943:                } else if (MaxNumberLines >= 32) {
        !          1944:                    MaxNumberLines = 32;
        !          1945:                    MaxNumberColumns = 80;
        !          1946:                    sb_terminal[SBTERMMODEL] = '3';
        !          1947:                } else {
        !          1948:                    MaxNumberLines = 24;
        !          1949:                    MaxNumberColumns = 80;
        !          1950:                    sb_terminal[SBTERMMODEL] = '2';
        !          1951:                }
        !          1952:                NumberLines = 24;               /* before we start out... */
        !          1953:                NumberColumns = 80;
        !          1954:                ScreenSize = NumberLines*NumberColumns;
        !          1955:                if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
        !          1956:                    ExitString(stderr,
        !          1957:                        "Programming error:  MAXSCREENSIZE too small.\n", 1);
        !          1958:                    /*NOTREACHED*/
        !          1959:                }
        !          1960:                memcpy(nfrontp, sb_terminal, sizeof sb_terminal);
        !          1961:                printsub(">", nfrontp+2, sizeof sb_terminal-2);
        !          1962:                nfrontp += sizeof sb_terminal;
        !          1963:                return;
        !          1964:            }
        !          1965: #endif /* defined(TN3270) */
        !          1966: 
        !          1967:            name = getenv("TERM");
        !          1968:            if ((name == 0) || ((len = strlen(name)) > 40)) {
        !          1969:                name = "UNKNOWN";
        !          1970:            }
        !          1971:            if ((len + 4+2) < NETROOM()) {
        !          1972:                strcpy(namebuf, name);
        !          1973:                upcase(namebuf);
        !          1974:                sprintf(nfrontp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
        !          1975:                                    TELQUAL_IS, namebuf, IAC, SE);
        !          1976:                printsub(">", nfrontp+2, 4+strlen(namebuf)+2-2-2);
        !          1977:                nfrontp += 4+strlen(namebuf)+2;
        !          1978:            } else {
        !          1979:                ExitString(stderr, "No room in buffer for terminal type.\n",
        !          1980:                                                        1);
        !          1981:                /*NOTREACHED*/
        !          1982:            }
        !          1983:        }
        !          1984: 
        !          1985:     default:
        !          1986:        break;
        !          1987:     }
        !          1988: }
        !          1989: 
        !          1990: #if    defined(TN3270)
        !          1991: static void
        !          1992: SetIn3270()
        !          1993: {
        !          1994:     if (Sent3270TerminalType && myopts[TELOPT_BINARY]
        !          1995:                            && hisopts[TELOPT_BINARY] && !donebinarytoggle) {
        !          1996:        if (!In3270) {
        !          1997:            In3270 = 1;
        !          1998:            Init3270();         /* Initialize 3270 functions */
        !          1999:            /* initialize terminal key mapping */
        !          2000:            InitTerminal();     /* Start terminal going */
        !          2001:            LocalClearScreen(); /* Make sure the screen is clear */
        !          2002:            setconnmode();
        !          2003:        }
        !          2004:     } else {
        !          2005:        if (In3270) {
        !          2006:            StopScreen(1);
        !          2007:            In3270 = 0;
        !          2008:            Stop3270();         /* Tell 3270 we aren't here anymore */
        !          2009:            setconnmode();
        !          2010:        }
        !          2011:     }
        !          2012: }
        !          2013: #endif /* defined(TN3270) */
        !          2014: 
        !          2015: 
        !          2016: static void
        !          2017: telrcv()
        !          2018: {
        !          2019:     register int c;
        !          2020:     static int telrcv_state = TS_DATA;
        !          2021: #   if defined(TN3270)
        !          2022:     register int Scc;
        !          2023:     register char *Sbp;
        !          2024: #   endif /* defined(TN3270) */
        !          2025: 
        !          2026:     while ((scc > 0) && (TTYROOM() > 2)) {
        !          2027:        c = *sbp++ & 0xff, scc--;
        !          2028:        switch (telrcv_state) {
        !          2029: 
        !          2030:        case TS_CR:
        !          2031:            telrcv_state = TS_DATA;
        !          2032:            if (c == '\0') {
        !          2033:                break;  /* Ignore \0 after CR */
        !          2034:            } else if (c == '\n') {
        !          2035:                if (hisopts[TELOPT_ECHO] && !crmod) {
        !          2036:                    TTYADD(c);
        !          2037:                }
        !          2038:                break;
        !          2039:            }
        !          2040:            /* Else, fall through */
        !          2041: 
        !          2042:        case TS_DATA:
        !          2043:            if (c == IAC) {
        !          2044:                telrcv_state = TS_IAC;
        !          2045:                continue;
        !          2046:            }
        !          2047: #          if defined(TN3270)
        !          2048:            if (In3270) {
        !          2049:                *Ifrontp++ = c;
        !          2050:                Sbp = sbp;
        !          2051:                Scc = scc;
        !          2052:                while (Scc > 0) {
        !          2053:                    c = *Sbp++ & 0377, Scc--;
        !          2054:                    if (c == IAC) {
        !          2055:                        telrcv_state = TS_IAC;
        !          2056:                        break;
        !          2057:                    }
        !          2058:                    *Ifrontp++ = c;
        !          2059:                }
        !          2060:                sbp = Sbp;
        !          2061:                scc = Scc;
        !          2062:            } else
        !          2063: #          endif /* defined(TN3270) */
        !          2064:                    /*
        !          2065:                     * The 'crmod' hack (see following) is needed
        !          2066:                     * since we can't * set CRMOD on output only.
        !          2067:                     * Machines like MULTICS like to send \r without
        !          2068:                     * \n; since we must turn off CRMOD to get proper
        !          2069:                     * input, the mapping is done here (sigh).
        !          2070:                     */
        !          2071:            if ((c == '\r') && !hisopts[TELOPT_BINARY]) {
        !          2072:                if (scc > 0) {
        !          2073:                    c = *sbp&0xff;
        !          2074:                    if (c == 0) {
        !          2075:                        sbp++, scc--;
        !          2076:                        /* a "true" CR */
        !          2077:                        TTYADD('\r');
        !          2078:                    } else if (!hisopts[TELOPT_ECHO] &&
        !          2079:                                        (c == '\n')) {
        !          2080:                        sbp++, scc--;
        !          2081:                        TTYADD('\n');
        !          2082:                    } else {
        !          2083:                        TTYADD('\r');
        !          2084:                        if (crmod) {
        !          2085:                                TTYADD('\n');
        !          2086:                        }
        !          2087:                    }
        !          2088:                } else {
        !          2089:                    telrcv_state = TS_CR;
        !          2090:                    TTYADD('\r');
        !          2091:                    if (crmod) {
        !          2092:                            TTYADD('\n');
        !          2093:                    }
        !          2094:                }
        !          2095:            } else {
        !          2096:                TTYADD(c);
        !          2097:            }
        !          2098:            continue;
        !          2099: 
        !          2100:        case TS_IAC:
        !          2101:            switch (c) {
        !          2102:            
        !          2103:            case WILL:
        !          2104:                telrcv_state = TS_WILL;
        !          2105:                continue;
        !          2106: 
        !          2107:            case WONT:
        !          2108:                telrcv_state = TS_WONT;
        !          2109:                continue;
        !          2110: 
        !          2111:            case DO:
        !          2112:                telrcv_state = TS_DO;
        !          2113:                continue;
        !          2114: 
        !          2115:            case DONT:
        !          2116:                telrcv_state = TS_DONT;
        !          2117:                continue;
        !          2118: 
        !          2119:            case DM:
        !          2120:                    /*
        !          2121:                     * We may have missed an urgent notification,
        !          2122:                     * so make sure we flush whatever is in the
        !          2123:                     * buffer currently.
        !          2124:                     */
        !          2125:                SYNCHing = 1;
        !          2126:                ttyflush();
        !          2127:                SYNCHing = stilloob(net);
        !          2128:                settimer(gotDM);
        !          2129:                break;
        !          2130: 
        !          2131:            case NOP:
        !          2132:            case GA:
        !          2133:                break;
        !          2134: 
        !          2135:            case SB:
        !          2136:                SB_CLEAR();
        !          2137:                telrcv_state = TS_SB;
        !          2138:                continue;
        !          2139: 
        !          2140: #          if defined(TN3270)
        !          2141:            case EOR:
        !          2142:                if (In3270) {
        !          2143:                    Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
        !          2144:                    if (Ibackp == Ifrontp) {
        !          2145:                        Ibackp = Ifrontp = Ibuf;
        !          2146:                        ISend = 0;      /* should have been! */
        !          2147:                    } else {
        !          2148:                        ISend = 1;
        !          2149:                    }
        !          2150:                }
        !          2151:                break;
        !          2152: #          endif /* defined(TN3270) */
        !          2153: 
        !          2154:            case IAC:
        !          2155: #          if !defined(TN3270)
        !          2156:                TTYADD(IAC);
        !          2157: #          else /* !defined(TN3270) */
        !          2158:                if (In3270) {
        !          2159:                    *Ifrontp++ = IAC;
        !          2160:                } else {
        !          2161:                    TTYADD(IAC);
        !          2162:                }
        !          2163: #          endif /* !defined(TN3270) */
        !          2164:                break;
        !          2165: 
        !          2166:            default:
        !          2167:                break;
        !          2168:            }
        !          2169:            telrcv_state = TS_DATA;
        !          2170:            continue;
        !          2171: 
        !          2172:        case TS_WILL:
        !          2173:            printoption(">RCVD", will, c, !hisopts[c]);
        !          2174:            if (c == TELOPT_TM) {
        !          2175:                if (flushout) {
        !          2176:                    flushout = 0;
        !          2177:                }
        !          2178:            } else if (!hisopts[c]) {
        !          2179:                willoption(c, 1);
        !          2180:            }
        !          2181:            SetIn3270();
        !          2182:            telrcv_state = TS_DATA;
        !          2183:            continue;
        !          2184: 
        !          2185:        case TS_WONT:
        !          2186:            printoption(">RCVD", wont, c, hisopts[c]);
        !          2187:            if (c == TELOPT_TM) {
        !          2188:                if (flushout) {
        !          2189:                    flushout = 0;
        !          2190:                }
        !          2191:            } else if (hisopts[c]) {
        !          2192:                wontoption(c, 1);
        !          2193:            }
        !          2194:            SetIn3270();
        !          2195:            telrcv_state = TS_DATA;
        !          2196:            continue;
        !          2197: 
        !          2198:        case TS_DO:
        !          2199:            printoption(">RCVD", doopt, c, !myopts[c]);
        !          2200:            if (!myopts[c])
        !          2201:                dooption(c);
        !          2202:            SetIn3270();
        !          2203:            telrcv_state = TS_DATA;
        !          2204:            continue;
        !          2205: 
        !          2206:        case TS_DONT:
        !          2207:            printoption(">RCVD", dont, c, myopts[c]);
        !          2208:            if (myopts[c]) {
        !          2209:                myopts[c] = 0;
        !          2210:                sprintf(nfrontp, wont, c);
        !          2211:                nfrontp += sizeof (wont) - 2;
        !          2212:                flushline = 1;
        !          2213:                setconnmode();  /* set new tty mode (maybe) */
        !          2214:                printoption(">SENT", wont, c, 0);
        !          2215:            }
        !          2216:            SetIn3270();
        !          2217:            telrcv_state = TS_DATA;
        !          2218:            continue;
        !          2219: 
        !          2220:        case TS_SB:
        !          2221:            if (c == IAC) {
        !          2222:                telrcv_state = TS_SE;
        !          2223:            } else {
        !          2224:                SB_ACCUM(c);
        !          2225:            }
        !          2226:            continue;
        !          2227: 
        !          2228:        case TS_SE:
        !          2229:            if (c != SE) {
        !          2230:                if (c != IAC) {
        !          2231:                    SB_ACCUM(IAC);
        !          2232:                }
        !          2233:                SB_ACCUM(c);
        !          2234:                telrcv_state = TS_SB;
        !          2235:            } else {
        !          2236:                SB_TERM();
        !          2237:                suboption();    /* handle sub-option */
        !          2238:                SetIn3270();
        !          2239:                telrcv_state = TS_DATA;
        !          2240:            }
        !          2241:        }
        !          2242:     }
        !          2243: }
        !          2244: 
        !          2245: #if    defined(TN3270)
        !          2246: 
        !          2247: /*
        !          2248:  * The following routines are places where the various tn3270
        !          2249:  * routines make calls into telnet.c.
        !          2250:  */
        !          2251: 
        !          2252: /* TtyChars() - returns the number of characters in the TTY buffer */
        !          2253: TtyChars()
        !          2254: {
        !          2255:     return(tfrontp-tbackp);
        !          2256: }
        !          2257: 
        !          2258: /*
        !          2259:  * DataToNetwork - queue up some data to go to network.  If "done" is set,
        !          2260:  * then when last byte is queued, we add on an IAC EOR sequence (so,
        !          2261:  * don't call us with "done" until you want that done...)
        !          2262:  *
        !          2263:  * We actually do send all the data to the network buffer, since our
        !          2264:  * only client needs for us to do that.
        !          2265:  */
        !          2266: 
        !          2267: int
        !          2268: DataToNetwork(buffer, count, done)
        !          2269: register char  *buffer;        /* where the data is */
        !          2270: register int   count;          /* how much to send */
        !          2271: int            done;           /* is this the last of a logical block */
        !          2272: {
        !          2273:     register int c;
        !          2274:     int origCount;
        !          2275:     fd_set o;
        !          2276: 
        !          2277:     origCount = count;
        !          2278:     FD_ZERO(&o);
        !          2279: 
        !          2280:     while (count) {
        !          2281:        if ((netobuf+sizeof netobuf - nfrontp) < 6) {
        !          2282:            netflush();
        !          2283:            while ((netobuf+sizeof netobuf - nfrontp) < 6) {
        !          2284:                FD_SET(net, &o);
        !          2285:                (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
        !          2286:                                                (struct timeval *) 0);
        !          2287:                netflush();
        !          2288:            }
        !          2289:        }
        !          2290:        c = *buffer++;
        !          2291:        count--;
        !          2292:        if (c == IAC) {
        !          2293:            *nfrontp++ = IAC;
        !          2294:            *nfrontp++ = IAC;
        !          2295:        } else {
        !          2296:            *nfrontp++ = c;
        !          2297:        }
        !          2298:     }
        !          2299: 
        !          2300:     if (done && !count) {
        !          2301:        *nfrontp++ = IAC;
        !          2302:        *nfrontp++ = EOR;
        !          2303:        netflush();             /* try to move along as quickly as ... */
        !          2304:     }
        !          2305:     return(origCount - count);
        !          2306: }
        !          2307: 
        !          2308: /* DataToTerminal - queue up some data to go to terminal. */
        !          2309: 
        !          2310: int
        !          2311: DataToTerminal(buffer, count)
        !          2312: register char  *buffer;                /* where the data is */
        !          2313: register int   count;                  /* how much to send */
        !          2314: {
        !          2315:     int origCount;
        !          2316: #if    defined(unix)
        !          2317:     fd_set     o;
        !          2318: 
        !          2319:     FD_ZERO(&o);
        !          2320: #endif /* defined(unix) */
        !          2321:     origCount = count;
        !          2322: 
        !          2323:     while (count) {
        !          2324:        if (tfrontp >= ttyobuf+sizeof ttyobuf) {
        !          2325:            ttyflush();
        !          2326:            while (tfrontp >= ttyobuf+sizeof ttyobuf) {
        !          2327: #if    defined(unix)
        !          2328:                FD_SET(tout, &o);
        !          2329:                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
        !          2330:                                                (struct timeval *) 0);
        !          2331: #endif /* defined(unix) */
        !          2332:                ttyflush();
        !          2333:            }
        !          2334:        }
        !          2335:        *tfrontp++ = *buffer++;
        !          2336:        count--;
        !          2337:     }
        !          2338:     return(origCount - count);
        !          2339: }
        !          2340: 
        !          2341: /* EmptyTerminal - called to make sure that the terminal buffer is empty.
        !          2342:  *                     Note that we consider the buffer to run all the
        !          2343:  *                     way to the kernel (thus the select).
        !          2344:  */
        !          2345: 
        !          2346: void
        !          2347: EmptyTerminal()
        !          2348: {
        !          2349: #if    defined(unix)
        !          2350:     fd_set     o;
        !          2351: 
        !          2352:     FD_ZERO(&o);
        !          2353: #endif /* defined(unix) */
        !          2354: 
        !          2355:     if (tfrontp == tbackp) {
        !          2356: #if    defined(unix)
        !          2357:        FD_SET(tout, &o);
        !          2358:        (void) select(tout+1, (int *) 0, &o, (int *) 0,
        !          2359:                        (struct timeval *) 0);  /* wait for TTLOWAT */
        !          2360: #endif /* defined(unix) */
        !          2361:     } else {
        !          2362:        while (tfrontp != tbackp) {
        !          2363:            ttyflush();
        !          2364: #if    defined(unix)
        !          2365:            FD_SET(tout, &o);
        !          2366:            (void) select(tout+1, (int *) 0, &o, (int *) 0,
        !          2367:                                (struct timeval *) 0);  /* wait for TTLOWAT */
        !          2368: #endif /* defined(unix) */
        !          2369:        }
        !          2370:     }
        !          2371: }
        !          2372: 
        !          2373: /*
        !          2374:  * Push3270 - Try to send data along the 3270 output (to screen) direction.
        !          2375:  */
        !          2376: 
        !          2377: static int
        !          2378: Push3270()
        !          2379: {
        !          2380:     int save = scc;
        !          2381: 
        !          2382:     if (scc) {
        !          2383:        if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
        !          2384:            if (Ibackp != Ibuf) {
        !          2385:                memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
        !          2386:                Ifrontp -= (Ibackp-Ibuf);
        !          2387:                Ibackp = Ibuf;
        !          2388:            }
        !          2389:        }
        !          2390:        if (Ifrontp+scc < Ibuf+sizeof Ibuf) {
        !          2391:            telrcv();
        !          2392:        }
        !          2393:     }
        !          2394:     return save != scc;
        !          2395: }
        !          2396: 
        !          2397: 
        !          2398: /*
        !          2399:  * Finish3270 - get the last dregs of 3270 data out to the terminal
        !          2400:  *             before quitting.
        !          2401:  */
        !          2402: 
        !          2403: static void
        !          2404: Finish3270()
        !          2405: {
        !          2406:     while (Push3270() || !DoTerminalOutput()) {
        !          2407: #if    defined(unix)
        !          2408:        HaveInput = 0;
        !          2409: #endif /* defined(unix) */
        !          2410:        ;
        !          2411:     }
        !          2412: }
        !          2413: 
        !          2414: 
        !          2415: 
        !          2416: /* StringToTerminal - output a null terminated string to the terminal */
        !          2417: 
        !          2418: void
        !          2419: StringToTerminal(s)
        !          2420: char *s;
        !          2421: {
        !          2422:     int count;
        !          2423: 
        !          2424:     count = strlen(s);
        !          2425:     if (count) {
        !          2426:        (void) DataToTerminal(s, count);        /* we know it always goes... */
        !          2427:     }
        !          2428: }
        !          2429: 
        !          2430: 
        !          2431: #if    defined(TN3270) && ((!defined(NOT43)) || defined(PUTCHAR))
        !          2432: /* _putchar - output a single character to the terminal.  This name is so that
        !          2433:  *     curses(3x) can call us to send out data.
        !          2434:  */
        !          2435: 
        !          2436: void
        !          2437: _putchar(c)
        !          2438: char c;
        !          2439: {
        !          2440:     if (tfrontp >= ttyobuf+sizeof ttyobuf) {
        !          2441:        (void) DataToTerminal(&c, 1);
        !          2442:     } else {
        !          2443:        *tfrontp++ = c;         /* optimize if possible. */
        !          2444:     }
        !          2445: }
        !          2446: #endif /* defined(TN3270) && ((!defined(NOT43)) || defined(PUTCHAR)) */
        !          2447: 
        !          2448: static void
        !          2449: SetForExit()
        !          2450: {
        !          2451:     setconnmode();
        !          2452:     if (In3270) {
        !          2453:        Finish3270();
        !          2454:     }
        !          2455:     setcommandmode();
        !          2456:     fflush(stdout);
        !          2457:     fflush(stderr);
        !          2458:     if (In3270) {
        !          2459:        StopScreen(1);
        !          2460:     }
        !          2461:     setconnmode();
        !          2462:     setcommandmode();
        !          2463: }
        !          2464: 
        !          2465: static void
        !          2466: Exit(returnCode)
        !          2467: int returnCode;
        !          2468: {
        !          2469:     SetForExit();
        !          2470:     exit(returnCode);
        !          2471: }
        !          2472: 
        !          2473: void
        !          2474: ExitString(file, string, returnCode)
        !          2475: FILE *file;
        !          2476: char *string;
        !          2477: int returnCode;
        !          2478: {
        !          2479:     SetForExit();
        !          2480:     fwrite(string, 1, strlen(string), file);
        !          2481:     exit(returnCode);
        !          2482: }
        !          2483: 
        !          2484: void
        !          2485: ExitPerror(string, returnCode)
        !          2486: char *string;
        !          2487: int returnCode;
        !          2488: {
        !          2489:     SetForExit();
        !          2490:     perror(string);
        !          2491:     exit(returnCode);
        !          2492: }
        !          2493: 
        !          2494: #endif /* defined(TN3270) */
        !          2495: 
        !          2496: /*
        !          2497:  * Scheduler()
        !          2498:  *
        !          2499:  * Try to do something.
        !          2500:  *
        !          2501:  * If we do something useful, return 1; else return 0.
        !          2502:  *
        !          2503:  */
        !          2504: 
        !          2505: 
        !          2506: int
        !          2507: Scheduler(block)
        !          2508: int    block;                  /* should we block in the select ? */
        !          2509: {
        !          2510:     register int c;
        !          2511:                /* One wants to be a bit careful about setting returnValue
        !          2512:                 * to one, since a one implies we did some useful work,
        !          2513:                 * and therefore probably won't be called to block next
        !          2514:                 * time (TN3270 mode only).
        !          2515:                 */
        !          2516:     int returnValue = 0;
        !          2517:     static struct timeval TimeValue = { 0 };
        !          2518: 
        !          2519:     if (scc < 0 && tcc < 0) {
        !          2520:        return -1;
        !          2521:     }
        !          2522: 
        !          2523:     if ((!MODE_LINE(globalmode) || flushline) && NETBYTES()) {
        !          2524:        FD_SET(net, &obits);
        !          2525:     } 
        !          2526: #if    !defined(MSDOS)
        !          2527:     if (TTYBYTES()) {
        !          2528:        FD_SET(tout, &obits);
        !          2529:     }
        !          2530: #if    defined(TN3270)
        !          2531:     if ((tcc == 0) && NETROOM() && (shell_active == 0)) {
        !          2532:        FD_SET(tin, &ibits);
        !          2533:     }
        !          2534: #else  /* defined(TN3270) */
        !          2535:     if ((tcc == 0) && NETROOM()) {
        !          2536:        FD_SET(tin, &ibits);
        !          2537:     }
        !          2538: #endif /* defined(TN3270) */
        !          2539: #endif /* !defined(MSDOS) */
        !          2540: #   if !defined(TN3270)
        !          2541:     if (TTYROOM()) {
        !          2542:        FD_SET(net, &ibits);
        !          2543:     }
        !          2544: #   else /* !defined(TN3270) */
        !          2545:     if (!ISend && TTYROOM()) {
        !          2546:        FD_SET(net, &ibits);
        !          2547:     }
        !          2548: #   endif /* !defined(TN3270) */
        !          2549:     if (!SYNCHing) {
        !          2550:        FD_SET(net, &xbits);
        !          2551:     }
        !          2552: #   if defined(TN3270) && defined(unix)
        !          2553:     if (HaveInput) {
        !          2554:        HaveInput = 0;
        !          2555:        signal(SIGIO, inputAvailable);
        !          2556:     }
        !          2557: #endif /* defined(TN3270) && defined(unix) */
        !          2558:     if ((c = select(16, &ibits, &obits, &xbits,
        !          2559:                        block? (struct timeval *)0 : &TimeValue)) < 0) {
        !          2560:        if (c == -1) {
        !          2561:                    /*
        !          2562:                     * we can get EINTR if we are in line mode,
        !          2563:                     * and the user does an escape (TSTP), or
        !          2564:                     * some other signal generator.
        !          2565:                     */
        !          2566:            if (errno == EINTR) {
        !          2567:                return 0;
        !          2568:            }
        !          2569: #          if defined(TN3270)
        !          2570:                    /*
        !          2571:                     * we can get EBADF if we were in transparent
        !          2572:                     * mode, and the transcom process died.
        !          2573:                    */
        !          2574:            if (errno == EBADF) {
        !          2575:                        /*
        !          2576:                         * zero the bits (even though kernel does it)
        !          2577:                         * to make sure we are selecting on the right
        !          2578:                         * ones.
        !          2579:                        */
        !          2580:                FD_ZERO(&ibits);
        !          2581:                FD_ZERO(&obits);
        !          2582:                FD_ZERO(&xbits);
        !          2583:                return 0;
        !          2584:            }
        !          2585: #          endif /* defined(TN3270) */
        !          2586:                    /* I don't like this, does it ever happen? */
        !          2587:            printf("sleep(5) from telnet, after select\r\n");
        !          2588: #if    defined(unix)
        !          2589:            sleep(5);
        !          2590: #endif /* defined(unix) */
        !          2591:        }
        !          2592:        return 0;
        !          2593:     }
        !          2594: 
        !          2595:     /*
        !          2596:      * Any urgent data?
        !          2597:      */
        !          2598:     if (FD_ISSET(net, &xbits)) {
        !          2599:        FD_CLR(net, &xbits);
        !          2600:        SYNCHing = 1;
        !          2601:        ttyflush();     /* flush already enqueued data */
        !          2602:     }
        !          2603: 
        !          2604:     /*
        !          2605:      * Something to read from the network...
        !          2606:      */
        !          2607:     if (FD_ISSET(net, &ibits)) {
        !          2608:        int canread;
        !          2609: 
        !          2610:        FD_CLR(net, &ibits);
        !          2611:        if (scc == 0) {
        !          2612:            sbp = sibuf;
        !          2613:        }
        !          2614:        canread = sibuf + sizeof sibuf - (sbp+scc);
        !          2615: #if    !defined(SO_OOBINLINE)
        !          2616:            /*
        !          2617:             * In 4.2 (and some early 4.3) systems, the
        !          2618:             * OOB indication and data handling in the kernel
        !          2619:             * is such that if two separate TCP Urgent requests
        !          2620:             * come in, one byte of TCP data will be overlaid.
        !          2621:             * This is fatal for Telnet, but we try to live
        !          2622:             * with it.
        !          2623:             *
        !          2624:             * In addition, in 4.2 (and...), a special protocol
        !          2625:             * is needed to pick up the TCP Urgent data in
        !          2626:             * the correct sequence.
        !          2627:             *
        !          2628:             * What we do is:  if we think we are in urgent
        !          2629:             * mode, we look to see if we are "at the mark".
        !          2630:             * If we are, we do an OOB receive.  If we run
        !          2631:             * this twice, we will do the OOB receive twice,
        !          2632:             * but the second will fail, since the second
        !          2633:             * time we were "at the mark", but there wasn't
        !          2634:             * any data there (the kernel doesn't reset
        !          2635:             * "at the mark" until we do a normal read).
        !          2636:             * Once we've read the OOB data, we go ahead
        !          2637:             * and do normal reads.
        !          2638:             *
        !          2639:             * There is also another problem, which is that
        !          2640:             * since the OOB byte we read doesn't put us
        !          2641:             * out of OOB state, and since that byte is most
        !          2642:             * likely the TELNET DM (data mark), we would
        !          2643:             * stay in the TELNET SYNCH (SYNCHing) state.
        !          2644:             * So, clocks to the rescue.  If we've "just"
        !          2645:             * received a DM, then we test for the
        !          2646:             * presence of OOB data when the receive OOB
        !          2647:             * fails (and AFTER we did the normal mode read
        !          2648:             * to clear "at the mark").
        !          2649:             */
        !          2650:        if (SYNCHing) {
        !          2651:            int atmark;
        !          2652: 
        !          2653:            ioctl(net, SIOCATMARK, (char *)&atmark);
        !          2654:            if (atmark) {
        !          2655:                c = recv(net, sbp+scc, canread, MSG_OOB);
        !          2656:                if ((c == -1) && (errno == EINVAL)) {
        !          2657:                    c = recv(net, sbp+scc, canread, 0);
        !          2658:                    if (clocks.didnetreceive < clocks.gotDM) {
        !          2659:                        SYNCHing = stilloob(net);
        !          2660:                    }
        !          2661:                }
        !          2662:            } else {
        !          2663:                c = recv(net, sbp+scc, canread, 0);
        !          2664:            }
        !          2665:        } else {
        !          2666:            c = recv(net, sbp+scc, canread, 0);
        !          2667:        }
        !          2668:        settimer(didnetreceive);
        !          2669: #else  /* !defined(SO_OOBINLINE) */
        !          2670:        c = recv(net, sbp+scc, canread, 0);
        !          2671: #endif /* !defined(SO_OOBINLINE) */
        !          2672:        if (c < 0 && errno == EWOULDBLOCK) {
        !          2673:            c = 0;
        !          2674:        } else if (c <= 0) {
        !          2675:            return -1;
        !          2676:        }
        !          2677:        if (netdata) {
        !          2678:            Dump('<', sbp+scc, c);
        !          2679:        }
        !          2680:        scc += c;
        !          2681:        returnValue = 1;
        !          2682:     }
        !          2683: 
        !          2684:     /*
        !          2685:      * Something to read from the tty...
        !          2686:      */
        !          2687: #if    defined(MSDOS)
        !          2688:     if ((tcc == 0) && NETROOM() && (shell_active == 0) && TerminalCanRead())
        !          2689: #else  /* defined(MSDOS) */
        !          2690:     if (FD_ISSET(tin, &ibits))
        !          2691: #endif /* defined(MSDOS) */
        !          2692:                                    {
        !          2693:        FD_CLR(tin, &ibits);
        !          2694:        if (tcc == 0) {
        !          2695:            tbp = tibuf;        /* nothing left, reset */
        !          2696:        }
        !          2697:        c = TerminalRead(tin, tbp, tibuf+sizeof tibuf - tbp);
        !          2698:        if (c < 0 && errno == EWOULDBLOCK) {
        !          2699:            c = 0;
        !          2700:        } else {
        !          2701: #if    defined(unix)
        !          2702:            /* EOF detection for line mode!!!! */
        !          2703:            if (c == 0 && MODE_LOCAL_CHARS(globalmode)) {
        !          2704:                        /* must be an EOF... */
        !          2705:                *tbp = ntc.t_eofc;
        !          2706:                c = 1;
        !          2707:            }
        !          2708: #endif /* defined(unix) */
        !          2709:            if (c <= 0) {
        !          2710:                tcc = c;
        !          2711:                return -1;
        !          2712:            }
        !          2713:        }
        !          2714:        tcc += c;
        !          2715:        returnValue = 1;                /* did something useful */
        !          2716:     }
        !          2717: 
        !          2718: #   if defined(TN3270)
        !          2719:     if (tcc > 0) {
        !          2720:        if (In3270) {
        !          2721:            c = DataFromTerminal(tbp, tcc);
        !          2722:            if (c) {
        !          2723:                returnValue = 1;
        !          2724:            }
        !          2725:            tcc -= c;
        !          2726:            tbp += c;
        !          2727:        } else {
        !          2728: #   endif /* defined(TN3270) */
        !          2729:            returnValue = 1;
        !          2730:            while (tcc > 0) {
        !          2731:                register int sc;
        !          2732: 
        !          2733:                if (NETROOM() < 2) {
        !          2734:                    flushline = 1;
        !          2735:                    break;
        !          2736:                }
        !          2737:                c = *tbp++ & 0xff, sc = strip(c), tcc--;
        !          2738:                if (sc == escape) {
        !          2739:                    command(0);
        !          2740:                    tcc = 0;
        !          2741:                    flushline = 1;
        !          2742:                    break;
        !          2743:                } else if (MODE_LINE(globalmode) && (sc == echoc)) {
        !          2744:                    if (tcc > 0 && strip(*tbp) == echoc) {
        !          2745:                        tbp++;
        !          2746:                        tcc--;
        !          2747:                    } else {
        !          2748:                        dontlecho = !dontlecho;
        !          2749:                        settimer(echotoggle);
        !          2750:                        setconnmode();
        !          2751:                        tcc = 0;
        !          2752:                        flushline = 1;
        !          2753:                        break;
        !          2754:                    }
        !          2755:                }
        !          2756:                if (localchars) {
        !          2757:                    if (TerminalSpecialChars(sc) == 0) {
        !          2758:                        break;
        !          2759:                    }
        !          2760:                }
        !          2761:                if (!myopts[TELOPT_BINARY]) {
        !          2762:                    switch (c) {
        !          2763:                    case '\n':
        !          2764:                            /*
        !          2765:                             * If we are in CRMOD mode (\r ==> \n)
        !          2766:                             * on our local machine, then probably
        !          2767:                             * a newline (unix) is CRLF (TELNET).
        !          2768:                             */
        !          2769:                        if (MODE_LOCAL_CHARS(globalmode)) {
        !          2770:                            NETADD('\r');
        !          2771:                        }
        !          2772:                        NETADD('\n');
        !          2773:                        flushline = 1;
        !          2774:                        break;
        !          2775:                    case '\r':
        !          2776:                        if (!crlf) {
        !          2777:                            NET2ADD('\r', '\0');
        !          2778:                        } else {
        !          2779:                            NET2ADD('\r', '\n');
        !          2780:                        }
        !          2781:                        flushline = 1;
        !          2782:                        break;
        !          2783:                    case IAC:
        !          2784:                        NET2ADD(IAC, IAC);
        !          2785:                        break;
        !          2786:                    default:
        !          2787:                        NETADD(c);
        !          2788:                        break;
        !          2789:                    }
        !          2790:                } else if (c == IAC) {
        !          2791:                    NET2ADD(IAC, IAC);
        !          2792:                } else {
        !          2793:                    NETADD(c);
        !          2794:                }
        !          2795:            }
        !          2796: #   if defined(TN3270)
        !          2797:        }
        !          2798:     }
        !          2799: #   endif /* defined(TN3270) */
        !          2800: 
        !          2801:     if ((!MODE_LINE(globalmode) || flushline || myopts[TELOPT_BINARY]) &&
        !          2802:        FD_ISSET(net, &obits) && (NETBYTES() > 0)) {
        !          2803:        FD_CLR(net, &obits);
        !          2804:        returnValue = netflush();
        !          2805:     }
        !          2806:     if (scc > 0) {
        !          2807: #      if !defined(TN3270)
        !          2808:        telrcv();
        !          2809:        returnValue = 1;
        !          2810: #      else /* !defined(TN3270) */
        !          2811:        returnValue = Push3270();
        !          2812: #      endif /* !defined(TN3270) */
        !          2813:     }
        !          2814: #if    defined(MSDOS)
        !          2815:     if (TTYBYTES())
        !          2816: #else  /* defined(MSDOS) */
        !          2817:     if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0))
        !          2818: #endif /* defined(MSDOS) */
        !          2819:                                                    {
        !          2820:        FD_CLR(tout, &obits);
        !          2821:        returnValue = ttyflush();
        !          2822:     }
        !          2823:     return returnValue;
        !          2824: }
        !          2825: 
        !          2826: /*
        !          2827:  * Select from tty and network...
        !          2828:  */
        !          2829: static void
        !          2830: telnet()
        !          2831: {
        !          2832: #if    defined(MSDOS)
        !          2833: #define        SCHED_BLOCK     0               /* Don't block in MSDOS */
        !          2834: #else  /* defined(MSDOS) */
        !          2835: #define        SCHED_BLOCK     1
        !          2836: #endif /* defined(MSDOS) */
        !          2837: 
        !          2838: #if    defined(TN3270) && defined(unix)
        !          2839:     int myPid;
        !          2840: #endif /* defined(TN3270) */
        !          2841: 
        !          2842:     tout = fileno(stdout);
        !          2843:     tin = fileno(stdin);
        !          2844:     setconnmode();
        !          2845:     scc = 0;
        !          2846:     tcc = 0;
        !          2847:     FD_ZERO(&ibits);
        !          2848:     FD_ZERO(&obits);
        !          2849:     FD_ZERO(&xbits);
        !          2850: 
        !          2851:     NetNonblockingIO(net, 1);
        !          2852: 
        !          2853: #if    defined(TN3270)
        !          2854:     if (noasynch == 0) {                       /* DBX can't handle! */
        !          2855:        NetSigIO(net, 1);
        !          2856:     }
        !          2857:     NetSetPgrp(net);
        !          2858: #endif /* defined(TN3270) */
        !          2859: 
        !          2860: 
        !          2861: #if    defined(SO_OOBINLINE) && !defined(MSDOS)
        !          2862:     SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1);
        !          2863: #endif /* defined(SO_OOBINLINE) && !defined(MSDOS) */
        !          2864: 
        !          2865: #   if !defined(TN3270)
        !          2866:     if (telnetport) {
        !          2867:        if (!hisopts[TELOPT_SGA]) {
        !          2868:            willoption(TELOPT_SGA, 0);
        !          2869:        }
        !          2870:        if (!myopts[TELOPT_TTYPE]) {
        !          2871:            dooption(TELOPT_TTYPE, 0);
        !          2872:        }
        !          2873:     }
        !          2874: #   endif /* !defined(TN3270) */
        !          2875: 
        !          2876: #   if !defined(TN3270)
        !          2877:     for (;;) {
        !          2878:        if (Scheduler(SCHED_BLOCK) == -1) {
        !          2879:            setcommandmode();
        !          2880:            return;
        !          2881:        }
        !          2882:     }
        !          2883: #   else /* !defined(TN3270) */
        !          2884:     for (;;) {
        !          2885:        int schedValue;
        !          2886: 
        !          2887:        while (!In3270 && !shell_active) {
        !          2888:            if (Scheduler(SCHED_BLOCK) == -1) {
        !          2889:                setcommandmode();
        !          2890:                return;
        !          2891:            }
        !          2892:        }
        !          2893: 
        !          2894:        while ((schedValue = Scheduler(0)) != 0) {
        !          2895:            if (schedValue == -1) {
        !          2896:                setcommandmode();
        !          2897:                return;
        !          2898:            }
        !          2899:        }
        !          2900:                /* If there is data waiting to go out to terminal, don't
        !          2901:                 * schedule any more data for the terminal.
        !          2902:                 */
        !          2903:        if (tfrontp-tbackp) {
        !          2904:            schedValue = 1;
        !          2905:        } else {
        !          2906:            if (shell_active) {
        !          2907:                if (shell_continue() == 0) {
        !          2908:                    ConnectScreen();
        !          2909:                }
        !          2910:            } else if (In3270) {
        !          2911:                schedValue = DoTerminalOutput();
        !          2912:            }
        !          2913:        }
        !          2914:        if (schedValue && (shell_active == 0)) {
        !          2915:            if (Scheduler(SCHED_BLOCK) == -1) {
        !          2916:                setcommandmode();
        !          2917:                return;
        !          2918:            }
        !          2919:        }
        !          2920:     }
        !          2921: #   endif /* !defined(TN3270) */
        !          2922: }
        !          2923: 
        !          2924: /*
        !          2925:  *     The following are data structures and routines for
        !          2926:  *     the "send" command.
        !          2927:  *
        !          2928:  */
        !          2929:  
        !          2930: struct sendlist {
        !          2931:     char       *name;          /* How user refers to it (case independent) */
        !          2932:     int                what;           /* Character to be sent (<0 ==> special) */
        !          2933:     char       *help;          /* Help information (0 ==> no help) */
        !          2934: #if    defined(NOT43)
        !          2935:     int                (*routine)();   /* Routine to perform (for special ops) */
        !          2936: #else  /* defined(NOT43) */
        !          2937:     void       (*routine)();   /* Routine to perform (for special ops) */
        !          2938: #endif /* defined(NOT43) */
        !          2939: };
        !          2940: 
        !          2941: #define        SENDQUESTION    -1
        !          2942: #define        SENDESCAPE      -3
        !          2943: 
        !          2944: static struct sendlist Sendlist[] = {
        !          2945:     { "ao", AO, "Send Telnet Abort output" },
        !          2946:     { "ayt", AYT, "Send Telnet 'Are You There'" },
        !          2947:     { "brk", BREAK, "Send Telnet Break" },
        !          2948:     { "ec", EC, "Send Telnet Erase Character" },
        !          2949:     { "el", EL, "Send Telnet Erase Line" },
        !          2950:     { "escape", SENDESCAPE, "Send current escape character" },
        !          2951:     { "ga", GA, "Send Telnet 'Go Ahead' sequence" },
        !          2952:     { "ip", IP, "Send Telnet Interrupt Process" },
        !          2953:     { "nop", NOP, "Send Telnet 'No operation'" },
        !          2954:     { "synch", SYNCH, "Perform Telnet 'Synch operation'", dosynch },
        !          2955:     { "?", SENDQUESTION, "Display send options" },
        !          2956:     { 0 }
        !          2957: };
        !          2958: 
        !          2959: static struct sendlist Sendlist2[] = {         /* some synonyms */
        !          2960:        { "break", BREAK, 0 },
        !          2961: 
        !          2962:        { "intp", IP, 0 },
        !          2963:        { "interrupt", IP, 0 },
        !          2964:        { "intr", IP, 0 },
        !          2965: 
        !          2966:        { "help", SENDQUESTION, 0 },
        !          2967: 
        !          2968:        { 0 }
        !          2969: };
        !          2970: 
        !          2971: static char **
        !          2972: getnextsend(name)
        !          2973: char *name;
        !          2974: {
        !          2975:     struct sendlist *c = (struct sendlist *) name;
        !          2976: 
        !          2977:     return (char **) (c+1);
        !          2978: }
        !          2979: 
        !          2980: static struct sendlist *
        !          2981: getsend(name)
        !          2982: char *name;
        !          2983: {
        !          2984:     struct sendlist *sl;
        !          2985: 
        !          2986:     if ((sl = (struct sendlist *)
        !          2987:                        genget(name, (char **) Sendlist, getnextsend)) != 0) {
        !          2988:        return sl;
        !          2989:     } else {
        !          2990:        return (struct sendlist *)
        !          2991:                                genget(name, (char **) Sendlist2, getnextsend);
        !          2992:     }
        !          2993: }
        !          2994: 
        !          2995: static
        !          2996: sendcmd(argc, argv)
        !          2997: int    argc;
        !          2998: char   **argv;
        !          2999: {
        !          3000:     int what;          /* what we are sending this time */
        !          3001:     int count;         /* how many bytes we are going to need to send */
        !          3002:     int i;
        !          3003:     int question = 0;  /* was at least one argument a question */
        !          3004:     struct sendlist *s;        /* pointer to current command */
        !          3005: 
        !          3006:     if (argc < 2) {
        !          3007:        printf("need at least one argument for 'send' command\n");
        !          3008:        printf("'send ?' for help\n");
        !          3009:        return 0;
        !          3010:     }
        !          3011:     /*
        !          3012:      * First, validate all the send arguments.
        !          3013:      * In addition, we see how much space we are going to need, and
        !          3014:      * whether or not we will be doing a "SYNCH" operation (which
        !          3015:      * flushes the network queue).
        !          3016:      */
        !          3017:     count = 0;
        !          3018:     for (i = 1; i < argc; i++) {
        !          3019:        s = getsend(argv[i]);
        !          3020:        if (s == 0) {
        !          3021:            printf("Unknown send argument '%s'\n'send ?' for help.\n",
        !          3022:                        argv[i]);
        !          3023:            return 0;
        !          3024:        } else if (s == Ambiguous(struct sendlist *)) {
        !          3025:            printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
        !          3026:                        argv[i]);
        !          3027:            return 0;
        !          3028:        }
        !          3029:        switch (s->what) {
        !          3030:        case SENDQUESTION:
        !          3031:            break;
        !          3032:        case SENDESCAPE:
        !          3033:            count += 1;
        !          3034:            break;
        !          3035:        case SYNCH:
        !          3036:            count += 2;
        !          3037:            break;
        !          3038:        default:
        !          3039:            count += 2;
        !          3040:            break;
        !          3041:        }
        !          3042:     }
        !          3043:     /* Now, do we have enough room? */
        !          3044:     if (NETROOM() < count) {
        !          3045:        printf("There is not enough room in the buffer TO the network\n");
        !          3046:        printf("to process your request.  Nothing will be done.\n");
        !          3047:        printf("('send synch' will throw away most data in the network\n");
        !          3048:        printf("buffer, if this might help.)\n");
        !          3049:        return 0;
        !          3050:     }
        !          3051:     /* OK, they are all OK, now go through again and actually send */
        !          3052:     for (i = 1; i < argc; i++) {
        !          3053:        if ((s = getsend(argv[i])) == 0) {
        !          3054:            fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
        !          3055:            quit();
        !          3056:            /*NOTREACHED*/
        !          3057:        }
        !          3058:        if (s->routine) {
        !          3059:            (*s->routine)(s);
        !          3060:        } else {
        !          3061:            switch (what = s->what) {
        !          3062:            case SYNCH:
        !          3063:                dosynch();
        !          3064:                break;
        !          3065:            case SENDQUESTION:
        !          3066:                for (s = Sendlist; s->name; s++) {
        !          3067:                    if (s->help) {
        !          3068:                        printf(s->name);
        !          3069:                        if (s->help) {
        !          3070:                            printf("\t%s", s->help);
        !          3071:                        }
        !          3072:                        printf("\n");
        !          3073:                    }
        !          3074:                }
        !          3075:                question = 1;
        !          3076:                break;
        !          3077:            case SENDESCAPE:
        !          3078:                NETADD(escape);
        !          3079:                break;
        !          3080:            default:
        !          3081:                NET2ADD(IAC, what);
        !          3082:                break;
        !          3083:            }
        !          3084:        }
        !          3085:     }
        !          3086:     return !question;
        !          3087: }
        !          3088: 
        !          3089: /*
        !          3090:  * The following are the routines and data structures referred
        !          3091:  * to by the arguments to the "toggle" command.
        !          3092:  */
        !          3093: 
        !          3094: static
        !          3095: lclchars()
        !          3096: {
        !          3097:     donelclchars = 1;
        !          3098:     return 1;
        !          3099: }
        !          3100: 
        !          3101: static
        !          3102: togdebug()
        !          3103: {
        !          3104: #ifndef        NOT43
        !          3105:     if (net > 0 &&
        !          3106:        (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
        !          3107:            perror("setsockopt (SO_DEBUG)");
        !          3108:     }
        !          3109: #else  /* NOT43 */
        !          3110:     if (debug) {
        !          3111:        if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
        !          3112:            perror("setsockopt (SO_DEBUG)");
        !          3113:     } else
        !          3114:        printf("Cannot turn off socket debugging\n");
        !          3115: #endif /* NOT43 */
        !          3116:     return 1;
        !          3117: }
        !          3118: 
        !          3119: 
        !          3120: static int
        !          3121: togcrlf()
        !          3122: {
        !          3123:     if (crlf) {
        !          3124:        printf("Will send carriage returns as telnet <CR><LF>.\n");
        !          3125:     } else {
        !          3126:        printf("Will send carriage returns as telnet <CR><NUL>.\n");
        !          3127:     }
        !          3128:     return 1;
        !          3129: }
        !          3130: 
        !          3131: 
        !          3132: static int
        !          3133: togbinary()
        !          3134: {
        !          3135:     donebinarytoggle = 1;
        !          3136: 
        !          3137:     if (myopts[TELOPT_BINARY] == 0) {  /* Go into binary mode */
        !          3138:        NET2ADD(IAC, DO);
        !          3139:        NETADD(TELOPT_BINARY);
        !          3140:        printoption("<SENT", doopt, TELOPT_BINARY, 0);
        !          3141:        NET2ADD(IAC, WILL);
        !          3142:        NETADD(TELOPT_BINARY);
        !          3143:        printoption("<SENT", doopt, TELOPT_BINARY, 0);
        !          3144:        hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 1;
        !          3145:        printf("Negotiating binary mode with remote host.\n");
        !          3146:     } else {                           /* Turn off binary mode */
        !          3147:        NET2ADD(IAC, DONT);
        !          3148:        NETADD(TELOPT_BINARY);
        !          3149:        printoption("<SENT", dont, TELOPT_BINARY, 0);
        !          3150:        NET2ADD(IAC, DONT);
        !          3151:        NETADD(TELOPT_BINARY);
        !          3152:        printoption("<SENT", dont, TELOPT_BINARY, 0);
        !          3153:        hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 0;
        !          3154:        printf("Negotiating network ascii mode with remote host.\n");
        !          3155:     }
        !          3156:     return 1;
        !          3157: }
        !          3158: 
        !          3159: 
        !          3160: 
        !          3161: extern int togglehelp();
        !          3162: 
        !          3163: struct togglelist {
        !          3164:     char       *name;          /* name of toggle */
        !          3165:     char       *help;          /* help message */
        !          3166:     int                (*handler)();   /* routine to do actual setting */
        !          3167:     int                dohelp;         /* should we display help information */
        !          3168:     int                *variable;
        !          3169:     char       *actionexplanation;
        !          3170: };
        !          3171: 
        !          3172: static struct togglelist Togglelist[] = {
        !          3173:     { "autoflush",
        !          3174:        "toggle flushing of output when sending interrupt characters",
        !          3175:            0,
        !          3176:                1,
        !          3177:                    &autoflush,
        !          3178:                        "flush output when sending interrupt characters" },
        !          3179:     { "autosynch",
        !          3180:        "toggle automatic sending of interrupt characters in urgent mode",
        !          3181:            0,
        !          3182:                1,
        !          3183:                    &autosynch,
        !          3184:                        "send interrupt characters in urgent mode" },
        !          3185:     { "binary",
        !          3186:        "toggle sending and receiving of binary data",
        !          3187:            togbinary,
        !          3188:                1,
        !          3189:                    0,
        !          3190:                        0 },
        !          3191:     { "crlf",
        !          3192:        "toggle sending carriage returns as telnet <CR><LF>",
        !          3193:            togcrlf,
        !          3194:                1,
        !          3195:                    &crlf,
        !          3196:                        0 },
        !          3197:     { "crmod",
        !          3198:        "toggle mapping of received carriage returns",
        !          3199:            0,
        !          3200:                1,
        !          3201:                    &crmod,
        !          3202:                        "map carriage return on output" },
        !          3203:     { "localchars",
        !          3204:        "toggle local recognition of certain control characters",
        !          3205:            lclchars,
        !          3206:                1,
        !          3207:                    &localchars,
        !          3208:                        "recognize certain control characters" },
        !          3209:     { " ", "", 0, 1 },         /* empty line */
        !          3210:     { "debug",
        !          3211:        "(debugging) toggle debugging",
        !          3212:            togdebug,
        !          3213:                1,
        !          3214:                    &debug,
        !          3215:                        "turn on socket level debugging" },
        !          3216:     { "netdata",
        !          3217:        "(debugging) toggle printing of hexadecimal network data",
        !          3218:            0,
        !          3219:                1,
        !          3220:                    &netdata,
        !          3221:                        "print hexadecimal representation of network traffic" },
        !          3222:     { "options",
        !          3223:        "(debugging) toggle viewing of options processing",
        !          3224:            0,
        !          3225:                1,
        !          3226:                    &showoptions,
        !          3227:                        "show option processing" },
        !          3228:     { " ", "", 0, 1 },         /* empty line */
        !          3229:     { "?",
        !          3230:        "display help information",
        !          3231:            togglehelp,
        !          3232:                1 },
        !          3233:     { "help",
        !          3234:        "display help information",
        !          3235:            togglehelp,
        !          3236:                0 },
        !          3237:     { 0 }
        !          3238: };
        !          3239: 
        !          3240: static
        !          3241: togglehelp()
        !          3242: {
        !          3243:     struct togglelist *c;
        !          3244: 
        !          3245:     for (c = Togglelist; c->name; c++) {
        !          3246:        if (c->dohelp) {
        !          3247:            printf("%s\t%s\n", c->name, c->help);
        !          3248:        }
        !          3249:     }
        !          3250:     return 0;
        !          3251: }
        !          3252: 
        !          3253: static char **
        !          3254: getnexttoggle(name)
        !          3255: char *name;
        !          3256: {
        !          3257:     struct togglelist *c = (struct togglelist *) name;
        !          3258: 
        !          3259:     return (char **) (c+1);
        !          3260: }
        !          3261: 
        !          3262: static struct togglelist *
        !          3263: gettoggle(name)
        !          3264: char *name;
        !          3265: {
        !          3266:     return (struct togglelist *)
        !          3267:                        genget(name, (char **) Togglelist, getnexttoggle);
        !          3268: }
        !          3269: 
        !          3270: static
        !          3271: toggle(argc, argv)
        !          3272: int    argc;
        !          3273: char   *argv[];
        !          3274: {
        !          3275:     int retval = 1;
        !          3276:     char *name;
        !          3277:     struct togglelist *c;
        !          3278: 
        !          3279:     if (argc < 2) {
        !          3280:        fprintf(stderr,
        !          3281:            "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
        !          3282:        return 0;
        !          3283:     }
        !          3284:     argc--;
        !          3285:     argv++;
        !          3286:     while (argc--) {
        !          3287:        name = *argv++;
        !          3288:        c = gettoggle(name);
        !          3289:        if (c == Ambiguous(struct togglelist *)) {
        !          3290:            fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
        !          3291:                                        name);
        !          3292:            return 0;
        !          3293:        } else if (c == 0) {
        !          3294:            fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
        !          3295:                                        name);
        !          3296:            return 0;
        !          3297:        } else {
        !          3298:            if (c->variable) {
        !          3299:                *c->variable = !*c->variable;           /* invert it */
        !          3300:                if (c->actionexplanation) {
        !          3301:                    printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !          3302:                                                        c->actionexplanation);
        !          3303:                }
        !          3304:            }
        !          3305:            if (c->handler) {
        !          3306:                retval &= (*c->handler)(c);
        !          3307:            }
        !          3308:        }
        !          3309:     }
        !          3310:     return retval;
        !          3311: }
        !          3312: 
        !          3313: /*
        !          3314:  * The following perform the "set" command.
        !          3315:  */
        !          3316: 
        !          3317: struct setlist {
        !          3318:     char *name;                                /* name */
        !          3319:     char *help;                                /* help information */
        !          3320:     char *charp;                       /* where it is located at */
        !          3321: };
        !          3322: 
        !          3323: static struct setlist Setlist[] = {
        !          3324:     { "echo",  "character to toggle local echoing on/off", &echoc },
        !          3325:     { "escape",        "character to escape back to telnet command mode", &escape },
        !          3326:     { " ", "" },
        !          3327:     { " ", "The following need 'localchars' to be toggled true", 0 },
        !          3328: #if    defined(unix)
        !          3329:     { "erase", "character to cause an Erase Character", &nttyb.sg_erase },
        !          3330:     { "flushoutput", "character to cause an Abort Oubput", &nltc.t_flushc },
        !          3331:     { "interrupt", "character to cause an Interrupt Process", &ntc.t_intrc },
        !          3332:     { "kill",  "character to cause an Erase Line", &nttyb.sg_kill },
        !          3333:     { "quit",  "character to cause a Break", &ntc.t_quitc },
        !          3334:     { "eof",   "character to cause an EOF ", &ntc.t_eofc },
        !          3335: #endif /* defined(unix) */
        !          3336: #if    defined(MSDOS)
        !          3337:     { "erase", "character to cause an Erase Character", &termEraseChar },
        !          3338:     { "flushoutput", "character to cause an Abort Oubput", &termFlushChar },
        !          3339:     { "interrupt", "character to cause an Interrupt Process", &termIntChar },
        !          3340:     { "kill",  "character to cause an Erase Line", &termKillChar },
        !          3341:     { "quit",  "character to cause a Break", &termQuitChar },
        !          3342:     { "eof",   "character to cause an EOF ", &termEofChar },
        !          3343: #endif /* defined(MSDOS) */
        !          3344:     { 0 }
        !          3345: };
        !          3346: 
        !          3347: static char **
        !          3348: getnextset(name)
        !          3349: char *name;
        !          3350: {
        !          3351:     struct setlist *c = (struct setlist *)name;
        !          3352: 
        !          3353:     return (char **) (c+1);
        !          3354: }
        !          3355: 
        !          3356: static struct setlist *
        !          3357: getset(name)
        !          3358: char *name;
        !          3359: {
        !          3360:     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
        !          3361: }
        !          3362: 
        !          3363: static
        !          3364: setcmd(argc, argv)
        !          3365: int    argc;
        !          3366: char   *argv[];
        !          3367: {
        !          3368:     int value;
        !          3369:     struct setlist *ct;
        !          3370: 
        !          3371:     /* XXX back we go... sigh */
        !          3372:     if (argc != 3) {
        !          3373:        if ((argc == 2) &&
        !          3374:                    ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
        !          3375:            for (ct = Setlist; ct->name; ct++) {
        !          3376:                printf("%s\t%s\n", ct->name, ct->help);
        !          3377:            }
        !          3378:            printf("?\tdisplay help information\n");
        !          3379:        } else {
        !          3380:            printf("Format is 'set Name Value'\n'set ?' for help.\n");
        !          3381:        }
        !          3382:        return 0;
        !          3383:     }
        !          3384: 
        !          3385:     ct = getset(argv[1]);
        !          3386:     if (ct == 0) {
        !          3387:        fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
        !          3388:                        argv[1]);
        !          3389:        return 0;
        !          3390:     } else if (ct == Ambiguous(struct setlist *)) {
        !          3391:        fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
        !          3392:                        argv[1]);
        !          3393:        return 0;
        !          3394:     } else {
        !          3395:        if (strcmp("off", argv[2])) {
        !          3396:            value = special(argv[2]);
        !          3397:        } else {
        !          3398:            value = -1;
        !          3399:        }
        !          3400:        *(ct->charp) = value;
        !          3401:        printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        !          3402:     }
        !          3403:     return 1;
        !          3404: }
        !          3405: 
        !          3406: /*
        !          3407:  * The following are the data structures and routines for the
        !          3408:  * 'mode' command.
        !          3409:  */
        !          3410: 
        !          3411: static
        !          3412: dolinemode()
        !          3413: {
        !          3414:     if (hisopts[TELOPT_SGA]) {
        !          3415:        wontoption(TELOPT_SGA, 0);
        !          3416:     }
        !          3417:     if (hisopts[TELOPT_ECHO]) {
        !          3418:        wontoption(TELOPT_ECHO, 0);
        !          3419:     }
        !          3420:     return 1;
        !          3421: }
        !          3422: 
        !          3423: static
        !          3424: docharmode()
        !          3425: {
        !          3426:     if (!hisopts[TELOPT_SGA]) {
        !          3427:        willoption(TELOPT_SGA, 0);
        !          3428:     }
        !          3429:     if (!hisopts[TELOPT_ECHO]) {
        !          3430:        willoption(TELOPT_ECHO, 0);
        !          3431:     }
        !          3432:     return 1;
        !          3433: }
        !          3434: 
        !          3435: static struct cmd Modelist[] = {
        !          3436:     { "character",     "character-at-a-time mode",     docharmode, 1, 1 },
        !          3437:     { "line",          "line-by-line mode",            dolinemode, 1, 1 },
        !          3438:     { 0 },
        !          3439: };
        !          3440: 
        !          3441: static char **
        !          3442: getnextmode(name)
        !          3443: char *name;
        !          3444: {
        !          3445:     struct cmd *c = (struct cmd *) name;
        !          3446: 
        !          3447:     return (char **) (c+1);
        !          3448: }
        !          3449: 
        !          3450: static struct cmd *
        !          3451: getmodecmd(name)
        !          3452: char *name;
        !          3453: {
        !          3454:     return (struct cmd *) genget(name, (char **) Modelist, getnextmode);
        !          3455: }
        !          3456: 
        !          3457: static
        !          3458: modecmd(argc, argv)
        !          3459: int    argc;
        !          3460: char   *argv[];
        !          3461: {
        !          3462:     struct cmd *mt;
        !          3463: 
        !          3464:     if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) {
        !          3465:        printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
        !          3466:        for (mt = Modelist; mt->name; mt++) {
        !          3467:            printf("%s\t%s\n", mt->name, mt->help);
        !          3468:        }
        !          3469:        return 0;
        !          3470:     }
        !          3471:     mt = getmodecmd(argv[1]);
        !          3472:     if (mt == 0) {
        !          3473:        fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
        !          3474:        return 0;
        !          3475:     } else if (mt == Ambiguous(struct cmd *)) {
        !          3476:        fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
        !          3477:        return 0;
        !          3478:     } else {
        !          3479:        (*mt->handler)();
        !          3480:     }
        !          3481:     return 1;
        !          3482: }
        !          3483: 
        !          3484: /*
        !          3485:  * The following data structures and routines implement the
        !          3486:  * "display" command.
        !          3487:  */
        !          3488: 
        !          3489: static
        !          3490: display(argc, argv)
        !          3491: int    argc;
        !          3492: char   *argv[];
        !          3493: {
        !          3494: #define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
        !          3495:                            if (*tl->variable) { \
        !          3496:                                printf("will"); \
        !          3497:                            } else { \
        !          3498:                                printf("won't"); \
        !          3499:                            } \
        !          3500:                            printf(" %s.\n", tl->actionexplanation); \
        !          3501:                        }
        !          3502: 
        !          3503: #define        doset(sl)   if (sl->name && *sl->name != ' ') { \
        !          3504:                        printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \
        !          3505:                    }
        !          3506: 
        !          3507:     struct togglelist *tl;
        !          3508:     struct setlist *sl;
        !          3509: 
        !          3510:     if (argc == 1) {
        !          3511:        for (tl = Togglelist; tl->name; tl++) {
        !          3512:            dotog(tl);
        !          3513:        }
        !          3514:        printf("\n");
        !          3515:        for (sl = Setlist; sl->name; sl++) {
        !          3516:            doset(sl);
        !          3517:        }
        !          3518:     } else {
        !          3519:        int i;
        !          3520: 
        !          3521:        for (i = 1; i < argc; i++) {
        !          3522:            sl = getset(argv[i]);
        !          3523:            tl = gettoggle(argv[i]);
        !          3524:            if ((sl == Ambiguous(struct setlist *)) ||
        !          3525:                                (tl == Ambiguous(struct togglelist *))) {
        !          3526:                printf("?Ambiguous argument '%s'.\n", argv[i]);
        !          3527:                return 0;
        !          3528:            } else if (!sl && !tl) {
        !          3529:                printf("?Unknown argument '%s'.\n", argv[i]);
        !          3530:                return 0;
        !          3531:            } else {
        !          3532:                if (tl) {
        !          3533:                    dotog(tl);
        !          3534:                }
        !          3535:                if (sl) {
        !          3536:                    doset(sl);
        !          3537:                }
        !          3538:            }
        !          3539:        }
        !          3540:     }
        !          3541:     return 1;
        !          3542: #undef doset
        !          3543: #undef dotog
        !          3544: }
        !          3545: 
        !          3546: /*
        !          3547:  * The following are the data structures, and many of the routines,
        !          3548:  * relating to command processing.
        !          3549:  */
        !          3550: 
        !          3551: /*
        !          3552:  * Set the escape character.
        !          3553:  */
        !          3554: static
        !          3555: setescape(argc, argv)
        !          3556:        int argc;
        !          3557:        char *argv[];
        !          3558: {
        !          3559:        register char *arg;
        !          3560:        char buf[50];
        !          3561: 
        !          3562:        printf(
        !          3563:            "Deprecated usage - please use 'set escape%s%s' in the future.\n",
        !          3564:                                (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
        !          3565:        if (argc > 2)
        !          3566:                arg = argv[1];
        !          3567:        else {
        !          3568:                printf("new escape character: ");
        !          3569:                gets(buf);
        !          3570:                arg = buf;
        !          3571:        }
        !          3572:        if (arg[0] != '\0')
        !          3573:                escape = arg[0];
        !          3574:        if (!In3270) {
        !          3575:                printf("Escape character is '%s'.\n", control(escape));
        !          3576:        }
        !          3577:        fflush(stdout);
        !          3578:        return 1;
        !          3579: }
        !          3580: 
        !          3581: /*VARARGS*/
        !          3582: static
        !          3583: togcrmod()
        !          3584: {
        !          3585:     crmod = !crmod;
        !          3586:     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
        !          3587:     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
        !          3588:     fflush(stdout);
        !          3589:     return 1;
        !          3590: }
        !          3591: 
        !          3592: /*VARARGS*/
        !          3593: suspend()
        !          3594: {
        !          3595:        setcommandmode();
        !          3596: #if    defined(unix)
        !          3597:        kill(0, SIGTSTP);
        !          3598: #endif /* defined(unix) */
        !          3599:        /* reget parameters in case they were changed */
        !          3600:        TerminalSaveState();
        !          3601:        setconnmode();
        !          3602:        return 1;
        !          3603: }
        !          3604: 
        !          3605: /*VARARGS*/
        !          3606: static
        !          3607: bye(argc, argv)
        !          3608: int    argc;           /* Number of arguments */
        !          3609: char   *argv[];        /* arguments */
        !          3610: {
        !          3611:     if (connected) {
        !          3612:        shutdown(net, 2);
        !          3613:        printf("Connection closed.\n");
        !          3614:        NetClose(net);
        !          3615:        connected = 0;
        !          3616:        /* reset options */
        !          3617:        tninit();
        !          3618: #if    defined(TN3270)
        !          3619:        SetIn3270();            /* Get out of 3270 mode */
        !          3620: #endif /* defined(TN3270) */
        !          3621:     }
        !          3622:     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
        !          3623:        longjmp(toplevel, 1);
        !          3624:        /* NOTREACHED */
        !          3625:     }
        !          3626:     return 1;                  /* Keep lint, etc., happy */
        !          3627: }
        !          3628: 
        !          3629: /*VARARGS*/
        !          3630: quit()
        !          3631: {
        !          3632:        (void) call(bye, "bye", "fromquit", 0);
        !          3633:        Exit(0);
        !          3634:        /*NOTREACHED*/
        !          3635:        return 1;                       /* just to keep lint happy */
        !          3636: }
        !          3637: 
        !          3638: /*
        !          3639:  * Print status about the connection.
        !          3640:  */
        !          3641: static
        !          3642: status(argc, argv)
        !          3643: int    argc;
        !          3644: char   *argv[];
        !          3645: {
        !          3646:     if (connected) {
        !          3647:        printf("Connected to %s.\n", hostname);
        !          3648:        if (argc < 2) {
        !          3649:            printf("Operating in %s.\n",
        !          3650:                                modelist[getconnmode()].modedescriptions);
        !          3651:            if (localchars) {
        !          3652:                printf("Catching signals locally.\n");
        !          3653:            }
        !          3654:        }
        !          3655:     } else {
        !          3656:        printf("No connection.\n");
        !          3657:     }
        !          3658: #   if !defined(TN3270)
        !          3659:     printf("Escape character is '%s'.\n", control(escape));
        !          3660:     fflush(stdout);
        !          3661: #   else /* !defined(TN3270) */
        !          3662:     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
        !          3663:        printf("Escape character is '%s'.\n", control(escape));
        !          3664:     }
        !          3665: #   if defined(unix)
        !          3666:     if (In3270 && transcom) {
        !          3667:        printf("Transparent mode command is '%s'.\n", transcom);
        !          3668:     }
        !          3669: #   endif /* defined(unix) */
        !          3670:     fflush(stdout);
        !          3671:     if (In3270) {
        !          3672:        return 0;
        !          3673:     }
        !          3674: #   endif /* defined(TN3270) */
        !          3675:     return 1;
        !          3676: }
        !          3677: 
        !          3678: #if    defined(TN3270) && defined(unix)
        !          3679: static
        !          3680: settranscom(argc, argv)
        !          3681:        int argc;
        !          3682:        char *argv[];
        !          3683: {
        !          3684:        int i, len = 0;
        !          3685:        char *strcpy(), *strcat();
        !          3686: 
        !          3687:        if (argc == 1 && transcom) {
        !          3688:           transcom = 0;
        !          3689:        }
        !          3690:        if (argc == 1) {
        !          3691:           return;
        !          3692:        }
        !          3693:        for (i = 1; i < argc; ++i) {
        !          3694:            len += 1 + strlen(argv[1]);
        !          3695:        }
        !          3696:        transcom = tline;
        !          3697:        (void) strcpy(transcom, argv[1]);
        !          3698:        for (i = 2; i < argc; ++i) {
        !          3699:            (void) strcat(transcom, " ");
        !          3700:            (void) strcat(transcom, argv[i]);
        !          3701:        }
        !          3702: }
        !          3703: #endif /* defined(TN3270) && defined(unix) */
        !          3704: 
        !          3705: 
        !          3706: 
        !          3707: static
        !          3708: tn(argc, argv)
        !          3709:        int argc;
        !          3710:        char *argv[];
        !          3711: {
        !          3712:     register struct hostent *host = 0;
        !          3713: #if defined(MSDOS)
        !          3714:     char *cp;
        !          3715: #endif /* defined(MSDOS) */
        !          3716: 
        !          3717:     if (connected) {
        !          3718:        printf("?Already connected to %s\n", hostname);
        !          3719:        return 0;
        !          3720:     }
        !          3721:     if (argc < 2) {
        !          3722:        (void) strcpy(line, "Connect ");
        !          3723:        printf("(to) ");
        !          3724:        gets(&line[strlen(line)]);
        !          3725:        makeargv();
        !          3726:        argc = margc;
        !          3727:        argv = margv;
        !          3728:     }
        !          3729:     if ((argc < 2) || (argc > 3)) {
        !          3730:        printf("usage: %s host-name [port]\n", argv[0]);
        !          3731:        return 0;
        !          3732:     }
        !          3733: #if    defined(MSDOS)
        !          3734:     for (cp = argv[1]; *cp; cp++) {
        !          3735:        if (isupper(*cp)) {
        !          3736:            *cp = tolower(*cp);
        !          3737:        }
        !          3738:     }
        !          3739: #endif /* defined(MSDOS) */
        !          3740:     sin.sin_addr.s_addr = inet_addr(argv[1]);
        !          3741:     if (sin.sin_addr.s_addr != -1) {
        !          3742:        sin.sin_family = AF_INET;
        !          3743:        (void) strcpy(hnamebuf, argv[1]);
        !          3744:        hostname = hnamebuf;
        !          3745:     } else {
        !          3746:        host = gethostbyname(argv[1]);
        !          3747:        if (host) {
        !          3748:            sin.sin_family = host->h_addrtype;
        !          3749: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !          3750:            memcpy((caddr_t)&sin.sin_addr,
        !          3751:                                host->h_addr_list[0], host->h_length);
        !          3752: #else  /* defined(h_addr) */
        !          3753:            memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
        !          3754: #endif /* defined(h_addr) */
        !          3755:            hostname = host->h_name;
        !          3756:        } else {
        !          3757:            printf("%s: unknown host\n", argv[1]);
        !          3758:            return 0;
        !          3759:        }
        !          3760:     }
        !          3761:     sin.sin_port = sp->s_port;
        !          3762:     if (argc == 3) {
        !          3763:        sin.sin_port = atoi(argv[2]);
        !          3764:        if (sin.sin_port == 0) {
        !          3765:            sp = getservbyname(argv[2], "tcp");
        !          3766:            if (sp)
        !          3767:                sin.sin_port = sp->s_port;
        !          3768:            else {
        !          3769:                printf("%s: bad port number\n", argv[2]);
        !          3770:                return 0;
        !          3771:            }
        !          3772:        } else {
        !          3773:            sin.sin_port = atoi(argv[2]);
        !          3774:            sin.sin_port = htons(sin.sin_port);
        !          3775:        }
        !          3776:        telnetport = 0;
        !          3777:     } else {
        !          3778:        telnetport = 1;
        !          3779:     }
        !          3780: #if    defined(unix)
        !          3781:     signal(SIGINT, intr);
        !          3782:     signal(SIGQUIT, intr2);
        !          3783:     signal(SIGPIPE, deadpeer);
        !          3784: #endif /* defined(unix) */
        !          3785:     printf("Trying...\n");
        !          3786:     do {
        !          3787:        net = socket(AF_INET, SOCK_STREAM, 0);
        !          3788:        if (net < 0) {
        !          3789:            perror("telnet: socket");
        !          3790:            return 0;
        !          3791:        }
        !          3792:        if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
        !          3793:                perror("setsockopt (SO_DEBUG)");
        !          3794:        }
        !          3795: 
        !          3796:        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
        !          3797: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !          3798:            if (host && host->h_addr_list[1]) {
        !          3799:                int oerrno = errno;
        !          3800: 
        !          3801:                fprintf(stderr, "telnet: connect to address %s: ",
        !          3802:                                                inet_ntoa(sin.sin_addr));
        !          3803:                errno = oerrno;
        !          3804:                perror((char *)0);
        !          3805:                host->h_addr_list++;
        !          3806:                memcpy((caddr_t)&sin.sin_addr, 
        !          3807:                        host->h_addr_list[0], host->h_length);
        !          3808:                fprintf(stderr, "Trying %s...\n",
        !          3809:                        inet_ntoa(sin.sin_addr));
        !          3810:                (void) NetClose(net);
        !          3811:                continue;
        !          3812:            }
        !          3813: #endif /* defined(h_addr) */
        !          3814:            perror("telnet: Unable to connect to remote host");
        !          3815: #if defined(unix)
        !          3816:            signal(SIGINT, SIG_DFL);
        !          3817:            signal(SIGQUIT, SIG_DFL);
        !          3818: #endif /* defined(unix) */
        !          3819:            return 0;
        !          3820:            }
        !          3821:        connected++;
        !          3822:     } while (connected == 0);
        !          3823:     call(status, "status", "notmuch", 0);
        !          3824:     if (setjmp(peerdied) == 0)
        !          3825:        telnet();
        !          3826:     NetClose(net);
        !          3827:     ExitString(stderr, "Connection closed by foreign host.\n",1);
        !          3828:     /*NOTREACHED*/
        !          3829: }
        !          3830: 
        !          3831: 
        !          3832: #define HELPINDENT (sizeof ("connect"))
        !          3833: 
        !          3834: static char
        !          3835:        openhelp[] =    "connect to a site",
        !          3836:        closehelp[] =   "close current connection",
        !          3837:        quithelp[] =    "exit telnet",
        !          3838:        statushelp[] =  "print status information",
        !          3839:        helphelp[] =    "print help information",
        !          3840:        sendhelp[] =    "transmit special characters ('send ?' for more)",
        !          3841:        sethelp[] =     "set operating parameters ('set ?' for more)",
        !          3842:        togglestring[] ="toggle operating parameters ('toggle ?' for more)",
        !          3843:        displayhelp[] = "display operating parameters",
        !          3844: #if    defined(TN3270) && defined(unix)
        !          3845:        transcomhelp[] = "specify Unix command for transparent mode pipe",
        !          3846: #endif /* defined(TN3270) && defined(unix) */
        !          3847: #if    defined(unix)
        !          3848:        zhelp[] =       "suspend telnet",
        !          3849: #endif /* defined(unix */
        !          3850: #if    defined(TN3270)
        !          3851:        shellhelp[] =   "invoke a subshell",
        !          3852: #endif /* defined(TN3270) */
        !          3853:        modehelp[] = "try to enter line-by-line or character-at-a-time mode";
        !          3854: 
        !          3855: extern int     help(), shell();
        !          3856: 
        !          3857: static struct cmd cmdtab[] = {
        !          3858:        { "close",      closehelp,      bye,            1, 1 },
        !          3859:        { "display",    displayhelp,    display,        1, 0 },
        !          3860:        { "mode",       modehelp,       modecmd,        1, 1 },
        !          3861:        { "open",       openhelp,       tn,             1, 0 },
        !          3862:        { "quit",       quithelp,       quit,           1, 0 },
        !          3863:        { "send",       sendhelp,       sendcmd,        1, 1 },
        !          3864:        { "set",        sethelp,        setcmd,         1, 0 },
        !          3865:        { "status",     statushelp,     status,         1, 0 },
        !          3866:        { "toggle",     togglestring,   toggle,         1, 0 },
        !          3867: #if    defined(TN3270) && defined(unix)
        !          3868:        { "transcom",   transcomhelp,   settranscom,    1, 0 },
        !          3869: #endif /* defined(TN3270) && defined(unix) */
        !          3870: #if    defined(unix)
        !          3871:        { "z",          zhelp,          suspend,        1, 0 },
        !          3872: #endif /* defined(unix) */
        !          3873: #if    defined(TN3270)
        !          3874:        { "!",          shellhelp,      shell,          1, 1 },
        !          3875: #endif /* defined(TN3270) */
        !          3876:        { "?",          helphelp,       help,           1, 0 },
        !          3877:        0
        !          3878: };
        !          3879: 
        !          3880: static char    crmodhelp[] =   "deprecated command -- use 'toggle crmod' instead";
        !          3881: static char    escapehelp[] =  "deprecated command -- use 'set escape' instead";
        !          3882: 
        !          3883: static struct cmd cmdtab2[] = {
        !          3884:        { "help",       helphelp,       help,           0, 0 },
        !          3885:        { "escape",     escapehelp,     setescape,      1, 0 },
        !          3886:        { "crmod",      crmodhelp,      togcrmod,       1, 0 },
        !          3887:        0
        !          3888: };
        !          3889: 
        !          3890: /*
        !          3891:  * Call routine with argc, argv set from args (terminated by 0).
        !          3892:  * VARARGS2
        !          3893:  */
        !          3894: static
        !          3895: call(routine, args)
        !          3896:        int (*routine)();
        !          3897:        char *args;
        !          3898: {
        !          3899:        register char **argp;
        !          3900:        register int argc;
        !          3901: 
        !          3902:        for (argc = 0, argp = &args; *argp++ != 0; argc++)
        !          3903:                ;
        !          3904:        return (*routine)(argc, &args);
        !          3905: }
        !          3906: 
        !          3907: static char **
        !          3908: getnextcmd(name)
        !          3909: char *name;
        !          3910: {
        !          3911:     struct cmd *c = (struct cmd *) name;
        !          3912: 
        !          3913:     return (char **) (c+1);
        !          3914: }
        !          3915: 
        !          3916: static struct cmd *
        !          3917: getcmd(name)
        !          3918: char *name;
        !          3919: {
        !          3920:     struct cmd *cm;
        !          3921: 
        !          3922:     if ((cm = (struct cmd *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
        !          3923:        return cm;
        !          3924:     } else {
        !          3925:        return (struct cmd *) genget(name, (char **) cmdtab2, getnextcmd);
        !          3926:     }
        !          3927: }
        !          3928: 
        !          3929: void
        !          3930: command(top)
        !          3931:        int top;
        !          3932: {
        !          3933:     register struct cmd *c;
        !          3934: 
        !          3935:     setcommandmode();
        !          3936:     if (!top) {
        !          3937:        putchar('\n');
        !          3938:     } else {
        !          3939: #if    defined(unix)
        !          3940:        signal(SIGINT, SIG_DFL);
        !          3941:        signal(SIGQUIT, SIG_DFL);
        !          3942: #endif /* defined(unix) */
        !          3943:     }
        !          3944:     for (;;) {
        !          3945:        printf("%s> ", prompt);
        !          3946:        if (gets(line) == NULL) {
        !          3947:            if (feof(stdin) || ferror(stdin))
        !          3948:                quit();
        !          3949:            break;
        !          3950:        }
        !          3951:        if (line[0] == 0)
        !          3952:            break;
        !          3953:        makeargv();
        !          3954:        c = getcmd(margv[0]);
        !          3955:        if (c == Ambiguous(struct cmd *)) {
        !          3956:            printf("?Ambiguous command\n");
        !          3957:            continue;
        !          3958:        }
        !          3959:        if (c == 0) {
        !          3960:            printf("?Invalid command\n");
        !          3961:            continue;
        !          3962:        }
        !          3963:        if (c->needconnect && !connected) {
        !          3964:            printf("?Need to be connected first.\n");
        !          3965:            continue;
        !          3966:        }
        !          3967:        if ((*c->handler)(margc, margv)) {
        !          3968:            break;
        !          3969:        }
        !          3970:     }
        !          3971:     if (!top) {
        !          3972:        if (!connected) {
        !          3973:            longjmp(toplevel, 1);
        !          3974:            /*NOTREACHED*/
        !          3975:        }
        !          3976: #if    defined(TN3270)
        !          3977:        if (shell_active == 0) {
        !          3978:            setconnmode();
        !          3979:        }
        !          3980: #else  /* defined(TN3270) */
        !          3981:        setconnmode();
        !          3982: #endif /* defined(TN3270) */
        !          3983:     }
        !          3984: }
        !          3985: 
        !          3986: /*
        !          3987:  * Help command.
        !          3988:  */
        !          3989: static
        !          3990: help(argc, argv)
        !          3991:        int argc;
        !          3992:        char *argv[];
        !          3993: {
        !          3994:        register struct cmd *c;
        !          3995: 
        !          3996:        if (argc == 1) {
        !          3997:                printf("Commands may be abbreviated.  Commands are:\n\n");
        !          3998:                for (c = cmdtab; c->name; c++)
        !          3999:                        if (c->dohelp) {
        !          4000:                                printf("%-*s\t%s\n", HELPINDENT, c->name,
        !          4001:                                                                    c->help);
        !          4002:                        }
        !          4003:                return 0;
        !          4004:        }
        !          4005:        while (--argc > 0) {
        !          4006:                register char *arg;
        !          4007:                arg = *++argv;
        !          4008:                c = getcmd(arg);
        !          4009:                if (c == Ambiguous(struct cmd *))
        !          4010:                        printf("?Ambiguous help command %s\n", arg);
        !          4011:                else if (c == (struct cmd *)0)
        !          4012:                        printf("?Invalid help command %s\n", arg);
        !          4013:                else
        !          4014:                        printf("%s\n", c->help);
        !          4015:        }
        !          4016:        return 0;
        !          4017: }
        !          4018: 
        !          4019: /*
        !          4020:  * main.  Parse arguments, invoke the protocol or command parser.
        !          4021:  */
        !          4022: 
        !          4023: 
        !          4024: void
        !          4025: main(argc, argv)
        !          4026:        int argc;
        !          4027:        char *argv[];
        !          4028: {
        !          4029:     tninit();          /* Clear out things */
        !          4030: 
        !          4031:     NetTrace = stdout;
        !          4032:     TerminalSaveState();
        !          4033:     autoflush = TerminalAutoFlush();
        !          4034: 
        !          4035:     prompt = argv[0];
        !          4036:     while ((argc > 1) && (argv[1][0] == '-')) {
        !          4037:        if (!strcmp(argv[1], "-d")) {
        !          4038:            debug = 1;
        !          4039:        } else if (!strcmp(argv[1], "-n")) {
        !          4040:            if ((argc > 1) && (argv[2][0] != '-')) {    /* get file name */
        !          4041:                NetTrace = fopen(argv[2], "w");
        !          4042:                argv++;
        !          4043:                argc--;
        !          4044:                if (NetTrace == NULL) {
        !          4045:                    NetTrace = stdout;
        !          4046:                }
        !          4047:            }
        !          4048:        } else {
        !          4049: #if    defined(TN3270) && defined(unix)
        !          4050:            if (!strcmp(argv[1], "-t")) {
        !          4051:                if ((argc > 1) && (argv[2][0] != '-')) { /* get file name */
        !          4052:                    transcom = tline;
        !          4053:                    (void) strcpy(transcom, argv[1]);
        !          4054:                    argv++;
        !          4055:                    argc--;
        !          4056:                }
        !          4057:            } else if (!strcmp(argv[1], "-noasynch")) {
        !          4058:                noasynch = 1;
        !          4059:            } else
        !          4060: #endif /* defined(TN3270) && defined(unix) */
        !          4061:            if (argv[1][1] != '\0') {
        !          4062:                fprintf(stderr, "Unknown option *%s*.\n", argv[1]);
        !          4063:            }
        !          4064:        }
        !          4065:        argc--;
        !          4066:        argv++;
        !          4067:     }
        !          4068:     if (argc != 1) {
        !          4069:        if (setjmp(toplevel) != 0)
        !          4070:            Exit(0);
        !          4071:        tn(argc, argv);
        !          4072:     }
        !          4073:     setjmp(toplevel);
        !          4074:     for (;;) {
        !          4075: #if    !defined(TN3270)
        !          4076:        command(1);
        !          4077: #else  /* !defined(TN3270) */
        !          4078:        if (!shell_active) {
        !          4079:            command(1);
        !          4080:        } else {
        !          4081: #if    defined(TN3270)
        !          4082:            shell_continue();
        !          4083: #endif /* defined(TN3270) */
        !          4084:        }
        !          4085: #endif /* !defined(TN3270) */
        !          4086:     }
        !          4087: }

unix.superglobalmegacorp.com

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