Annotation of 43BSD/ucb/tn3270/tn3270.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     Copyright 1984, 1985 by the Regents of the University of
                      3:  *     California and by Gregory Glenn Minshall.
                      4:  *
                      5:  *     Permission to use, copy, modify, and distribute these
                      6:  *     programs and their documentation for any purpose and
                      7:  *     without fee is hereby granted, provided that this
                      8:  *     copyright and permission appear on all copies and
                      9:  *     supporting documentation, the name of the Regents of
                     10:  *     the University of California not be used in advertising
                     11:  *     or publicity pertaining to distribution of the programs
                     12:  *     without specific prior permission, and notice be given in
                     13:  *     supporting documentation that copying and distribution is
                     14:  *     by permission of the Regents of the University of California
                     15:  *     and by Gregory Glenn Minshall.  Neither the Regents of the
                     16:  *     University of California nor Gregory Glenn Minshall make
                     17:  *     representations about the suitability of this software
                     18:  *     for any purpose.  It is provided "as is" without
                     19:  *     express or implied warranty.
                     20:  */
                     21: 
                     22: 
                     23: #ifndef lint
                     24: static char sccsid[] = "@(#)tn3270.c   2.7\t5/13/86";
                     25: #endif
                     26: 
                     27: /*
                     28:  * User telnet program, specially modified for tn3270.
                     29:  */
                     30: #include <sys/types.h>
                     31: #include <sys/socket.h>
                     32: #include <sys/ioctl.h>
                     33: #include <sys/time.h>
                     34: 
                     35: #include <netinet/in.h>
                     36: 
                     37: #define        TELOPTS
                     38: #include <arpa/telnet.h>
                     39: 
                     40: #include <stdio.h>
                     41: #include <ctype.h>
                     42: #include <errno.h>
                     43: #include <signal.h>
                     44: #include <setjmp.h>
                     45: #include <netdb.h>
                     46: 
                     47: #define        strip(x)        ((x)&0177)
                     48: #define min(x,y)       ((x<y)? x:y)
                     49: 
                     50: static char    Ibuf[8*BUFSIZ], *Ifrontp = Ibuf, *Ibackp = Ibuf;
                     51: static char    ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
                     52: static char    netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
                     53: 
                     54: static char    SbBuffer[100], *pSb = SbBuffer;
                     55: #define Sb_Option SbBuffer[0]
                     56: #define Sb_Command SbBuffer[1]
                     57: 
                     58: 
                     59: static char    hisopts[256];
                     60: static char    myopts[256];
                     61: 
                     62: static char    doopt[] = { IAC, DO, '%', 'c', 0 };
                     63: static char    dont[] = { IAC, DONT, '%', 'c', 0 };
                     64: static char    will[] = { IAC, WILL, '%', 'c', 0 };
                     65: static char    wont[] = { IAC, WONT, '%', 'c', 0 };
                     66: static char    sb_terminal[] = { IAC, SB,
                     67:                        TELOPT_TTYPE, TELQUAL_IS,
                     68:                        'I', 'B', 'M', '-', '3', '2', '7', '7', '-', '2',
                     69:                        IAC, SE };
                     70: 
                     71: /* The following is a real, live, global. */
                     72: 
                     73: /* The point of HaveInput is to give a hint to the terminal output processor
                     74:  * that some input from some source (network or terminal) has come in.
                     75:  */
                     76: 
                     77: int HaveInput = 1;     /* we have received input in the not too distant past */
                     78: 
                     79: 
                     80: static int     connected;
                     81: static int     SentTerminalType = 0;           /* returned sb_terminal to other? */
                     82: static int     In3270 = 0;                     /* we are in 3270 binary mode */
                     83: static int     ISend = 0;                      /* trying to send network data in */
                     84: static int     ForceMode = -1;                 /* for debugging */
                     85: static int     net;
                     86: static int     showoptions = 0;
                     87: static int     debug = 0;
                     88: static int     crmod = 0;
                     89: static int     printnet = 0;
                     90: static FILE    *NetTrace;
                     91: static char    *prompt;
                     92: static char    escape = CTRL(]);
                     93: 
                     94: static char    line[200];
                     95: static int     margc;
                     96: static char    *margv[20];
                     97: 
                     98: static jmp_buf toplevel;
                     99: static jmp_buf peerdied;
                    100: 
                    101: extern int errno;
                    102: 
                    103: int    quit(), suspend();
                    104: static int     tn(), bye(), help();
                    105: static int     setescape(), status(), toggle(), setoptions();
                    106: static int     setcrmod(), setdebug(), SetPrintNet();
                    107: 
                    108: #define HELPINDENT (sizeof ("connect"))
                    109: 
                    110: struct cmd {
                    111:        char    *name;          /* command name */
                    112:        char    *help;          /* help string */
                    113:        int     (*handler)();   /* routine which executes command */
                    114:        int     dohelp;         /* Should we give general help information? */
                    115: };
                    116: 
                    117: static char    openhelp[] =    "connect to a site";
                    118: static char    closehelp[] =   "close current connection";
                    119: static char    quithelp[] =    "exit telnet";
                    120: static char    zhelp[] =       "suspend telnet";
                    121: static char    debughelp[] =   "toggle debugging";
                    122: static char    escapehelp[] =  "set escape character";
                    123: static char    statushelp[] =  "print status information";
                    124: static char    helphelp[] =    "print help information";
                    125: static char    optionshelp[] = "toggle viewing of options processing";
                    126: static char    crmodhelp[] =   "toggle mapping of received carriage returns";
                    127: static char    printnethelp[] = "print out raw data to/from net";
                    128: 
                    129: static struct cmd cmdtab[] = {
                    130:        { "open",       openhelp,       tn, 1 },
                    131:        { "close",      closehelp,      bye, 1 },
                    132:        { "quit",       quithelp,       quit, 1 },
                    133:        { "z",          zhelp,          suspend, 1 },
                    134:        { "suspend",    zhelp,          suspend, 0 },
                    135:        { "escape",     escapehelp,     setescape, 0 },
                    136:        { "status",     statushelp,     status, 1 },
                    137:        { "options",    optionshelp,    setoptions, 0 },
                    138:        { "crmod",      crmodhelp,      setcrmod, 0 },
                    139:        { "debug",      debughelp,      setdebug, 0 },
                    140:        { "printnet",   printnethelp,   SetPrintNet, 0 },
                    141:        { "?",          helphelp,       help, 1 },
                    142:        { "help",       helphelp,       help, 0 },
                    143:        0
                    144: };
                    145: 
                    146: static struct sockaddr_in sin;
                    147: 
                    148: static int     intr(), deadpeer(), inputAvailable();
                    149: static char    *control();
                    150: static struct  cmd *getcmd();
                    151: static struct  servent *sp;
                    152: 
                    153: static struct  tchars otc;
                    154: static struct  ltchars oltc;
                    155: static struct  sgttyb ottyb;
                    156: 
                    157: main(argc, argv)
                    158:        int argc;
                    159:        char *argv[];
                    160: {
                    161:        ioctl(0, TIOCGETP, (char *)&ottyb);
                    162:        ioctl(0, TIOCGETC, (char *)&otc);
                    163:        ioctl(0, TIOCGLTC, (char *)&oltc);
                    164:        sp = getservbyname("telnet", "tcp");
                    165:        if (sp == 0) {
                    166:                ExitString(stderr, "telnet: tcp/telnet: unknown service\n", 1);
                    167:        }
                    168:        NetTrace = stdout;
                    169:        prompt = argv[0];
                    170:        if (argc > 1 && !strcmp(argv[1], "-d")) {
                    171:                debug = SO_DEBUG, argv++, argc--;
                    172:        }
                    173:        if (argc > 1 && !strcmp(argv[1], "-n")) {
                    174:            argv++;
                    175:            argc--;
                    176:            if (argc > 1) {             /* get file name */
                    177:                NetTrace = fopen(argv[1], "w");
                    178:                argv++;
                    179:                argc--;
                    180:                if (NetTrace == NULL) {
                    181:                    NetTrace = stdout;
                    182:                }
                    183:            }
                    184:        }
                    185:        if (argc != 1) {
                    186:                if (setjmp(toplevel) != 0)
                    187:                        Exit(0);
                    188:                tn(argc, argv);
                    189:        }
                    190:        setjmp(toplevel);
                    191:        for (;;)
                    192:                command(1);
                    193: }
                    194: 
                    195: static char    *hostname;
                    196: static char    hnamebuf[32];
                    197: 
                    198: static
                    199: tn(argc, argv)
                    200:        int argc;
                    201:        char *argv[];
                    202: {
                    203:        register struct hostent *host;
                    204:        char *strcpy();
                    205: 
                    206:        if (connected) {
                    207:                printf("?Already connected to %s\n", hostname);
                    208:                return;
                    209:        }
                    210:        if (argc < 2) {
                    211:                (void) strcpy(line, "Connect ");
                    212:                printf("(to) ");
                    213:                gets(&line[strlen(line)]);
                    214:                makeargv();
                    215:                argc = margc;
                    216:                argv = margv;
                    217:        }
                    218:        if (argc > 3) {
                    219:                printf("usage: %s host-name [port]\n", argv[0]);
                    220:                return;
                    221:        }
                    222:        host = gethostbyname(argv[1]);
                    223:        if (host) {
                    224:                sin.sin_family = host->h_addrtype;
                    225:                bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length);
                    226:                hostname = host->h_name;
                    227:        } else {
                    228:                sin.sin_family = AF_INET;
                    229:                sin.sin_addr.s_addr = inet_addr(argv[1]);
                    230:                if (sin.sin_addr.s_addr == -1) {
                    231:                        printf("%s: unknown host\n", argv[1]);
                    232:                        return;
                    233:                }
                    234:                (void) strcpy(hnamebuf, argv[1]);
                    235:                hostname = hnamebuf;
                    236:        }
                    237:        sin.sin_port = sp->s_port;
                    238:        if (argc == 3) {
                    239:                sin.sin_port = atoi(argv[2]);
                    240:                sin.sin_port = htons(sin.sin_port);
                    241:        }
                    242:        net = socket(AF_INET, SOCK_STREAM, 0);
                    243:        if (net < 0) {
                    244:                perror("telnet: socket");
                    245:                return;
                    246:        }
                    247:        if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                    248:                perror("setsockopt (SO_DEBUG)");
                    249:        signal(SIGINT, intr);
                    250:        signal(SIGPIPE, deadpeer);
                    251:        printf("Trying...\n");
                    252:        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
                    253:                perror("telnet: connect");
                    254:                signal(SIGINT, SIG_DFL);
                    255:                return;
                    256:        }
                    257:        connected++;
                    258:        call(status, "status", 0);
                    259:        if (setjmp(peerdied) == 0)
                    260:                telnet();
                    261:        if (In3270) {
                    262:            Stop3270(1);
                    263:        }
                    264:        ExitString(stderr, "Connection closed by foreign host.\n", 1);
                    265: }
                    266: 
                    267: /*
                    268:  * Print status about the connection.
                    269:  */
                    270: /*VARARGS*/
                    271: static
                    272: status()
                    273: {
                    274:        if (connected)
                    275:                printf("Connected to %s.\n", hostname);
                    276:        else
                    277:                printf("No connection.\n");
                    278:        /*printf("Escape character is '%s'.\n", control(escape));*/
                    279:        fflush(stdout);
                    280: }
                    281: 
                    282: static
                    283: makeargv()
                    284: {
                    285:        register char *cp;
                    286:        register char **argp = margv;
                    287: 
                    288:        margc = 0;
                    289:        for (cp = line; *cp;) {
                    290:                while (isspace(*cp))
                    291:                        cp++;
                    292:                if (*cp == '\0')
                    293:                        break;
                    294:                *argp++ = cp;
                    295:                margc += 1;
                    296:                while (*cp != '\0' && !isspace(*cp))
                    297:                        cp++;
                    298:                if (*cp == '\0')
                    299:                        break;
                    300:                *cp++ = '\0';
                    301:        }
                    302:        *argp++ = 0;
                    303: }
                    304: 
                    305: /*VARARGS*/
                    306: suspend()
                    307: {
                    308:        register int save;
                    309: 
                    310:        save = mode(0);
                    311:        kill(0, SIGTSTP);
                    312:        /* reget parameters in case they were changed */
                    313:        ioctl(0, TIOCGETP, (char *)&ottyb);
                    314:        ioctl(0, TIOCGETC, (char *)&otc);
                    315:        ioctl(0, TIOCGLTC, (char *)&oltc);
                    316:        (void) mode(save);
                    317: }
                    318: 
                    319: /*VARARGS*/
                    320: static
                    321: bye()
                    322: {
                    323:        register char *op;
                    324: 
                    325:        (void) mode(0);
                    326:        if (connected) {
                    327:                shutdown(net, 2);
                    328:                printf("Connection closed.\n");
                    329:                close(net);
                    330:                connected = 0;
                    331:                /* reset his options */
                    332:                for (op = hisopts; op < &hisopts[256]; op++)
                    333:                        *op = 0;
                    334:        }
                    335: }
                    336: 
                    337: /*VARARGS*/
                    338: quit()
                    339: {
                    340:        call(bye, "bye", 0);
                    341:        Exit(0);
                    342: }
                    343: 
                    344: /*
                    345:  * Help command.
                    346:  */
                    347: static
                    348: help(argc, argv)
                    349:        int argc;
                    350:        char *argv[];
                    351: {
                    352:        register struct cmd *c;
                    353: 
                    354:        if (argc == 1) {
                    355:                printf("Commands may be abbreviated.  Commands are:\n\n");
                    356:                for (c = cmdtab; c->name; c++)
                    357:                        if (c->dohelp) {
                    358:                            printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
                    359:                        }
                    360:                return;
                    361:        }
                    362:        while (--argc > 0) {
                    363:                register char *arg;
                    364:                arg = *++argv;
                    365:                c = getcmd(arg);
                    366:                if (c == (struct cmd *)-1)
                    367:                        printf("?Ambiguous help command %s\n", arg);
                    368:                else if (c == (struct cmd *)0)
                    369:                        printf("?Invalid help command %s\n", arg);
                    370:                else
                    371:                        printf("%s\n", c->help);
                    372:        }
                    373: }
                    374: 
                    375: /*
                    376:  * Call routine with argc, argv set from args (terminated by 0).
                    377:  * VARARGS2
                    378:  */
                    379: static
                    380: call(routine, args)
                    381:        int (*routine)();
                    382:        int args;
                    383: {
                    384:        register int *argp;
                    385:        register int argc;
                    386: 
                    387:        for (argc = 0, argp = &args; *argp++ != 0; argc++)
                    388:                ;
                    389:        (*routine)(argc, &args);
                    390: }
                    391: 
                    392: static struct  tchars notc =   { -1, -1, -1, -1, -1, -1 };
                    393: static struct  ltchars noltc = { -1, -1, -1, -1, -1, -1 };
                    394: 
                    395: mode(f)
                    396:        register int f;
                    397: {
                    398:        static int prevmode = 0;
                    399:        struct tchars *tc, tc3;
                    400:        struct ltchars *ltc;
                    401:        struct sgttyb sb;
                    402:        int onoff, old;
                    403: 
                    404:        if (prevmode == f)
                    405:                return (f);
                    406:        old = prevmode;
                    407:        prevmode = f;
                    408:        sb = ottyb;
                    409:        if (ForceMode != -1) {
                    410:                f = ForceMode;
                    411:                ForceMode = -1;
                    412:        }
                    413:        switch (f) {
                    414: 
                    415:        case 0:
                    416:                onoff = 0;
                    417:                tc = &otc;
                    418:                ltc = &oltc;
                    419:                break;
                    420: 
                    421:        case 1:         /* the rawest */
                    422:        case 2:         /* allows for local echoing, newline mapping */
                    423:        case 3:         /* like 1, but with XON/XOFF */
                    424: 
                    425:                sb.sg_flags |= CBREAK;
                    426:                if ((f == 1) || (f == 3)) {
                    427:                    sb.sg_flags &= ~(ECHO|CRMOD);
                    428:                } else {
                    429:                    sb.sg_flags |= ECHO|CRMOD;
                    430:                }
                    431:                sb.sg_erase = sb.sg_kill = -1;
                    432:                if (f == 3) {
                    433:                    tc = &tc3;
                    434:                    tc3 = notc;
                    435:                        /* get XON, XOFF characters */
                    436:                    tc3.t_startc = otc.t_startc;
                    437:                    tc3.t_stopc = otc.t_stopc;
                    438:                } else {
                    439:                    tc = &notc;
                    440:                }
                    441:                ltc = &noltc;
                    442:                onoff = 1;
                    443:                break;
                    444: 
                    445:        default:
                    446:                return(old);
                    447:        }
                    448:        ioctl(fileno(stdin), TIOCSLTC, (char *)ltc);
                    449:        ioctl(fileno(stdin), TIOCSETC, (char *)tc);
                    450:        ioctl(fileno(stdin), TIOCSETP, (char *)&sb);
                    451:        ioctl(fileno(stdin), FIONBIO, (char *)&onoff);
                    452:        ioctl(fileno(stdout), FIONBIO, (char *)&onoff);
                    453:        ioctl(fileno(stdin), FIOASYNC, (char *)&onoff);
                    454:        return (old);
                    455: }
                    456: 
                    457: static char    sibuf[BUFSIZ], *sbp;
                    458: static char    tibuf[BUFSIZ], *tbp;
                    459: static int     scc, tcc;
                    460: static int tin, tout;                  /* file descriptors */
                    461: 
                    462: /*
                    463:  * Select from tty and network...
                    464:  */
                    465: static
                    466: telnet()
                    467: {
                    468:     int on = 1;
                    469:     int negativePid = -getpid();
                    470:     int schedValue;
                    471: 
                    472:     (void) mode(2);
                    473:     ioctl(net, FIONBIO, (char *)&on);
                    474:     ioctl(net, FIOASYNC, (char *)&on); /* hear about input */
                    475:     ioctl(net, SIOCSPGRP, (char *)&negativePid);       /* set my pid */
                    476:     tin = fileno(stdin);
                    477:     tout = fileno(stdout);
                    478: 
                    479:     for (;;) {
                    480:        while (schedValue = Scheduler(0)) {
                    481:            if (schedValue == -1) {
                    482:                (void) mode(0);
                    483:                return;
                    484:            }
                    485:        }
                    486:                /* If there is data waiting to go out to terminal, don't
                    487:                 * schedule any more data for the terminal.
                    488:                 */
                    489:        if (tfrontp-tbackp) {
                    490:            schedValue = 1;
                    491:        } else {
                    492:            schedValue = DoTerminalOutput();
                    493:        }
                    494:        if (schedValue) {
                    495:            if (Scheduler(1) == -1) {
                    496:                (void) mode(0);
                    497:                return;
                    498:            }
                    499:        }
                    500:     }
                    501: }
                    502: 
                    503: 
                    504: /* Loop around once. */
                    505: 
                    506: static
                    507: Scheduler(block)
                    508: int block;             /* should we block in the select? */
                    509: {
                    510:     register int c;
                    511:     int ibits = 0, obits = 0;
                    512:                /* One wants to be a bit careful about setting returnValue
                    513:                 * to one, since a one implies we did some useful work,
                    514:                 * and therefore probably won't be called to block next
                    515:                 * time.
                    516:                 */
                    517:     int returnValue = 0;
                    518:     static struct timeval TimeValue = {0};
                    519: 
                    520:     if (!In3270) {
                    521:        if (nfrontp - nbackp)
                    522:                obits |= (1 << net);
                    523:        else if (tcc == 0) {
                    524:                ibits |= (1 << tin);
                    525:        }
                    526:        if (tfrontp - tbackp)
                    527:                obits |= (1 << tout);
                    528:        else if (!ISend)
                    529:                ibits |= (1 << net);
                    530:     } else {
                    531:        if (nfrontp - nbackp) { /* something for network? */
                    532:            obits |= 1<<net;            /* yes - wait for space */
                    533:        }
                    534:        if (tcc == 0) {         /* any pending tty input? */
                    535:            ibits |= 1<<tin;    /* no, look for new input */
                    536:        }
                    537:        if (tfrontp-tbackp) {   /* any pending tty output? */
                    538:            obits |= 1<<tout;   /* yes - wait for space */
                    539:        }
                    540:        if (!ISend) {           /* any pending net input? */
                    541:            ibits |= 1<<net;            /* no, look for new input */
                    542:        }
                    543:     }
                    544:     if (scc < 0 && tcc < 0) {
                    545:            return(-1);
                    546:     }
                    547:     if (HaveInput) {           /* Reprime SIGIO handler if appropriate */
                    548:        HaveInput = 0;
                    549:        signal(SIGIO, inputAvailable);
                    550:     }
                    551:     select(16, &ibits, &obits, (int *) 0,
                    552:                                (block)? (struct timeval *)0:&TimeValue);
                    553:     if (ibits == 0 && obits == 0 && block) {
                    554:                    /* I don't like this, does it ever happen? */
                    555:            printf("sleep(5) from tn3270, after select\n");
                    556:            sleep(5);
                    557:            return(0);
                    558:     }
                    559: 
                    560:     /*
                    561:      * Something to read from the network...
                    562:      */
                    563:     if (ibits & (1 << net)) {
                    564:            scc = read(net, sibuf, sizeof (sibuf));
                    565:            if (scc < 0 && errno == EWOULDBLOCK)
                    566:                    scc = 0;
                    567:            else {
                    568:                    if (scc <= 0)
                    569:                            return(-1);
                    570:                    sbp = sibuf;
                    571:                    if (printnet) {
                    572:                            Dump('<', sbp, scc);
                    573:                    }
                    574:                    returnValue = 1;            /* did something usefull */
                    575:            }
                    576:     }
                    577: 
                    578:     /*
                    579:      * Something to read from the tty...
                    580:      */
                    581:     if (ibits & (1 << tin)) {
                    582:            tcc = read(tin, tibuf, sizeof tibuf);
                    583:            if (tcc < 0 && errno == EWOULDBLOCK)
                    584:                    tcc = 0;
                    585:            else {
                    586:                    if (tcc <= 0)
                    587:                            return(-1);
                    588:                    tbp = tibuf;
                    589:                    returnValue = 1;            /* did something usefull */
                    590:            }
                    591:     }
                    592: 
                    593:     if (tcc > 0) {
                    594:        if (In3270) {
                    595:            c = DataFromTerminal(tbp, tcc);
                    596:            if (c) {
                    597:                returnValue = 1;                /* did something usefull */
                    598:            }
                    599:            tcc -= c;
                    600:            tbp += c;
                    601:        } else {
                    602:            returnValue = 1;            /* did something usefull */
                    603:            while (tcc > 0) {
                    604:                if ((&netobuf[BUFSIZ] - nfrontp) < 2)
                    605:                        break;
                    606:                c = *tbp++ & 0377, tcc--;
                    607:                if (strip(c) == escape) {
                    608:                        command(0);
                    609:                        tcc = 0;
                    610:                        break;
                    611:                }
                    612:                if (c == IAC)
                    613:                        *nfrontp++ = c;
                    614:                *nfrontp++ = c;
                    615:            }
                    616:        }
                    617:     }
                    618:     if ((obits & (1 << net)) && (c = (int) (nfrontp - nbackp)) > 0) {
                    619:        netflush();
                    620:        if (c != (int) (nfrontp-nbackp)) {
                    621:            returnValue = 1;
                    622:        }
                    623:     }
                    624:     if (scc > 0) {
                    625:        if (Ifrontp+scc >= Ibuf+sizeof Ibuf) {
                    626:            if (Ibackp != Ibuf) {       /* do some copying */
                    627:                bcopy(Ibackp, Ibuf, Ifrontp-Ibackp);
                    628:                Ifrontp -= (Ibackp-Ibuf);
                    629:                Ibackp = Ibuf;
                    630:            }
                    631:        }
                    632:        if (Ifrontp+scc < Ibuf+sizeof Ibuf) {
                    633:            returnValue = 1;            /* doing something useful */
                    634:            telrcv();
                    635:        }               /* Else - we may never recover */
                    636:     }
                    637:     if ((obits & (1 << tout)) && (c = (int) (tfrontp - tbackp)) > 0) {
                    638:        ttyflush();
                    639:        if (c != (int) (tfrontp-tbackp)) {
                    640:            returnValue = 1;
                    641:        }
                    642:     }
                    643:     if (In3270 && (c = (int) (Ifrontp-Ibackp))) {
                    644:            Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, ISend);
                    645:            if (c != (int) (Ifrontp-Ibackp)) {
                    646:                returnValue = 1;
                    647:            }
                    648:            if (Ibackp == Ifrontp) {
                    649:                    Ibackp = Ifrontp = Ibuf;
                    650:                    ISend = 0;  /* take data from network */
                    651:            }
                    652:     }
                    653:     return(returnValue);                               /* good return */
                    654: }
                    655: 
                    656: command(top)
                    657:        int top;
                    658: {
                    659:        register struct cmd *c;
                    660:        int oldmode;
                    661: 
                    662:        oldmode = mode(0);
                    663:        if (!top)
                    664:                putchar('\n');
                    665:        else
                    666:                signal(SIGINT, SIG_DFL);
                    667:        for (;;) {
                    668:                printf("%s> ", prompt);
                    669:                if (gets(line) == 0) {
                    670:                        if (feof(stdin)) {
                    671:                                clearerr(stdin);
                    672:                                putchar('\n');
                    673:                        }
                    674:                        break;
                    675:                }
                    676:                if (line[0] == 0)
                    677:                        break;
                    678:                makeargv();
                    679:                c = getcmd(margv[0]);
                    680:                if (c == (struct cmd *)-1) {
                    681:                        printf("?Ambiguous command\n");
                    682:                        continue;
                    683:                }
                    684:                if (c == 0) {
                    685:                        printf("?Invalid command\n");
                    686:                        continue;
                    687:                }
                    688:                (*c->handler)(margc, margv);
                    689:                if (c->handler != help)
                    690:                        break;
                    691:        }
                    692:        if (!top) {
                    693:                if (!connected)
                    694:                        longjmp(toplevel, 1);
                    695:                (void) mode(oldmode);
                    696:        }
                    697: }
                    698: 
                    699: /*
                    700:  * Telnet receiver states for fsm
                    701:  */
                    702: #define        TS_DATA         0
                    703: #define        TS_IAC          1
                    704: #define        TS_WILL         2
                    705: #define        TS_WONT         3
                    706: #define        TS_DO           4
                    707: #define        TS_DONT         5
                    708: #define TS_SB          6       /* in sub-negotiation */
                    709: #define        TS_SE           7       /* coming out of sub-negotiation */
                    710: 
                    711: #define SB_ACCUM(c)    {*pSb = c;      /* accumulate character */ \
                    712:                        if (pSb >= SbBuffer+sizeof (SbBuffer)) { \
                    713:                                /* can't accept any more */ \
                    714:                                pSb = SbBuffer; \
                    715:                        } \
                    716:                        pSb++;}
                    717: 
                    718: static
                    719: telrcv()
                    720: {
                    721:        register int c;
                    722:        register char *Sbp;
                    723:        register int Scc;
                    724:        static int state = TS_DATA;
                    725: 
                    726:        while (scc > 0) {
                    727:                c = *sbp++ & 0377, scc--;
                    728:                switch (state) {
                    729: 
                    730:                case TS_DATA:
                    731:                        if (c == IAC) {
                    732:                            state = TS_IAC;
                    733:                            continue;
                    734:                        }
                    735:                                /* We optimize this loop, since it is
                    736:                                 * where we spend 99% of this routine.
                    737:                                 */
                    738:                        if (In3270) {
                    739:                            *Ifrontp++ = c;
                    740:                            Sbp = sbp;
                    741:                            Scc = scc;
                    742:                            while (Scc > 0) {
                    743:                                c = *Sbp++ & 0377, Scc--;
                    744:                                if (c == IAC) {
                    745:                                    state = TS_IAC;
                    746:                                    break;
                    747:                                }
                    748:                                *Ifrontp++ = c;
                    749:                            }
                    750:                            sbp = Sbp;
                    751:                            scc = Scc;
                    752:                        } else {
                    753:                            *tfrontp++ = c;
                    754:                            /*
                    755:                             * This hack is needed since we can't set
                    756:                             * CRMOD on output only.  Machines like MULTICS
                    757:                             * like to send \r without \n; since we must
                    758:                             * turn off CRMOD to get proper input, the mapping
                    759:                             * is done here (sigh).
                    760:                             */
                    761:                            if (c == '\r' && crmod && !In3270)
                    762:                                    *tfrontp++ = '\n';
                    763:                        }
                    764:                        continue;
                    765: 
                    766: 
                    767:                case TS_IAC:
                    768:                        switch (c) {
                    769:                        
                    770:                        case WILL:
                    771:                                state = TS_WILL;
                    772:                                continue;
                    773: 
                    774:                        case WONT:
                    775:                                state = TS_WONT;
                    776:                                continue;
                    777: 
                    778:                        case DO:
                    779:                                state = TS_DO;
                    780:                                continue;
                    781: 
                    782:                        case DONT:
                    783:                                state = TS_DONT;
                    784:                                continue;
                    785: 
                    786:                        case DM:
                    787:                                outputPurge();
                    788:                                break;
                    789: 
                    790:                        case NOP:
                    791:                        case GA:
                    792:                                break;
                    793: 
                    794:                        case SB:
                    795:                                state = TS_SB;
                    796:                                pSb = SbBuffer; /* where to collect */
                    797:                                continue;
                    798: 
                    799:                        case EOR:
                    800:                                if (In3270) {
                    801:                                    Ibackp += DataFromNetwork(Ibackp,
                    802:                                                Ifrontp-Ibackp, 1);
                    803:                                    if (Ibackp == Ifrontp) {
                    804:                                        Ibackp = Ifrontp = Ibuf;
                    805:                                        ISend = 0;      /* should have been! */
                    806:                                    } else {
                    807:                                        ISend = 1;
                    808:                                    }
                    809:                                }
                    810:                                break;
                    811: 
                    812:                        case IAC:
                    813:                                if (In3270) {
                    814:                                    *Ifrontp++ = IAC;
                    815:                                } else {
                    816:                                    *tfrontp++ = IAC;
                    817:                                }
                    818:                                break;
                    819: 
                    820:                        default:
                    821:                                break;
                    822:                        }
                    823:                        state = TS_DATA;
                    824:                        continue;
                    825: 
                    826:                case TS_WILL:
                    827:                        printoption("RCVD", will, c, !hisopts[c]);
                    828:                        if (!hisopts[c])
                    829:                                willoption(c);
                    830:                        state = TS_DATA;
                    831:                        continue;
                    832: 
                    833:                case TS_WONT:
                    834:                        printoption("RCVD", wont, c, hisopts[c]);
                    835:                        if (hisopts[c])
                    836:                                wontoption(c);
                    837:                        state = TS_DATA;
                    838:                        continue;
                    839: 
                    840:                case TS_DO:
                    841:                        printoption("RCVD", doopt, c, !myopts[c]);
                    842:                        if (!myopts[c])
                    843:                                dooption(c);
                    844:                        state = TS_DATA;
                    845:                        continue;
                    846: 
                    847:                case TS_DONT:
                    848:                        printoption("RCVD", dont, c, myopts[c]);
                    849:                        if (myopts[c]) {
                    850:                                myopts[c] = 0;
                    851:                                if (c == TELOPT_BINARY) {
                    852:                                    SetIn3270();
                    853:                                }
                    854:                                sprintf(nfrontp, wont, c);
                    855:                                nfrontp += sizeof (wont) - 2;
                    856:                                printoption("SENT", wont, c);
                    857:                        }
                    858:                        state = TS_DATA;
                    859:                        continue;
                    860:                case TS_SB:
                    861:                        if (c == IAC) {
                    862:                                state = TS_SE;
                    863:                                continue;
                    864:                        }
                    865:                        SB_ACCUM(c);
                    866:                        continue;
                    867:                case TS_SE:
                    868:                    if (c != SE) {
                    869:                        if (c != IAC) {
                    870:                            SB_ACCUM(IAC);
                    871:                        }
                    872:                        SB_ACCUM(c);
                    873:                        state = TS_SB;
                    874:                    } else {
                    875:                        /* this is the end of the sub negotiation */
                    876:                        /* we only allow a termtype, send, sub */
                    877:                        if ((Sb_Option != TELOPT_TTYPE) ||
                    878:                                (Sb_Command != TELQUAL_SEND)) {
                    879:                            /* what to do? XXX */
                    880:                        } else {
                    881:                            /* send our type */
                    882:                            SentTerminalType = 1;
                    883:                            SetIn3270();
                    884:                            bcopy(sb_terminal, nfrontp, sizeof sb_terminal);
                    885:                            nfrontp += sizeof sb_terminal;
                    886:                            printoption("SENT", sb_terminal,
                    887:                                        TELOPT_TTYPE);
                    888:                        }
                    889:                        state = TS_DATA;
                    890:                    }
                    891:                }
                    892:        }
                    893: }
                    894: 
                    895: static
                    896: willoption(option)
                    897:        int option;
                    898: {
                    899:        char *fmt;
                    900: 
                    901:        switch (option) {
                    902: 
                    903:        case TELOPT_ECHO:
                    904:                (void) mode(1);
                    905: 
                    906:        case TELOPT_BINARY:
                    907:                hisopts[option] = 1;
                    908:                SetIn3270();
                    909:                fmt = doopt;
                    910:                break;
                    911: 
                    912:        case TELOPT_EOR:
                    913:        case TELOPT_SGA:
                    914:                hisopts[option] = 1;
                    915:                fmt = doopt;
                    916:                break;
                    917: 
                    918:        case TELOPT_TM:
                    919:                fmt = dont;
                    920:                break;
                    921: 
                    922:        default:
                    923:                fmt = dont;
                    924:                break;
                    925:        }
                    926:        sprintf(nfrontp, fmt, option);
                    927:        nfrontp += sizeof (dont) - 2;
                    928:        printoption("SENT", fmt, option);
                    929: }
                    930: 
                    931: static
                    932: wontoption(option)
                    933:        int option;
                    934: {
                    935:        char *fmt;
                    936: 
                    937:        switch (option) {
                    938: 
                    939:        case TELOPT_BINARY:
                    940:                hisopts[option] = 0;
                    941:                SetIn3270();
                    942:                fmt = doopt;
                    943:                break;
                    944: 
                    945:        case TELOPT_ECHO:
                    946:                (void) mode(2);
                    947: 
                    948:        case TELOPT_SGA:
                    949:                hisopts[option] = 0;
                    950:                fmt = dont;
                    951:                break;
                    952: 
                    953:        default:
                    954:                fmt = dont;
                    955:        }
                    956:        sprintf(nfrontp, fmt, option);
                    957:        nfrontp += sizeof (doopt) - 2;
                    958:        printoption("SENT", fmt, option);
                    959: }
                    960: 
                    961: static
                    962: dooption(option)
                    963:        int option;
                    964: {
                    965:        char *fmt;
                    966: 
                    967:        switch (option) {
                    968: 
                    969:        case TELOPT_TTYPE:
                    970:        case TELOPT_BINARY:
                    971:                myopts[option] = 1;
                    972:                SetIn3270();
                    973:                fmt = will;
                    974:                break;
                    975: 
                    976:        case TELOPT_TM:
                    977:                fmt = wont;
                    978:                break;
                    979: 
                    980:        case TELOPT_ECHO:
                    981:                (void) mode(2);
                    982:                fmt = will;
                    983:                hisopts[option] = 0;
                    984:                break;
                    985: 
                    986:        case TELOPT_EOR:
                    987:        case TELOPT_SGA:
                    988:                fmt = will;
                    989:                break;
                    990: 
                    991:        default:
                    992:                fmt = wont;
                    993:                break;
                    994:        }
                    995:        sprintf(nfrontp, fmt, option);
                    996:        nfrontp += (sizeof dont)-2;
                    997:        printoption("SENT", fmt, option);
                    998: }
                    999: 
                   1000: static
                   1001: SetIn3270()
                   1002: {
                   1003:     if (SentTerminalType && myopts[TELOPT_BINARY] && hisopts[TELOPT_BINARY]) {
                   1004:        if (!In3270) {
                   1005:            In3270 = 1;
                   1006:            OptInit();          /* initialize mappings */
                   1007:            /* initialize terminal key mapping */
                   1008:            (void) DataFromTerminal(ttyobuf, 0);
                   1009:            (void) mode(3);
                   1010:        }
                   1011:     } else {
                   1012:        if (In3270) {
                   1013:            Stop3270(1);
                   1014:            In3270 = 0;
                   1015:            (void) mode(2);
                   1016:        }
                   1017:     }
                   1018: }
                   1019: 
                   1020: /*
                   1021:  * Set the escape character.
                   1022:  */
                   1023: static
                   1024: setescape(argc, argv)
                   1025:        int argc;
                   1026:        char *argv[];
                   1027: {
                   1028:        register char *arg;
                   1029:        char buf[50];
                   1030: 
                   1031:        if (argc > 2)
                   1032:                arg = argv[1];
                   1033:        else {
                   1034:                printf("new escape character: ");
                   1035:                gets(buf);
                   1036:                arg = buf;
                   1037:        }
                   1038:        if (arg[0] != '\0')
                   1039:                escape = arg[0];
                   1040:        printf("Escape character is '%s'.\n", control(escape));
                   1041:        fflush(stdout);
                   1042: }
                   1043: 
                   1044: /*VARARGS*/
                   1045: static
                   1046: setoptions()
                   1047: {
                   1048: 
                   1049:        showoptions = !showoptions;
                   1050:        printf("%s show option processing.\n", showoptions ? "Will" : "Wont");
                   1051:        fflush(stdout);
                   1052: }
                   1053: 
                   1054: /*VARARGS*/
                   1055: static
                   1056: setcrmod()
                   1057: {
                   1058: 
                   1059:        crmod = !crmod;
                   1060:        printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont");
                   1061:        fflush(stdout);
                   1062: }
                   1063: 
                   1064: /*VARARGS*/
                   1065: static
                   1066: setdebug()
                   1067: {
                   1068: 
                   1069:        debug = !debug;
                   1070:        printf("%s turn on socket level debugging.\n",
                   1071:                debug ? "Will" : "Wont");
                   1072:        fflush(stdout);
                   1073:        if (debug && net > 0 && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                   1074:                perror("setsockopt (SO_DEBUG)");
                   1075: }
                   1076: 
                   1077: /*VARARGS*/
                   1078: static
                   1079: SetPrintNet()
                   1080: {
                   1081: 
                   1082:        printnet = !printnet;
                   1083:        printf("%s turn on printing of raw network traffic.\n",
                   1084:                printnet ? "Will" : "Wont");
                   1085: }
                   1086: 
                   1087: /*
                   1088:  * Construct a control character sequence
                   1089:  * for a special character.
                   1090:  */
                   1091: static char *
                   1092: control(c)
                   1093:        register int c;
                   1094: {
                   1095:        static char buf[3];
                   1096: 
                   1097:        if (c == 0177)
                   1098:                return ("^?");
                   1099:        if (c >= 040) {
                   1100:                buf[0] = c;
                   1101:                buf[1] = 0;
                   1102:        } else {
                   1103:                buf[0] = '^';
                   1104:                buf[1] = '@'+c;
                   1105:                buf[2] = 0;
                   1106:        }
                   1107:        return (buf);
                   1108: }
                   1109: 
                   1110: static struct cmd *
                   1111: getcmd(name)
                   1112:        register char *name;
                   1113: {
                   1114:        register char *p, *q;
                   1115:        register struct cmd *c, *found;
                   1116:        register int nmatches, longest;
                   1117: 
                   1118:        longest = 0;
                   1119:        nmatches = 0;
                   1120:        found = 0;
                   1121:        for (c = cmdtab; p = c->name; c++) {
                   1122:                for (q = name; *q == *p++; q++)
                   1123:                        if (*q == 0)            /* exact match? */
                   1124:                                return (c);
                   1125:                if (!*q) {                      /* the name was a prefix */
                   1126:                        if (q - name > longest) {
                   1127:                                longest = q - name;
                   1128:                                nmatches = 1;
                   1129:                                found = c;
                   1130:                        } else if (q - name == longest)
                   1131:                                nmatches++;
                   1132:                }
                   1133:        }
                   1134:        if (nmatches > 1)
                   1135:                return ((struct cmd *)-1);
                   1136:        return (found);
                   1137: }
                   1138: 
                   1139: static
                   1140: deadpeer()
                   1141: {
                   1142:        (void) mode(0);
                   1143:        longjmp(peerdied, -1);
                   1144: }
                   1145: 
                   1146: static
                   1147: intr()
                   1148: {
                   1149:        (void) mode(0);
                   1150:        longjmp(toplevel, -1);
                   1151: }
                   1152: 
                   1153: static
                   1154: inputAvailable()
                   1155: {
                   1156:     HaveInput = 1;
                   1157: }
                   1158: 
                   1159: /* outputPurge() - get rid of all output destined for terminal. */
                   1160: outputPurge()
                   1161: {
                   1162:     ioctl(fileno(stdout), TIOCFLUSH, (char *)0);
                   1163:     tbackp = tfrontp = ttyobuf;
                   1164: }
                   1165: 
                   1166: ttyflush()
                   1167: {
                   1168:        int n;
                   1169: 
                   1170:        if ((n = tfrontp - tbackp) > 0)
                   1171:                n = write(tout, tbackp, n);
                   1172:        if (n < 0)
                   1173:                return;
                   1174:        tbackp += n;
                   1175:        if (tbackp == tfrontp)
                   1176:                tbackp = tfrontp = ttyobuf;
                   1177: }
                   1178: 
                   1179: /* TtyChars() - returns the number of characters in the TTY buffer */
                   1180: TtyChars()
                   1181: {
                   1182:     return(tfrontp-tbackp);
                   1183: }
                   1184: 
                   1185: netflush()
                   1186: {
                   1187:        int n;
                   1188: 
                   1189:        if ((n = nfrontp - nbackp) > 0)
                   1190:                n = write(net, nbackp, n);
                   1191:        if (n < 0) {
                   1192:                if (errno != ENOBUFS && errno != EWOULDBLOCK) {
                   1193:                        (void) mode(0);
                   1194:                        perror(hostname);
                   1195:                        close(net);
                   1196:                        longjmp(peerdied, -1);
                   1197:                        /*NOTREACHED*/
                   1198:                }
                   1199:                n = 0;
                   1200:        }
                   1201:        if (printnet) {
                   1202:                Dump('>', nbackp, n);
                   1203:        }
                   1204:        nbackp += n;
                   1205:        if (nbackp == nfrontp)
                   1206:                nbackp = nfrontp = netobuf;
                   1207: }
                   1208: 
                   1209: /* DataToNetwork - queue up some data to go to network.  When last byte is
                   1210:     queued, we add on an IAC EOR sequence (so, don't call us until you
                   1211:     want that done...)
                   1212:  */
                   1213: 
                   1214: int
                   1215: DataToNetwork(buffer, count)
                   1216: register char  *buffer;                /* where the data is */
                   1217: register int   count;                  /* how much to send */
                   1218: {
                   1219:     register int c;
                   1220:     int origCount;
                   1221: 
                   1222:     origCount = count;
                   1223: 
                   1224:     while (count) {
                   1225:        if ((&netobuf[sizeof netobuf] - nfrontp) < 6) {
                   1226:            netflush();
                   1227:            if ((&netobuf[sizeof netobuf] - nfrontp) < 6) {
                   1228:                break;
                   1229:            }
                   1230:        }
                   1231:        c = *buffer++;
                   1232:        count--;
                   1233:        if (c == IAC) {
                   1234:            *nfrontp++ = IAC;
                   1235:            *nfrontp++ = IAC;
                   1236:        } else {
                   1237:            *nfrontp++ = c;
                   1238:        }
                   1239:     }
                   1240: 
                   1241:     if (!count) {
                   1242:        *nfrontp++ = IAC;
                   1243:        *nfrontp++ = EOR;
                   1244:        netflush();             /* try to move along as quickly as ... */
                   1245:     }
                   1246:     return(origCount - count);
                   1247: }
                   1248: 
                   1249: /* DataToTerminal - queue up some data to go to terminal. */
                   1250: 
                   1251: int
                   1252: DataToTerminal(buffer, count)
                   1253: register char  *buffer;                /* where the data is */
                   1254: register int   count;                  /* how much to send */
                   1255: {
                   1256:     int origCount;
                   1257:     int o;
                   1258: 
                   1259:     origCount = count;
                   1260: 
                   1261:     while (count) {
                   1262:        if (tfrontp >= &ttyobuf[sizeof ttyobuf]) {
                   1263:            ttyflush();
                   1264:            while (tfrontp >= &ttyobuf[sizeof ttyobuf]) {
                   1265:                o = 1<<tout;
                   1266:                (void) select(tout+1, (int *) 0, &o, (int *) 0,
                   1267:                                                (struct timeval *) 0);
                   1268:                ttyflush();
                   1269:            }
                   1270:        }
                   1271:        *tfrontp++ = *buffer++;
                   1272:        count--;
                   1273:     }
                   1274:     return(origCount - count);
                   1275: }
                   1276: 
                   1277: /* EmptyTerminal - called to make sure that the terminal buffer is empty.
                   1278:  *                     Note that we consider the buffer to run all the
                   1279:  *                     way to the kernel (thus the select).
                   1280:  */
                   1281: 
                   1282: void
                   1283: EmptyTerminal()
                   1284: {
                   1285:     int o;
                   1286: 
                   1287:     o = 1<<tout;
                   1288: 
                   1289:     if (tfrontp == tbackp) {
                   1290:        (void) select(tout+1, (int *) 0, &o, (int *) 0,
                   1291:                        (struct timeval *) 0);  /* wait for TTLOWAT */
                   1292:     } else {
                   1293:        while (tfrontp != tbackp) {
                   1294:            ttyflush();
                   1295:            (void) select(tout+1, (int *) 0, &o, (int *) 0,
                   1296:                                (struct timeval *) 0);  /* wait for TTLOWAT */
                   1297:        }
                   1298:     }
                   1299: }
                   1300: 
                   1301: 
                   1302: 
                   1303: /* StringToTerminal - output a null terminated string to the terminal */
                   1304: 
                   1305: int
                   1306: StringToTerminal(s)
                   1307: char *s;
                   1308: {
                   1309:     int count;
                   1310: 
                   1311:     count = strlen(s);
                   1312:     if (count) {
                   1313:        (void) DataToTerminal(s, count);        /* we know it always goes... */
                   1314:     }
                   1315: }
                   1316: 
                   1317: 
                   1318: /* _putchar - output a single character to the terminal.  This name is so that
                   1319:  *     curses(3x) can call us to send out data.
                   1320:  */
                   1321: 
                   1322: _putchar(c)
                   1323: char c;
                   1324: {
                   1325:     if (tfrontp >= &ttyobuf[sizeof ttyobuf]) {
                   1326:        (void) DataToTerminal(&c, 1);
                   1327:     } else {
                   1328:        *tfrontp++ = c;         /* optimize if possible. */
                   1329:     }
                   1330: }
                   1331: 
                   1332: static
                   1333: SetForExit()
                   1334: {
                   1335:     (void) mode(2);                    /* switch modes to flush output */
                   1336:     (void) mode(0);
                   1337:     fflush(stdout);
                   1338:     fflush(stderr);
                   1339:     if (In3270) {
                   1340:        Stop3270(0);
                   1341:     }
                   1342:     (void) mode(2);                    /* make sure we go back to mode 0 */
                   1343:     (void) mode(0);
                   1344: }
                   1345: 
                   1346: static
                   1347: Exit(returnCode)
                   1348: int returnCode;
                   1349: {
                   1350:     SetForExit();
                   1351:     exit(returnCode);
                   1352: }
                   1353: 
                   1354: ExitString(file, string, returnCode)
                   1355: FILE *file;
                   1356: char *string;
                   1357: int returnCode;
                   1358: {
                   1359:     SetForExit();
                   1360:     fwrite(string, 1, strlen(string), file);
                   1361:     exit(returnCode);
                   1362: }
                   1363: 
                   1364: ExitPerror(string, returnCode)
                   1365: char *string;
                   1366: int returnCode;
                   1367: {
                   1368:     SetForExit();
                   1369:     perror(string);
                   1370:     exit(returnCode);
                   1371: }
                   1372: 
                   1373: 
                   1374: static
                   1375: Dump(direction, buffer, length)
                   1376: char   direction;
                   1377: char   *buffer;
                   1378: int    length;
                   1379: {
                   1380: #   define BYTES_PER_LINE      32
                   1381:     char *pThis;
                   1382:     int offset;
                   1383: 
                   1384:     offset = 0;
                   1385: 
                   1386:     while (length) {
                   1387:        /* print one line */
                   1388:        fprintf(NetTrace, "%c 0x%x\t", direction, offset);
                   1389:        pThis = buffer;
                   1390:        buffer = buffer+min(length, BYTES_PER_LINE);
                   1391:        while (pThis < buffer) {
                   1392:            fprintf(NetTrace, "%.2x", (*pThis)&0xff);
                   1393:            pThis++;
                   1394:        }
                   1395:        fprintf(NetTrace, "\n");
                   1396:        length -= BYTES_PER_LINE;
                   1397:        offset += BYTES_PER_LINE;
                   1398:        if (length < 0) {
                   1399:            return;
                   1400:        }
                   1401:        /* find next unique line */
                   1402:     }
                   1403: }
                   1404: 
                   1405: 
                   1406: 
                   1407: /*VARARGS*/
                   1408: static
                   1409: printoption(direction, fmt, option, what)
                   1410:        char *direction, *fmt;
                   1411:        int option, what;
                   1412: {
                   1413:        if (!showoptions)
                   1414:                return;
                   1415:        printf("%s ", direction);
                   1416:        if (fmt == doopt)
                   1417:                fmt = "do";
                   1418:        else if (fmt == dont)
                   1419:                fmt = "dont";
                   1420:        else if (fmt == will)
                   1421:                fmt = "will";
                   1422:        else if (fmt == wont)
                   1423:                fmt = "wont";
                   1424:        else if (fmt == sb_terminal)
                   1425:                fmt = "will (terminal)";
                   1426:        else
                   1427:                fmt = "???";
                   1428:        if (option < TELOPT_SUPDUP)
                   1429:                printf("%s %s", fmt, telopts[option]);
                   1430:        else
                   1431:                printf("%s %d", fmt, option);
                   1432:        if (*direction == '<') {
                   1433:                printf("\r\n");
                   1434:                return;
                   1435:        }
                   1436:        printf(" (%s)\r\n", what ? "reply" : "don't reply");
                   1437: }

unix.superglobalmegacorp.com

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