Annotation of 43BSDTahoe/ucb/telnet/Source/commands.c, revision 1.1.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.