Annotation of 43BSDTahoe/ucb/telnet/Source/commands.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: static char sccsid[] = "@(#)commands.c 1.5 (Berkeley) 5/15/88";
        !            15: #endif /* not lint */
        !            16: 
        !            17: #include <sys/types.h>
        !            18: #include <sys/socket.h>
        !            19: #include <netinet/in.h>
        !            20: 
        !            21: #include <signal.h>
        !            22: #include <netdb.h>
        !            23: #include <ctype.h>
        !            24: 
        !            25: #include <arpa/telnet.h>
        !            26: 
        !            27: #include "general.h"
        !            28: 
        !            29: #include "ring.h"
        !            30: 
        !            31: #include "externs.h"
        !            32: #include "defines.h"
        !            33: #include "types.h"
        !            34: 
        !            35: char   *hostname;
        !            36: 
        !            37: #define Ambiguous(s)   ((char *)s == ambiguous)
        !            38: static char *ambiguous;                /* special return value for command routines */
        !            39: 
        !            40: typedef struct {
        !            41:        char    *name;          /* command name */
        !            42:        char    *help;          /* help string */
        !            43:        int     (*handler)();   /* routine which executes command */
        !            44:        int     dohelp;         /* Should we give general help information? */
        !            45:        int     needconnect;    /* Do we need to be connected to execute? */
        !            46: } Command;
        !            47: 
        !            48: static char line[200];
        !            49: static int margc;
        !            50: static char *margv[20];
        !            51: 
        !            52: /*
        !            53:  * Various utility routines.
        !            54:  */
        !            55: 
        !            56: static void
        !            57: makeargv()
        !            58: {
        !            59:     register char *cp;
        !            60:     register char **argp = margv;
        !            61: 
        !            62:     margc = 0;
        !            63:     cp = line;
        !            64:     if (*cp == '!') {          /* Special case shell escape */
        !            65:        *argp++ = "!";          /* No room in string to get this */
        !            66:        margc++;
        !            67:        cp++;
        !            68:     }
        !            69:     while (*cp) {
        !            70:        while (isspace(*cp))
        !            71:            cp++;
        !            72:        if (*cp == '\0')
        !            73:            break;
        !            74:        *argp++ = cp;
        !            75:        margc += 1;
        !            76:        while (*cp != '\0' && !isspace(*cp))
        !            77:            cp++;
        !            78:        if (*cp == '\0')
        !            79:            break;
        !            80:        *cp++ = '\0';
        !            81:     }
        !            82:     *argp++ = 0;
        !            83: }
        !            84: 
        !            85: 
        !            86: static char **
        !            87: genget(name, table, next)
        !            88: char   *name;          /* name to match */
        !            89: char   **table;                /* name entry in table */
        !            90: char   **(*next)();    /* routine to return next entry in table */
        !            91: {
        !            92:        register char *p, *q;
        !            93:        register char **c, **found;
        !            94:        register int nmatches, longest;
        !            95: 
        !            96:        if (name == 0) {
        !            97:            return 0;
        !            98:        }
        !            99:        longest = 0;
        !           100:        nmatches = 0;
        !           101:        found = 0;
        !           102:        for (c = table; (p = *c) != 0; c = (*next)(c)) {
        !           103:                for (q = name;
        !           104:                    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
        !           105:                        if (*q == 0)            /* exact match? */
        !           106:                                return (c);
        !           107:                if (!*q) {                      /* the name was a prefix */
        !           108:                        if (q - name > longest) {
        !           109:                                longest = q - name;
        !           110:                                nmatches = 1;
        !           111:                                found = c;
        !           112:                        } else if (q - name == longest)
        !           113:                                nmatches++;
        !           114:                }
        !           115:        }
        !           116:        if (nmatches > 1)
        !           117:                return (char **)ambiguous;
        !           118:        return (found);
        !           119: }
        !           120: 
        !           121: /*
        !           122:  * Make a character string into a number.
        !           123:  *
        !           124:  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
        !           125:  */
        !           126: 
        !           127: static
        !           128: special(s)
        !           129: register char *s;
        !           130: {
        !           131:        register char c;
        !           132:        char b;
        !           133: 
        !           134:        switch (*s) {
        !           135:        case '^':
        !           136:                b = *++s;
        !           137:                if (b == '?') {
        !           138:                    c = b | 0x40;               /* DEL */
        !           139:                } else {
        !           140:                    c = b & 0x1f;
        !           141:                }
        !           142:                break;
        !           143:        default:
        !           144:                c = *s;
        !           145:                break;
        !           146:        }
        !           147:        return c;
        !           148: }
        !           149: 
        !           150: /*
        !           151:  * Construct a control character sequence
        !           152:  * for a special character.
        !           153:  */
        !           154: static char *
        !           155: control(c)
        !           156:        register int c;
        !           157: {
        !           158:        static char buf[3];
        !           159: 
        !           160:        if (c == 0x7f)
        !           161:                return ("^?");
        !           162:        if (c == '\377') {
        !           163:                return "off";
        !           164:        }
        !           165:        if (c >= 0x20) {
        !           166:                buf[0] = c;
        !           167:                buf[1] = 0;
        !           168:        } else {
        !           169:                buf[0] = '^';
        !           170:                buf[1] = '@'+c;
        !           171:                buf[2] = 0;
        !           172:        }
        !           173:        return (buf);
        !           174: }
        !           175: 
        !           176: 
        !           177: 
        !           178: /*
        !           179:  *     The following are data structures and routines for
        !           180:  *     the "send" command.
        !           181:  *
        !           182:  */
        !           183:  
        !           184: struct sendlist {
        !           185:     char       *name;          /* How user refers to it (case independent) */
        !           186:     int                what;           /* Character to be sent (<0 ==> special) */
        !           187:     char       *help;          /* Help information (0 ==> no help) */
        !           188: #if    defined(NOT43)
        !           189:     int                (*routine)();   /* Routine to perform (for special ops) */
        !           190: #else  /* defined(NOT43) */
        !           191:     void       (*routine)();   /* Routine to perform (for special ops) */
        !           192: #endif /* defined(NOT43) */
        !           193: };
        !           194: 
        !           195: #define        SENDQUESTION    -1
        !           196: #define        SENDESCAPE      -3
        !           197: 
        !           198: static struct sendlist Sendlist[] = {
        !           199:     { "ao", AO, "Send Telnet Abort output" },
        !           200:     { "ayt", AYT, "Send Telnet 'Are You There'" },
        !           201:     { "brk", BREAK, "Send Telnet Break" },
        !           202:     { "ec", EC, "Send Telnet Erase Character" },
        !           203:     { "el", EL, "Send Telnet Erase Line" },
        !           204:     { "escape", SENDESCAPE, "Send current escape character" },
        !           205:     { "ga", GA, "Send Telnet 'Go Ahead' sequence" },
        !           206:     { "ip", IP, "Send Telnet Interrupt Process" },
        !           207:     { "nop", NOP, "Send Telnet 'No operation'" },
        !           208:     { "synch", SYNCH, "Perform Telnet 'Synch operation'", dosynch },
        !           209:     { "?", SENDQUESTION, "Display send options" },
        !           210:     { 0 }
        !           211: };
        !           212: 
        !           213: static struct sendlist Sendlist2[] = {         /* some synonyms */
        !           214:        { "break", BREAK, 0 },
        !           215: 
        !           216:        { "intp", IP, 0 },
        !           217:        { "interrupt", IP, 0 },
        !           218:        { "intr", IP, 0 },
        !           219: 
        !           220:        { "help", SENDQUESTION, 0 },
        !           221: 
        !           222:        { 0 }
        !           223: };
        !           224: 
        !           225: static char **
        !           226: getnextsend(name)
        !           227: char *name;
        !           228: {
        !           229:     struct sendlist *c = (struct sendlist *) name;
        !           230: 
        !           231:     return (char **) (c+1);
        !           232: }
        !           233: 
        !           234: static struct sendlist *
        !           235: getsend(name)
        !           236: char *name;
        !           237: {
        !           238:     struct sendlist *sl;
        !           239: 
        !           240:     if ((sl = (struct sendlist *)
        !           241:                        genget(name, (char **) Sendlist, getnextsend)) != 0) {
        !           242:        return sl;
        !           243:     } else {
        !           244:        return (struct sendlist *)
        !           245:                                genget(name, (char **) Sendlist2, getnextsend);
        !           246:     }
        !           247: }
        !           248: 
        !           249: static
        !           250: sendcmd(argc, argv)
        !           251: int    argc;
        !           252: char   **argv;
        !           253: {
        !           254:     int what;          /* what we are sending this time */
        !           255:     int count;         /* how many bytes we are going to need to send */
        !           256:     int i;
        !           257:     int question = 0;  /* was at least one argument a question */
        !           258:     struct sendlist *s;        /* pointer to current command */
        !           259: 
        !           260:     if (argc < 2) {
        !           261:        printf("need at least one argument for 'send' command\n");
        !           262:        printf("'send ?' for help\n");
        !           263:        return 0;
        !           264:     }
        !           265:     /*
        !           266:      * First, validate all the send arguments.
        !           267:      * In addition, we see how much space we are going to need, and
        !           268:      * whether or not we will be doing a "SYNCH" operation (which
        !           269:      * flushes the network queue).
        !           270:      */
        !           271:     count = 0;
        !           272:     for (i = 1; i < argc; i++) {
        !           273:        s = getsend(argv[i]);
        !           274:        if (s == 0) {
        !           275:            printf("Unknown send argument '%s'\n'send ?' for help.\n",
        !           276:                        argv[i]);
        !           277:            return 0;
        !           278:        } else if (Ambiguous(s)) {
        !           279:            printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
        !           280:                        argv[i]);
        !           281:            return 0;
        !           282:        }
        !           283:        switch (s->what) {
        !           284:        case SENDQUESTION:
        !           285:            break;
        !           286:        case SENDESCAPE:
        !           287:            count += 1;
        !           288:            break;
        !           289:        case SYNCH:
        !           290:            count += 2;
        !           291:            break;
        !           292:        default:
        !           293:            count += 2;
        !           294:            break;
        !           295:        }
        !           296:     }
        !           297:     /* Now, do we have enough room? */
        !           298:     if (NETROOM() < count) {
        !           299:        printf("There is not enough room in the buffer TO the network\n");
        !           300:        printf("to process your request.  Nothing will be done.\n");
        !           301:        printf("('send synch' will throw away most data in the network\n");
        !           302:        printf("buffer, if this might help.)\n");
        !           303:        return 0;
        !           304:     }
        !           305:     /* OK, they are all OK, now go through again and actually send */
        !           306:     for (i = 1; i < argc; i++) {
        !           307:        if ((s = getsend(argv[i])) == 0) {
        !           308:            fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
        !           309:            quit();
        !           310:            /*NOTREACHED*/
        !           311:        }
        !           312:        if (s->routine) {
        !           313:            (*s->routine)(s);
        !           314:        } else {
        !           315:            switch (what = s->what) {
        !           316:            case SYNCH:
        !           317:                dosynch();
        !           318:                break;
        !           319:            case SENDQUESTION:
        !           320:                for (s = Sendlist; s->name; s++) {
        !           321:                    if (s->help) {
        !           322:                        printf(s->name);
        !           323:                        if (s->help) {
        !           324:                            printf("\t%s", s->help);
        !           325:                        }
        !           326:                        printf("\n");
        !           327:                    }
        !           328:                }
        !           329:                question = 1;
        !           330:                break;
        !           331:            case SENDESCAPE:
        !           332:                NETADD(escape);
        !           333:                break;
        !           334:            default:
        !           335:                NET2ADD(IAC, what);
        !           336:                break;
        !           337:            }
        !           338:        }
        !           339:     }
        !           340:     return !question;
        !           341: }
        !           342: 
        !           343: /*
        !           344:  * The following are the routines and data structures referred
        !           345:  * to by the arguments to the "toggle" command.
        !           346:  */
        !           347: 
        !           348: static
        !           349: lclchars()
        !           350: {
        !           351:     donelclchars = 1;
        !           352:     return 1;
        !           353: }
        !           354: 
        !           355: static
        !           356: togdebug()
        !           357: {
        !           358: #ifndef        NOT43
        !           359:     if (net > 0 &&
        !           360:        (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
        !           361:            perror("setsockopt (SO_DEBUG)");
        !           362:     }
        !           363: #else  /* NOT43 */
        !           364:     if (debug) {
        !           365:        if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
        !           366:            perror("setsockopt (SO_DEBUG)");
        !           367:     } else
        !           368:        printf("Cannot turn off socket debugging\n");
        !           369: #endif /* NOT43 */
        !           370:     return 1;
        !           371: }
        !           372: 
        !           373: 
        !           374: static int
        !           375: togcrlf()
        !           376: {
        !           377:     if (crlf) {
        !           378:        printf("Will send carriage returns as telnet <CR><LF>.\n");
        !           379:     } else {
        !           380:        printf("Will send carriage returns as telnet <CR><NUL>.\n");
        !           381:     }
        !           382:     return 1;
        !           383: }
        !           384: 
        !           385: 
        !           386: static int
        !           387: togbinary()
        !           388: {
        !           389:     donebinarytoggle = 1;
        !           390: 
        !           391:     if (myopts[TELOPT_BINARY] == 0) {  /* Go into binary mode */
        !           392:        NET2ADD(IAC, DO);
        !           393:        NETADD(TELOPT_BINARY);
        !           394:        printoption("<SENT", doopt, TELOPT_BINARY, 0);
        !           395:        NET2ADD(IAC, WILL);
        !           396:        NETADD(TELOPT_BINARY);
        !           397:        printoption("<SENT", doopt, TELOPT_BINARY, 0);
        !           398:        hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 1;
        !           399:        printf("Negotiating binary mode with remote host.\n");
        !           400:     } else {                           /* Turn off binary mode */
        !           401:        NET2ADD(IAC, DONT);
        !           402:        NETADD(TELOPT_BINARY);
        !           403:        printoption("<SENT", dont, TELOPT_BINARY, 0);
        !           404:        NET2ADD(IAC, DONT);
        !           405:        NETADD(TELOPT_BINARY);
        !           406:        printoption("<SENT", dont, TELOPT_BINARY, 0);
        !           407:        hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 0;
        !           408:        printf("Negotiating network ascii mode with remote host.\n");
        !           409:     }
        !           410:     return 1;
        !           411: }
        !           412: 
        !           413: 
        !           414: 
        !           415: extern int togglehelp();
        !           416: 
        !           417: struct togglelist {
        !           418:     char       *name;          /* name of toggle */
        !           419:     char       *help;          /* help message */
        !           420:     int                (*handler)();   /* routine to do actual setting */
        !           421:     int                dohelp;         /* should we display help information */
        !           422:     int                *variable;
        !           423:     char       *actionexplanation;
        !           424: };
        !           425: 
        !           426: static struct togglelist Togglelist[] = {
        !           427:     { "autoflush",
        !           428:        "toggle flushing of output when sending interrupt characters",
        !           429:            0,
        !           430:                1,
        !           431:                    &autoflush,
        !           432:                        "flush output when sending interrupt characters" },
        !           433:     { "autosynch",
        !           434:        "toggle automatic sending of interrupt characters in urgent mode",
        !           435:            0,
        !           436:                1,
        !           437:                    &autosynch,
        !           438:                        "send interrupt characters in urgent mode" },
        !           439:     { "binary",
        !           440:        "toggle sending and receiving of binary data",
        !           441:            togbinary,
        !           442:                1,
        !           443:                    0,
        !           444:                        0 },
        !           445:     { "crlf",
        !           446:        "toggle sending carriage returns as telnet <CR><LF>",
        !           447:            togcrlf,
        !           448:                1,
        !           449:                    &crlf,
        !           450:                        0 },
        !           451:     { "crmod",
        !           452:        "toggle mapping of received carriage returns",
        !           453:            0,
        !           454:                1,
        !           455:                    &crmod,
        !           456:                        "map carriage return on output" },
        !           457:     { "localchars",
        !           458:        "toggle local recognition of certain control characters",
        !           459:            lclchars,
        !           460:                1,
        !           461:                    &localchars,
        !           462:                        "recognize certain control characters" },
        !           463:     { " ", "", 0, 1 },         /* empty line */
        !           464:     { "debug",
        !           465:        "(debugging) toggle debugging",
        !           466:            togdebug,
        !           467:                1,
        !           468:                    &debug,
        !           469:                        "turn on socket level debugging" },
        !           470:     { "netdata",
        !           471:        "(debugging) toggle printing of hexadecimal network data",
        !           472:            0,
        !           473:                1,
        !           474:                    &netdata,
        !           475:                        "print hexadecimal representation of network traffic" },
        !           476:     { "options",
        !           477:        "(debugging) toggle viewing of options processing",
        !           478:            0,
        !           479:                1,
        !           480:                    &showoptions,
        !           481:                        "show option processing" },
        !           482:     { " ", "", 0, 1 },         /* empty line */
        !           483:     { "?",
        !           484:        "display help information",
        !           485:            togglehelp,
        !           486:                1 },
        !           487:     { "help",
        !           488:        "display help information",
        !           489:            togglehelp,
        !           490:                0 },
        !           491:     { 0 }
        !           492: };
        !           493: 
        !           494: static
        !           495: togglehelp()
        !           496: {
        !           497:     struct togglelist *c;
        !           498: 
        !           499:     for (c = Togglelist; c->name; c++) {
        !           500:        if (c->dohelp) {
        !           501:            printf("%s\t%s\n", c->name, c->help);
        !           502:        }
        !           503:     }
        !           504:     return 0;
        !           505: }
        !           506: 
        !           507: static char **
        !           508: getnexttoggle(name)
        !           509: char *name;
        !           510: {
        !           511:     struct togglelist *c = (struct togglelist *) name;
        !           512: 
        !           513:     return (char **) (c+1);
        !           514: }
        !           515: 
        !           516: static struct togglelist *
        !           517: gettoggle(name)
        !           518: char *name;
        !           519: {
        !           520:     return (struct togglelist *)
        !           521:                        genget(name, (char **) Togglelist, getnexttoggle);
        !           522: }
        !           523: 
        !           524: static
        !           525: toggle(argc, argv)
        !           526: int    argc;
        !           527: char   *argv[];
        !           528: {
        !           529:     int retval = 1;
        !           530:     char *name;
        !           531:     struct togglelist *c;
        !           532: 
        !           533:     if (argc < 2) {
        !           534:        fprintf(stderr,
        !           535:            "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
        !           536:        return 0;
        !           537:     }
        !           538:     argc--;
        !           539:     argv++;
        !           540:     while (argc--) {
        !           541:        name = *argv++;
        !           542:        c = gettoggle(name);
        !           543:        if (Ambiguous(c)) {
        !           544:            fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
        !           545:                                        name);
        !           546:            return 0;
        !           547:        } else if (c == 0) {
        !           548:            fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
        !           549:                                        name);
        !           550:            return 0;
        !           551:        } else {
        !           552:            if (c->variable) {
        !           553:                *c->variable = !*c->variable;           /* invert it */
        !           554:                if (c->actionexplanation) {
        !           555:                    printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !           556:                                                        c->actionexplanation);
        !           557:                }
        !           558:                printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !           559:                                                        c->actionexplanation);
        !           560:            }
        !           561:            if (c->handler) {
        !           562:                retval &= (*c->handler)(c);
        !           563:            }
        !           564:        }
        !           565:     }
        !           566:     return retval;
        !           567: }
        !           568: 
        !           569: /*
        !           570:  * The following perform the "set" command.
        !           571:  */
        !           572: 
        !           573: struct setlist {
        !           574:     char *name;                                /* name */
        !           575:     char *help;                                /* help information */
        !           576:     char *charp;                       /* where it is located at */
        !           577: };
        !           578: 
        !           579: static struct setlist Setlist[] = {
        !           580:     { "echo",  "character to toggle local echoing on/off", &echoc },
        !           581:     { "escape",        "character to escape back to telnet command mode", &escape },
        !           582:     { " ", "" },
        !           583:     { " ", "The following need 'localchars' to be toggled true", 0 },
        !           584:     { "erase", "character to cause an Erase Character", &termEraseChar },
        !           585:     { "flushoutput", "character to cause an Abort Oubput", &termFlushChar },
        !           586:     { "interrupt", "character to cause an Interrupt Process", &termIntChar },
        !           587:     { "kill",  "character to cause an Erase Line", &termKillChar },
        !           588:     { "quit",  "character to cause a Break", &termQuitChar },
        !           589:     { "eof",   "character to cause an EOF ", &termEofChar },
        !           590:     { 0 }
        !           591: };
        !           592: 
        !           593: static char **
        !           594: getnextset(name)
        !           595: char *name;
        !           596: {
        !           597:     struct setlist *c = (struct setlist *)name;
        !           598: 
        !           599:     return (char **) (c+1);
        !           600: }
        !           601: 
        !           602: static struct setlist *
        !           603: getset(name)
        !           604: char *name;
        !           605: {
        !           606:     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
        !           607: }
        !           608: 
        !           609: static
        !           610: setcmd(argc, argv)
        !           611: int    argc;
        !           612: char   *argv[];
        !           613: {
        !           614:     int value;
        !           615:     struct setlist *ct;
        !           616: 
        !           617:     /* XXX back we go... sigh */
        !           618:     if (argc != 3) {
        !           619:        if ((argc == 2) &&
        !           620:                    ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
        !           621:            for (ct = Setlist; ct->name; ct++) {
        !           622:                printf("%s\t%s\n", ct->name, ct->help);
        !           623:            }
        !           624:            printf("?\tdisplay help information\n");
        !           625:        } else {
        !           626:            printf("Format is 'set Name Value'\n'set ?' for help.\n");
        !           627:        }
        !           628:        return 0;
        !           629:     }
        !           630: 
        !           631:     ct = getset(argv[1]);
        !           632:     if (ct == 0) {
        !           633:        fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
        !           634:                        argv[1]);
        !           635:        return 0;
        !           636:     } else if (Ambiguous(ct)) {
        !           637:        fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
        !           638:                        argv[1]);
        !           639:        return 0;
        !           640:     } else {
        !           641:        if (strcmp("off", argv[2])) {
        !           642:            value = special(argv[2]);
        !           643:        } else {
        !           644:            value = -1;
        !           645:        }
        !           646:        *(ct->charp) = value;
        !           647:        printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        !           648:     }
        !           649:     return 1;
        !           650: }
        !           651: 
        !           652: /*
        !           653:  * The following are the data structures and routines for the
        !           654:  * 'mode' command.
        !           655:  */
        !           656: 
        !           657: static
        !           658: dolinemode()
        !           659: {
        !           660:     if (hisopts[TELOPT_SGA]) {
        !           661:        wontoption(TELOPT_SGA, 0);
        !           662:     }
        !           663:     if (hisopts[TELOPT_ECHO]) {
        !           664:        wontoption(TELOPT_ECHO, 0);
        !           665:     }
        !           666:     return 1;
        !           667: }
        !           668: 
        !           669: static
        !           670: docharmode()
        !           671: {
        !           672:     if (!hisopts[TELOPT_SGA]) {
        !           673:        willoption(TELOPT_SGA, 0);
        !           674:     }
        !           675:     if (!hisopts[TELOPT_ECHO]) {
        !           676:        willoption(TELOPT_ECHO, 0);
        !           677:     }
        !           678:     return 1;
        !           679: }
        !           680: 
        !           681: static Command Mode_commands[] = {
        !           682:     { "character",     "character-at-a-time mode",     docharmode, 1, 1 },
        !           683:     { "line",          "line-by-line mode",            dolinemode, 1, 1 },
        !           684:     { 0 },
        !           685: };
        !           686: 
        !           687: static char **
        !           688: getnextmode(name)
        !           689: char *name;
        !           690: {
        !           691:     Command *c = (Command *) name;
        !           692: 
        !           693:     return (char **) (c+1);
        !           694: }
        !           695: 
        !           696: static Command *
        !           697: getmodecmd(name)
        !           698: char *name;
        !           699: {
        !           700:     return (Command *) genget(name, (char **) Mode_commands, getnextmode);
        !           701: }
        !           702: 
        !           703: static
        !           704: modecmd(argc, argv)
        !           705: int    argc;
        !           706: char   *argv[];
        !           707: {
        !           708:     Command *mt;
        !           709: 
        !           710:     if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) {
        !           711:        printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
        !           712:        for (mt = Mode_commands; mt->name; mt++) {
        !           713:            printf("%s\t%s\n", mt->name, mt->help);
        !           714:        }
        !           715:        return 0;
        !           716:     }
        !           717:     mt = getmodecmd(argv[1]);
        !           718:     if (mt == 0) {
        !           719:        fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
        !           720:        return 0;
        !           721:     } else if (Ambiguous(mt)) {
        !           722:        fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
        !           723:        return 0;
        !           724:     } else {
        !           725:        (*mt->handler)();
        !           726:     }
        !           727:     return 1;
        !           728: }
        !           729: 
        !           730: /*
        !           731:  * The following data structures and routines implement the
        !           732:  * "display" command.
        !           733:  */
        !           734: 
        !           735: static
        !           736: display(argc, argv)
        !           737: int    argc;
        !           738: char   *argv[];
        !           739: {
        !           740: #define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
        !           741:                            if (*tl->variable) { \
        !           742:                                printf("will"); \
        !           743:                            } else { \
        !           744:                                printf("won't"); \
        !           745:                            } \
        !           746:                            printf(" %s.\n", tl->actionexplanation); \
        !           747:                        }
        !           748: 
        !           749: #define        doset(sl)   if (sl->name && *sl->name != ' ') { \
        !           750:                        printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \
        !           751:                    }
        !           752: 
        !           753:     struct togglelist *tl;
        !           754:     struct setlist *sl;
        !           755: 
        !           756:     if (argc == 1) {
        !           757:        for (tl = Togglelist; tl->name; tl++) {
        !           758:            dotog(tl);
        !           759:        }
        !           760:        printf("\n");
        !           761:        for (sl = Setlist; sl->name; sl++) {
        !           762:            doset(sl);
        !           763:        }
        !           764:     } else {
        !           765:        int i;
        !           766: 
        !           767:        for (i = 1; i < argc; i++) {
        !           768:            sl = getset(argv[i]);
        !           769:            tl = gettoggle(argv[i]);
        !           770:            if (Ambiguous(sl) || Ambiguous(tl)) {
        !           771:                printf("?Ambiguous argument '%s'.\n", argv[i]);
        !           772:                return 0;
        !           773:            } else if (!sl && !tl) {
        !           774:                printf("?Unknown argument '%s'.\n", argv[i]);
        !           775:                return 0;
        !           776:            } else {
        !           777:                if (tl) {
        !           778:                    dotog(tl);
        !           779:                }
        !           780:                if (sl) {
        !           781:                    doset(sl);
        !           782:                }
        !           783:            }
        !           784:        }
        !           785:     }
        !           786:     return 1;
        !           787: #undef doset
        !           788: #undef dotog
        !           789: }
        !           790: 
        !           791: /*
        !           792:  * The following are the data structures, and many of the routines,
        !           793:  * relating to command processing.
        !           794:  */
        !           795: 
        !           796: /*
        !           797:  * Set the escape character.
        !           798:  */
        !           799: static
        !           800: setescape(argc, argv)
        !           801:        int argc;
        !           802:        char *argv[];
        !           803: {
        !           804:        register char *arg;
        !           805:        char buf[50];
        !           806: 
        !           807:        printf(
        !           808:            "Deprecated usage - please use 'set escape%s%s' in the future.\n",
        !           809:                                (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
        !           810:        if (argc > 2)
        !           811:                arg = argv[1];
        !           812:        else {
        !           813:                printf("new escape character: ");
        !           814:                gets(buf);
        !           815:                arg = buf;
        !           816:        }
        !           817:        if (arg[0] != '\0')
        !           818:                escape = arg[0];
        !           819:        if (!In3270) {
        !           820:                printf("Escape character is '%s'.\n", control(escape));
        !           821:        }
        !           822:        fflush(stdout);
        !           823:        return 1;
        !           824: }
        !           825: 
        !           826: /*VARARGS*/
        !           827: static
        !           828: togcrmod()
        !           829: {
        !           830:     crmod = !crmod;
        !           831:     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
        !           832:     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
        !           833:     fflush(stdout);
        !           834:     return 1;
        !           835: }
        !           836: 
        !           837: /*VARARGS*/
        !           838: suspend()
        !           839: {
        !           840:        setcommandmode();
        !           841: #if    defined(unix)
        !           842:        kill(0, SIGTSTP);
        !           843: #endif /* defined(unix) */
        !           844:        /* reget parameters in case they were changed */
        !           845:        TerminalSaveState();
        !           846:        setconnmode();
        !           847:        return 1;
        !           848: }
        !           849: 
        !           850: /*VARARGS*/
        !           851: static
        !           852: bye(argc, argv)
        !           853: int    argc;           /* Number of arguments */
        !           854: char   *argv[];        /* arguments */
        !           855: {
        !           856:     if (connected) {
        !           857:        shutdown(net, 2);
        !           858:        printf("Connection closed.\n");
        !           859:        NetClose(net);
        !           860:        connected = 0;
        !           861:        /* reset options */
        !           862:        tninit();
        !           863: #if    defined(TN3270)
        !           864:        SetIn3270();            /* Get out of 3270 mode */
        !           865: #endif /* defined(TN3270) */
        !           866:     }
        !           867:     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
        !           868:        longjmp(toplevel, 1);
        !           869:        /* NOTREACHED */
        !           870:     }
        !           871:     return 1;                  /* Keep lint, etc., happy */
        !           872: }
        !           873: 
        !           874: /*VARARGS*/
        !           875: quit()
        !           876: {
        !           877:        (void) call(bye, "bye", "fromquit", 0);
        !           878:        Exit(0);
        !           879:        /*NOTREACHED*/
        !           880:        return 1;                       /* just to keep lint happy */
        !           881: }
        !           882: 
        !           883: /*
        !           884:  * Print status about the connection.
        !           885:  */
        !           886: static
        !           887: status(argc, argv)
        !           888: int    argc;
        !           889: char   *argv[];
        !           890: {
        !           891:     if (connected) {
        !           892:        printf("Connected to %s.\n", hostname);
        !           893:        if (argc < 2) {
        !           894:            printf("Operating in %s.\n",
        !           895:                                modelist[getconnmode()].modedescriptions);
        !           896:            if (localchars) {
        !           897:                printf("Catching signals locally.\n");
        !           898:            }
        !           899:        }
        !           900:     } else {
        !           901:        printf("No connection.\n");
        !           902:     }
        !           903: #   if !defined(TN3270)
        !           904:     printf("Escape character is '%s'.\n", control(escape));
        !           905:     fflush(stdout);
        !           906: #   else /* !defined(TN3270) */
        !           907:     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
        !           908:        printf("Escape character is '%s'.\n", control(escape));
        !           909:     }
        !           910: #   if defined(unix)
        !           911:     if (In3270 && transcom) {
        !           912:        printf("Transparent mode command is '%s'.\n", transcom);
        !           913:     }
        !           914: #   endif /* defined(unix) */
        !           915:     fflush(stdout);
        !           916:     if (In3270) {
        !           917:        return 0;
        !           918:     }
        !           919: #   endif /* defined(TN3270) */
        !           920:     return 1;
        !           921: }
        !           922: 
        !           923: 
        !           924: 
        !           925: int
        !           926: tn(argc, argv)
        !           927:        int argc;
        !           928:        char *argv[];
        !           929: {
        !           930:     register struct hostent *host = 0;
        !           931:     struct sockaddr_in sin;
        !           932:     struct servent *sp = 0;
        !           933:     static char        hnamebuf[32];
        !           934: 
        !           935: 
        !           936: #if defined(MSDOS)
        !           937:     char *cp;
        !           938: #endif /* defined(MSDOS) */
        !           939: 
        !           940:     if (connected) {
        !           941:        printf("?Already connected to %s\n", hostname);
        !           942:        return 0;
        !           943:     }
        !           944:     if (argc < 2) {
        !           945:        (void) strcpy(line, "Connect ");
        !           946:        printf("(to) ");
        !           947:        gets(&line[strlen(line)]);
        !           948:        makeargv();
        !           949:        argc = margc;
        !           950:        argv = margv;
        !           951:     }
        !           952:     if ((argc < 2) || (argc > 3)) {
        !           953:        printf("usage: %s host-name [port]\n", argv[0]);
        !           954:        return 0;
        !           955:     }
        !           956: #if    defined(MSDOS)
        !           957:     for (cp = argv[1]; *cp; cp++) {
        !           958:        if (isupper(*cp)) {
        !           959:            *cp = tolower(*cp);
        !           960:        }
        !           961:     }
        !           962: #endif /* defined(MSDOS) */
        !           963:     sin.sin_addr.s_addr = inet_addr(argv[1]);
        !           964:     if (sin.sin_addr.s_addr != -1) {
        !           965:        sin.sin_family = AF_INET;
        !           966:        (void) strcpy(hnamebuf, argv[1]);
        !           967:        hostname = hnamebuf;
        !           968:     } else {
        !           969:        host = gethostbyname(argv[1]);
        !           970:        if (host) {
        !           971:            sin.sin_family = host->h_addrtype;
        !           972: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !           973:            memcpy((caddr_t)&sin.sin_addr,
        !           974:                                host->h_addr_list[0], host->h_length);
        !           975: #else  /* defined(h_addr) */
        !           976:            memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
        !           977: #endif /* defined(h_addr) */
        !           978:            hostname = host->h_name;
        !           979:        } else {
        !           980:            printf("%s: unknown host\n", argv[1]);
        !           981:            return 0;
        !           982:        }
        !           983:     }
        !           984:     if (argc == 3) {
        !           985:        sin.sin_port = atoi(argv[2]);
        !           986:        if (sin.sin_port == 0) {
        !           987:            sp = getservbyname(argv[2], "tcp");
        !           988:            if (sp)
        !           989:                sin.sin_port = sp->s_port;
        !           990:            else {
        !           991:                printf("%s: bad port number\n", argv[2]);
        !           992:                return 0;
        !           993:            }
        !           994:        } else {
        !           995:            sin.sin_port = atoi(argv[2]);
        !           996:            sin.sin_port = htons(sin.sin_port);
        !           997:        }
        !           998:        telnetport = 0;
        !           999:     } else {
        !          1000:        if (sp == 0) {
        !          1001:            sp = getservbyname("telnet", "tcp");
        !          1002:            if (sp == 0) {
        !          1003:                fprintf(stderr, "telnet: tcp/telnet: unknown service\n",1);
        !          1004:                return 0;
        !          1005:            }
        !          1006:            sin.sin_port = sp->s_port;
        !          1007:        }
        !          1008:        telnetport = 1;
        !          1009:     }
        !          1010:     printf("Trying...\n");
        !          1011:     do {
        !          1012:        net = socket(AF_INET, SOCK_STREAM, 0);
        !          1013:        if (net < 0) {
        !          1014:            perror("telnet: socket");
        !          1015:            return 0;
        !          1016:        }
        !          1017:        if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
        !          1018:                perror("setsockopt (SO_DEBUG)");
        !          1019:        }
        !          1020: 
        !          1021:        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
        !          1022: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !          1023:            if (host && host->h_addr_list[1]) {
        !          1024:                int oerrno = errno;
        !          1025: 
        !          1026:                fprintf(stderr, "telnet: connect to address %s: ",
        !          1027:                                                inet_ntoa(sin.sin_addr));
        !          1028:                errno = oerrno;
        !          1029:                perror((char *)0);
        !          1030:                host->h_addr_list++;
        !          1031:                memcpy((caddr_t)&sin.sin_addr, 
        !          1032:                        host->h_addr_list[0], host->h_length);
        !          1033:                fprintf(stderr, "Trying %s...\n",
        !          1034:                        inet_ntoa(sin.sin_addr));
        !          1035:                (void) NetClose(net);
        !          1036:                continue;
        !          1037:            }
        !          1038: #endif /* defined(h_addr) */
        !          1039:            perror("telnet: Unable to connect to remote host");
        !          1040:            return 0;
        !          1041:            }
        !          1042:        connected++;
        !          1043:     } while (connected == 0);
        !          1044:     call(status, "status", "notmuch", 0);
        !          1045:     if (setjmp(peerdied) == 0)
        !          1046:        telnet();
        !          1047:     NetClose(net);
        !          1048:     ExitString("Connection closed by foreign host.\n",1);
        !          1049:     /*NOTREACHED*/
        !          1050: }
        !          1051: 
        !          1052: 
        !          1053: #define HELPINDENT (sizeof ("connect"))
        !          1054: 
        !          1055: static char
        !          1056:        openhelp[] =    "connect to a site",
        !          1057:        closehelp[] =   "close current connection",
        !          1058:        quithelp[] =    "exit telnet",
        !          1059:        statushelp[] =  "print status information",
        !          1060:        helphelp[] =    "print help information",
        !          1061:        sendhelp[] =    "transmit special characters ('send ?' for more)",
        !          1062:        sethelp[] =     "set operating parameters ('set ?' for more)",
        !          1063:        togglestring[] ="toggle operating parameters ('toggle ?' for more)",
        !          1064:        displayhelp[] = "display operating parameters",
        !          1065: #if    defined(TN3270) && defined(unix)
        !          1066:        transcomhelp[] = "specify Unix command for transparent mode pipe",
        !          1067: #endif /* defined(TN3270) && defined(unix) */
        !          1068: #if    defined(unix)
        !          1069:        zhelp[] =       "suspend telnet",
        !          1070: #endif /* defined(unix */
        !          1071: #if    defined(TN3270)
        !          1072:        shellhelp[] =   "invoke a subshell",
        !          1073: #endif /* defined(TN3270) */
        !          1074:        modehelp[] = "try to enter line-by-line or character-at-a-time mode";
        !          1075: 
        !          1076: extern int     help(), shell();
        !          1077: 
        !          1078: static Command cmdtab[] = {
        !          1079:        { "close",      closehelp,      bye,            1, 1 },
        !          1080:        { "display",    displayhelp,    display,        1, 0 },
        !          1081:        { "mode",       modehelp,       modecmd,        1, 1 },
        !          1082:        { "open",       openhelp,       tn,             1, 0 },
        !          1083:        { "quit",       quithelp,       quit,           1, 0 },
        !          1084:        { "send",       sendhelp,       sendcmd,        1, 1 },
        !          1085:        { "set",        sethelp,        setcmd,         1, 0 },
        !          1086:        { "status",     statushelp,     status,         1, 0 },
        !          1087:        { "toggle",     togglestring,   toggle,         1, 0 },
        !          1088: #if    defined(TN3270) && defined(unix)
        !          1089:        { "transcom",   transcomhelp,   settranscom,    1, 0 },
        !          1090: #endif /* defined(TN3270) && defined(unix) */
        !          1091: #if    defined(unix)
        !          1092:        { "z",          zhelp,          suspend,        1, 0 },
        !          1093: #endif /* defined(unix) */
        !          1094: #if    defined(TN3270)
        !          1095:        { "!",          shellhelp,      shell,          1, 1 },
        !          1096: #endif /* defined(TN3270) */
        !          1097:        { "?",          helphelp,       help,           1, 0 },
        !          1098:        0
        !          1099: };
        !          1100: 
        !          1101: static char    crmodhelp[] =   "deprecated command -- use 'toggle crmod' instead";
        !          1102: static char    escapehelp[] =  "deprecated command -- use 'set escape' instead";
        !          1103: 
        !          1104: static Command cmdtab2[] = {
        !          1105:        { "help",       helphelp,       help,           0, 0 },
        !          1106:        { "escape",     escapehelp,     setescape,      1, 0 },
        !          1107:        { "crmod",      crmodhelp,      togcrmod,       1, 0 },
        !          1108:        0
        !          1109: };
        !          1110: 
        !          1111: /*
        !          1112:  * Call routine with argc, argv set from args (terminated by 0).
        !          1113:  * VARARGS2
        !          1114:  */
        !          1115: static
        !          1116: call(routine, args)
        !          1117:        int (*routine)();
        !          1118:        char *args;
        !          1119: {
        !          1120:        register char **argp;
        !          1121:        register int argc;
        !          1122: 
        !          1123:        for (argc = 0, argp = &args; *argp++ != 0; argc++)
        !          1124:                ;
        !          1125:        return (*routine)(argc, &args);
        !          1126: }
        !          1127: 
        !          1128: static char **
        !          1129: getnextcmd(name)
        !          1130: char *name;
        !          1131: {
        !          1132:     Command *c = (Command *) name;
        !          1133: 
        !          1134:     return (char **) (c+1);
        !          1135: }
        !          1136: 
        !          1137: static Command *
        !          1138: getcmd(name)
        !          1139: char *name;
        !          1140: {
        !          1141:     Command *cm;
        !          1142: 
        !          1143:     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
        !          1144:        return cm;
        !          1145:     } else {
        !          1146:        return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
        !          1147:     }
        !          1148: }
        !          1149: 
        !          1150: void
        !          1151: command(top)
        !          1152:        int top;
        !          1153: {
        !          1154:     register Command *c;
        !          1155: 
        !          1156:     setcommandmode();
        !          1157:     if (!top) {
        !          1158:        putchar('\n');
        !          1159:     } else {
        !          1160: #if    defined(unix)
        !          1161:        signal(SIGINT, SIG_DFL);
        !          1162:        signal(SIGQUIT, SIG_DFL);
        !          1163: #endif /* defined(unix) */
        !          1164:     }
        !          1165:     for (;;) {
        !          1166:        printf("%s> ", prompt);
        !          1167:        if (gets(line) == NULL) {
        !          1168:            if (feof(stdin) || ferror(stdin))
        !          1169:                quit();
        !          1170:            break;
        !          1171:        }
        !          1172:        if (line[0] == 0)
        !          1173:            break;
        !          1174:        makeargv();
        !          1175:        c = getcmd(margv[0]);
        !          1176:        if (Ambiguous(c)) {
        !          1177:            printf("?Ambiguous command\n");
        !          1178:            continue;
        !          1179:        }
        !          1180:        if (c == 0) {
        !          1181:            printf("?Invalid command\n");
        !          1182:            continue;
        !          1183:        }
        !          1184:        if (c->needconnect && !connected) {
        !          1185:            printf("?Need to be connected first.\n");
        !          1186:            continue;
        !          1187:        }
        !          1188:        if ((*c->handler)(margc, margv)) {
        !          1189:            break;
        !          1190:        }
        !          1191:     }
        !          1192:     if (!top) {
        !          1193:        if (!connected) {
        !          1194:            longjmp(toplevel, 1);
        !          1195:            /*NOTREACHED*/
        !          1196:        }
        !          1197: #if    defined(TN3270)
        !          1198:        if (shell_active == 0) {
        !          1199:            setconnmode();
        !          1200:        }
        !          1201: #else  /* defined(TN3270) */
        !          1202:        setconnmode();
        !          1203: #endif /* defined(TN3270) */
        !          1204:     }
        !          1205: }
        !          1206: 
        !          1207: /*
        !          1208:  * Help command.
        !          1209:  */
        !          1210: static
        !          1211: help(argc, argv)
        !          1212:        int argc;
        !          1213:        char *argv[];
        !          1214: {
        !          1215:        register Command *c;
        !          1216: 
        !          1217:        if (argc == 1) {
        !          1218:                printf("Commands may be abbreviated.  Commands are:\n\n");
        !          1219:                for (c = cmdtab; c->name; c++)
        !          1220:                        if (c->dohelp) {
        !          1221:                                printf("%-*s\t%s\n", HELPINDENT, c->name,
        !          1222:                                                                    c->help);
        !          1223:                        }
        !          1224:                return 0;
        !          1225:        }
        !          1226:        while (--argc > 0) {
        !          1227:                register char *arg;
        !          1228:                arg = *++argv;
        !          1229:                c = getcmd(arg);
        !          1230:                if (Ambiguous(c))
        !          1231:                        printf("?Ambiguous help command %s\n", arg);
        !          1232:                else if (c == (Command *)0)
        !          1233:                        printf("?Invalid help command %s\n", arg);
        !          1234:                else
        !          1235:                        printf("%s\n", c->help);
        !          1236:        }
        !          1237:        return 0;
        !          1238: }

unix.superglobalmegacorp.com

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