Annotation of 43BSDReno/usr.bin/telnet/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 provided
        !             6:  * that: (1) source distributions retain this entire copyright notice and
        !             7:  * comment, and (2) distributions including binaries display the following
        !             8:  * acknowledgement:  ``This product includes software developed by the
        !             9:  * University of California, Berkeley and its contributors'' in the
        !            10:  * documentation or other materials provided with the distribution and in
        !            11:  * all advertising materials mentioning features or use of this software.
        !            12:  * Neither the name of the University nor the names of its contributors may
        !            13:  * be used to endorse or promote products derived from this software without
        !            14:  * specific prior written permission.
        !            15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            18:  */
        !            19: 
        !            20: #ifndef lint
        !            21: static char sccsid[] = "@(#)commands.c 1.32 (Berkeley) 7/28/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: #include <sys/types.h>
        !            25: #if    defined(unix)
        !            26: #include <sys/file.h>
        !            27: #endif /* defined(unix) */
        !            28: #include <sys/socket.h>
        !            29: #include <netinet/in.h>
        !            30: #ifdef CRAY
        !            31: #include <sys/fcntl.h>
        !            32: #endif /* CRAY */
        !            33: 
        !            34: #include <signal.h>
        !            35: #include <netdb.h>
        !            36: #include <ctype.h>
        !            37: #include <pwd.h>
        !            38: #include <varargs.h>
        !            39: 
        !            40: #include <arpa/telnet.h>
        !            41: 
        !            42: #include "general.h"
        !            43: 
        !            44: #include "ring.h"
        !            45: 
        !            46: #include "externs.h"
        !            47: #include "defines.h"
        !            48: #include "types.h"
        !            49: 
        !            50: #ifdef SRCRT
        !            51: # ifndef CRAY
        !            52: # include <netinet/in_systm.h>
        !            53: #  if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix)
        !            54: #  include <machine/endian.h>
        !            55: #  endif /* vax */
        !            56: # endif /* CRAY */
        !            57: #include <netinet/ip.h>
        !            58: #endif /* SRCRT */
        !            59: 
        !            60: #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS)
        !            61: # define HAS_IP_TOS
        !            62: #endif
        !            63: 
        !            64: 
        !            65: char   *hostname;
        !            66: extern char *getenv();
        !            67: 
        !            68: #define Ambiguous(s)   ((char **)s == &ambiguous)
        !            69: static char *ambiguous;                /* special return value for command routines */
        !            70: static call();
        !            71: 
        !            72: typedef struct {
        !            73:        char    *name;          /* command name */
        !            74:        char    *help;          /* help string (NULL for no help) */
        !            75:        int     (*handler)();   /* routine which executes command */
        !            76:        int     needconnect;    /* Do we need to be connected to execute? */
        !            77: } Command;
        !            78: 
        !            79: static char line[256];
        !            80: static char saveline[256];
        !            81: static int margc;
        !            82: static char *margv[20];
        !            83: 
        !            84: /*
        !            85:  * Various utility routines.
        !            86:  */
        !            87: 
        !            88: #if    !defined(BSD) || (BSD <= 43)
        !            89: 
        !            90: char   *h_errlist[] = {
        !            91:        "Error 0",
        !            92:        "Unknown host",                         /* 1 HOST_NOT_FOUND */
        !            93:        "Host name lookup failure",             /* 2 TRY_AGAIN */
        !            94:        "Unknown server error",                 /* 3 NO_RECOVERY */
        !            95:        "No address associated with name",      /* 4 NO_ADDRESS */
        !            96: };
        !            97: int    h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) };
        !            98: 
        !            99: int h_errno;           /* In some version of SunOS this is necessary */
        !           100: 
        !           101: /*
        !           102:  * herror --
        !           103:  *     print the error indicated by the h_errno value.
        !           104:  */
        !           105: herror(s)
        !           106:        char *s;
        !           107: {
        !           108:        if (s && *s) {
        !           109:                fprintf(stderr, "%s: ", s);
        !           110:        }
        !           111:        if ((h_errno < 0) || (h_errno >= h_nerr)) {
        !           112:                fprintf(stderr, "Unknown error\n");
        !           113:        } else if (h_errno == 0) {
        !           114: #if    defined(sun)
        !           115:                fprintf(stderr, "Host unknown\n");
        !           116: #endif /* defined(sun) */
        !           117:        } else {
        !           118:                fprintf(stderr, "%s\n", h_errlist[h_errno]);
        !           119:        }
        !           120: }
        !           121: #endif /* !define(BSD) || (BSD <= 43) */
        !           122: 
        !           123: static void
        !           124: makeargv()
        !           125: {
        !           126:     register char *cp, *cp2, c;
        !           127:     register char **argp = margv;
        !           128: 
        !           129:     margc = 0;
        !           130:     cp = line;
        !           131:     if (*cp == '!') {          /* Special case shell escape */
        !           132:        strcpy(saveline, line); /* save for shell command */
        !           133:        *argp++ = "!";          /* No room in string to get this */
        !           134:        margc++;
        !           135:        cp++;
        !           136:     }
        !           137:     while (c = *cp) {
        !           138:        register int inquote = 0;
        !           139:        while (isspace(c))
        !           140:            c = *++cp;
        !           141:        if (c == '\0')
        !           142:            break;
        !           143:        *argp++ = cp;
        !           144:        margc += 1;
        !           145:        for (cp2 = cp; c != '\0'; c = *++cp) {
        !           146:            if (inquote) {
        !           147:                if (c == inquote) {
        !           148:                    inquote = 0;
        !           149:                    continue;
        !           150:                }
        !           151:            } else {
        !           152:                if (c == '\\') {
        !           153:                    if ((c = *++cp) == '\0')
        !           154:                        break;
        !           155:                } else if (c == '"') {
        !           156:                    inquote = '"';
        !           157:                    continue;
        !           158:                } else if (c == '\'') {
        !           159:                    inquote = '\'';
        !           160:                    continue;
        !           161:                } else if (isspace(c))
        !           162:                    break;
        !           163:            }
        !           164:            *cp2++ = c;
        !           165:        }
        !           166:        *cp2 = '\0';
        !           167:        if (c == '\0')
        !           168:            break;
        !           169:        cp++;
        !           170:     }
        !           171:     *argp++ = 0;
        !           172: }
        !           173: 
        !           174: 
        !           175: static char **
        !           176: genget(name, table, next)
        !           177: char   *name;          /* name to match */
        !           178: char   **table;                /* name entry in table */
        !           179: char   **(*next)();    /* routine to return next entry in table */
        !           180: {
        !           181:        register char *p, *q;
        !           182:        register char **c, **found;
        !           183:        register int nmatches, longest;
        !           184: 
        !           185:        if (name == 0) {
        !           186:            return 0;
        !           187:        }
        !           188:        longest = 0;
        !           189:        nmatches = 0;
        !           190:        found = 0;
        !           191:        for (c = table; (p = *c) != 0; c = (*next)(c)) {
        !           192:                for (q = name;
        !           193:                    (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++)
        !           194:                        if (*q == 0)            /* exact match? */
        !           195:                                return (c);
        !           196:                if (!*q) {                      /* the name was a prefix */
        !           197:                        if (q - name > longest) {
        !           198:                                longest = q - name;
        !           199:                                nmatches = 1;
        !           200:                                found = c;
        !           201:                        } else if (q - name == longest)
        !           202:                                nmatches++;
        !           203:                }
        !           204:        }
        !           205:        if (nmatches > 1)
        !           206:                return &ambiguous;
        !           207:        return (found);
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Make a character string into a number.
        !           212:  *
        !           213:  * Todo:  1.  Could take random integers (12, 0x12, 012, 0b1).
        !           214:  */
        !           215: 
        !           216: static
        !           217: special(s)
        !           218: register char *s;
        !           219: {
        !           220:        register char c;
        !           221:        char b;
        !           222: 
        !           223:        switch (*s) {
        !           224:        case '^':
        !           225:                b = *++s;
        !           226:                if (b == '?') {
        !           227:                    c = b | 0x40;               /* DEL */
        !           228:                } else {
        !           229:                    c = b & 0x1f;
        !           230:                }
        !           231:                break;
        !           232:        default:
        !           233:                c = *s;
        !           234:                break;
        !           235:        }
        !           236:        return c;
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Construct a control character sequence
        !           241:  * for a special character.
        !           242:  */
        !           243: static char *
        !           244: control(c)
        !           245:        register cc_t c;
        !           246: {
        !           247:        static char buf[5];
        !           248: 
        !           249:        if (c == 0x7f)
        !           250:                return ("^?");
        !           251:        if (c == (cc_t)-1) {
        !           252:                return "off";
        !           253:        }
        !           254:        if (c >= 0x80) {
        !           255:                buf[0] = '\\';
        !           256:                buf[1] = ((c>>6)&07) + '0';
        !           257:                buf[2] = ((c>>3)&07) + '0';
        !           258:                buf[3] = (c&07) + '0';
        !           259:                buf[4] = 0;
        !           260:        } else if (c >= 0x20) {
        !           261:                buf[0] = c;
        !           262:                buf[1] = 0;
        !           263:        } else {
        !           264:                buf[0] = '^';
        !           265:                buf[1] = '@'+c;
        !           266:                buf[2] = 0;
        !           267:        }
        !           268:        return (buf);
        !           269: }
        !           270: 
        !           271: 
        !           272: 
        !           273: /*
        !           274:  *     The following are data structures and routines for
        !           275:  *     the "send" command.
        !           276:  *
        !           277:  */
        !           278:  
        !           279: struct sendlist {
        !           280:     char       *name;          /* How user refers to it (case independent) */
        !           281:     char       *help;          /* Help information (0 ==> no help) */
        !           282: #if    defined(NOT43)
        !           283:     int                (*handler)();   /* Routine to perform (for special ops) */
        !           284: #else  /* defined(NOT43) */
        !           285:     void       (*handler)();   /* Routine to perform (for special ops) */
        !           286: #endif /* defined(NOT43) */
        !           287:     int                what;           /* Character to be sent (<0 ==> special) */
        !           288: };
        !           289: 
        !           290: #define        SENDQUESTION    -1
        !           291: #define        SENDESCAPE      -3
        !           292: 
        !           293: static struct sendlist Sendlist[] = {
        !           294:     { "ao",    "Send Telnet Abort output",             0,      AO },
        !           295:     { "ayt",   "Send Telnet 'Are You There'",          0,      AYT },
        !           296:     { "brk",   "Send Telnet Break",                    0,      BREAK },
        !           297:     { "ec",    "Send Telnet Erase Character",          0,      EC },
        !           298:     { "el",    "Send Telnet Erase Line",               0,      EL },
        !           299:     { "escape",        "Send current escape character",        0,      SENDESCAPE },
        !           300:     { "ga",    "Send Telnet 'Go Ahead' sequence",      0,      GA },
        !           301:     { "ip",    "Send Telnet Interrupt Process",        0,      IP },
        !           302:     { "nop",   "Send Telnet 'No operation'",           0,      NOP },
        !           303:     { "eor",   "Send Telnet 'End of Record'",          0,      EOR },
        !           304:     { "abort", "Send Telnet 'Abort Process'",          0,      ABORT },
        !           305:     { "susp",  "Send Telnet 'Suspend Process'",        0,      SUSP },
        !           306:     { "eof",   "Send Telnet End of File Character",    0,      xEOF },
        !           307:     { "synch", "Perform Telnet 'Synch operation'",     dosynch, SYNCH },
        !           308:     { "getstatus", "Send request for STATUS",          get_status, 0 },
        !           309:     { "?",     "Display send options",                 0,      SENDQUESTION },
        !           310:     { 0 }
        !           311: };
        !           312: 
        !           313: static struct sendlist Sendlist2[] = {         /* some synonyms */
        !           314:     { "break",         0, 0, BREAK },
        !           315: 
        !           316:     { "intp",          0, 0, IP },
        !           317:     { "interrupt",     0, 0, IP },
        !           318:     { "intr",          0, 0, IP },
        !           319: 
        !           320:     { "help",          0, 0, SENDQUESTION },
        !           321: 
        !           322:     { 0 }
        !           323: };
        !           324: 
        !           325: static char **
        !           326: getnextsend(name)
        !           327: char *name;
        !           328: {
        !           329:     struct sendlist *c = (struct sendlist *) name;
        !           330: 
        !           331:     return (char **) (c+1);
        !           332: }
        !           333: 
        !           334: static struct sendlist *
        !           335: getsend(name)
        !           336: char *name;
        !           337: {
        !           338:     struct sendlist *sl;
        !           339: 
        !           340:     if ((sl = (struct sendlist *)
        !           341:                        genget(name, (char **) Sendlist, getnextsend)) != 0) {
        !           342:        return sl;
        !           343:     } else {
        !           344:        return (struct sendlist *)
        !           345:                                genget(name, (char **) Sendlist2, getnextsend);
        !           346:     }
        !           347: }
        !           348: 
        !           349: static
        !           350: sendcmd(argc, argv)
        !           351: int    argc;
        !           352: char   **argv;
        !           353: {
        !           354:     int what;          /* what we are sending this time */
        !           355:     int count;         /* how many bytes we are going to need to send */
        !           356:     int i;
        !           357:     int question = 0;  /* was at least one argument a question */
        !           358:     struct sendlist *s;        /* pointer to current command */
        !           359: 
        !           360:     if (argc < 2) {
        !           361:        printf("need at least one argument for 'send' command\n");
        !           362:        printf("'send ?' for help\n");
        !           363:        return 0;
        !           364:     }
        !           365:     /*
        !           366:      * First, validate all the send arguments.
        !           367:      * In addition, we see how much space we are going to need, and
        !           368:      * whether or not we will be doing a "SYNCH" operation (which
        !           369:      * flushes the network queue).
        !           370:      */
        !           371:     count = 0;
        !           372:     for (i = 1; i < argc; i++) {
        !           373:        s = getsend(argv[i]);
        !           374:        if (s == 0) {
        !           375:            printf("Unknown send argument '%s'\n'send ?' for help.\n",
        !           376:                        argv[i]);
        !           377:            return 0;
        !           378:        } else if (Ambiguous(s)) {
        !           379:            printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
        !           380:                        argv[i]);
        !           381:            return 0;
        !           382:        }
        !           383:        switch (s->what) {
        !           384:        case SENDQUESTION:
        !           385:            question = 1;
        !           386:            break;
        !           387:        case SENDESCAPE:
        !           388:            count += 1;
        !           389:            break;
        !           390:        case SYNCH:
        !           391:            count += 2;
        !           392:            break;
        !           393:        default:
        !           394:            count += 2;
        !           395:            break;
        !           396:        }
        !           397:     }
        !           398:     if (!connected) {
        !           399:        if (count)
        !           400:            printf("?Need to be connected first.\n");
        !           401:        if (question) {
        !           402:            for (s = Sendlist; s->name; s++)
        !           403:                if (s->help)
        !           404:                    printf("%-15s %s\n", s->name, s->help);
        !           405:        } else
        !           406:            printf("'send ?' for help\n");
        !           407:        return !question;
        !           408:     }
        !           409:     /* Now, do we have enough room? */
        !           410:     if (NETROOM() < count) {
        !           411:        printf("There is not enough room in the buffer TO the network\n");
        !           412:        printf("to process your request.  Nothing will be done.\n");
        !           413:        printf("('send synch' will throw away most data in the network\n");
        !           414:        printf("buffer, if this might help.)\n");
        !           415:        return 0;
        !           416:     }
        !           417:     /* OK, they are all OK, now go through again and actually send */
        !           418:     for (i = 1; i < argc; i++) {
        !           419:        if ((s = getsend(argv[i])) == 0) {
        !           420:            fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
        !           421:            (void) quit();
        !           422:            /*NOTREACHED*/
        !           423:        }
        !           424:        if (s->handler) {
        !           425:            (*s->handler)(s);
        !           426:        } else {
        !           427:            switch (what = s->what) {
        !           428:            case SYNCH:
        !           429:                dosynch();
        !           430:                break;
        !           431:            case SENDQUESTION:
        !           432:                for (s = Sendlist; s->name; s++) {
        !           433:                    if (s->help)
        !           434:                        printf("%-15s %s\n", s->name, s->help);
        !           435:                }
        !           436:                question = 1;
        !           437:                break;
        !           438:            case SENDESCAPE:
        !           439:                NETADD(escape);
        !           440:                break;
        !           441:            default:
        !           442:                NET2ADD(IAC, what);
        !           443:                break;
        !           444:            }
        !           445:        }
        !           446:     }
        !           447:     return !question;
        !           448: }
        !           449: 
        !           450: /*
        !           451:  * The following are the routines and data structures referred
        !           452:  * to by the arguments to the "toggle" command.
        !           453:  */
        !           454: 
        !           455: static
        !           456: lclchars()
        !           457: {
        !           458:     donelclchars = 1;
        !           459:     return 1;
        !           460: }
        !           461: 
        !           462: static
        !           463: togdebug()
        !           464: {
        !           465: #ifndef        NOT43
        !           466:     if (net > 0 &&
        !           467:        (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
        !           468:            perror("setsockopt (SO_DEBUG)");
        !           469:     }
        !           470: #else  /* NOT43 */
        !           471:     if (debug) {
        !           472:        if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
        !           473:            perror("setsockopt (SO_DEBUG)");
        !           474:     } else
        !           475:        printf("Cannot turn off socket debugging\n");
        !           476: #endif /* NOT43 */
        !           477:     return 1;
        !           478: }
        !           479: 
        !           480: 
        !           481: static int
        !           482: togcrlf()
        !           483: {
        !           484:     if (crlf) {
        !           485:        printf("Will send carriage returns as telnet <CR><LF>.\n");
        !           486:     } else {
        !           487:        printf("Will send carriage returns as telnet <CR><NUL>.\n");
        !           488:     }
        !           489:     return 1;
        !           490: }
        !           491: 
        !           492: int binmode;
        !           493: 
        !           494: static int
        !           495: togbinary(val)
        !           496: int val;
        !           497: {
        !           498:     donebinarytoggle = 1;
        !           499: 
        !           500:     if (val >= 0) {
        !           501:        binmode = val;
        !           502:     } else {
        !           503:        if (my_want_state_is_will(TELOPT_BINARY) &&
        !           504:                                my_want_state_is_do(TELOPT_BINARY)) {
        !           505:            binmode = 1;
        !           506:        } else if (my_want_state_is_wont(TELOPT_BINARY) &&
        !           507:                                my_want_state_is_dont(TELOPT_BINARY)) {
        !           508:            binmode = 0;
        !           509:        }
        !           510:        val = binmode ? 0 : 1;
        !           511:     }
        !           512: 
        !           513:     if (val == 1) {
        !           514:        if (my_want_state_is_will(TELOPT_BINARY) &&
        !           515:                                        my_want_state_is_do(TELOPT_BINARY)) {
        !           516:            printf("Already operating in binary mode with remote host.\n");
        !           517:        } else {
        !           518:            printf("Negotiating binary mode with remote host.\n");
        !           519:            tel_enter_binary(3);
        !           520:        }
        !           521:     } else {
        !           522:        if (my_want_state_is_wont(TELOPT_BINARY) &&
        !           523:                                        my_want_state_is_dont(TELOPT_BINARY)) {
        !           524:            printf("Already in network ascii mode with remote host.\n");
        !           525:        } else {
        !           526:            printf("Negotiating network ascii mode with remote host.\n");
        !           527:            tel_leave_binary(3);
        !           528:        }
        !           529:     }
        !           530:     return 1;
        !           531: }
        !           532: 
        !           533: static int
        !           534: togrbinary(val)
        !           535: int val;
        !           536: {
        !           537:     donebinarytoggle = 1;
        !           538: 
        !           539:     if (val == -1)
        !           540:        val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
        !           541: 
        !           542:     if (val == 1) {
        !           543:        if (my_want_state_is_do(TELOPT_BINARY)) {
        !           544:            printf("Already receiving in binary mode.\n");
        !           545:        } else {
        !           546:            printf("Negotiating binary mode on input.\n");
        !           547:            tel_enter_binary(1);
        !           548:        }
        !           549:     } else {
        !           550:        if (my_want_state_is_dont(TELOPT_BINARY)) {
        !           551:            printf("Already receiving in network ascii mode.\n");
        !           552:        } else {
        !           553:            printf("Negotiating network ascii mode on input.\n");
        !           554:            tel_leave_binary(1);
        !           555:        }
        !           556:     }
        !           557:     return 1;
        !           558: }
        !           559: 
        !           560: static int
        !           561: togxbinary(val)
        !           562: int val;
        !           563: {
        !           564:     donebinarytoggle = 1;
        !           565: 
        !           566:     if (val == -1)
        !           567:        val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
        !           568: 
        !           569:     if (val == 1) {
        !           570:        if (my_want_state_is_will(TELOPT_BINARY)) {
        !           571:            printf("Already transmitting in binary mode.\n");
        !           572:        } else {
        !           573:            printf("Negotiating binary mode on output.\n");
        !           574:            tel_enter_binary(2);
        !           575:        }
        !           576:     } else {
        !           577:        if (my_want_state_is_wont(TELOPT_BINARY)) {
        !           578:            printf("Already transmitting in network ascii mode.\n");
        !           579:        } else {
        !           580:            printf("Negotiating network ascii mode on output.\n");
        !           581:            tel_leave_binary(2);
        !           582:        }
        !           583:     }
        !           584:     return 1;
        !           585: }
        !           586: 
        !           587: 
        !           588: extern int togglehelp();
        !           589: extern int slc_check();
        !           590: 
        !           591: struct togglelist {
        !           592:     char       *name;          /* name of toggle */
        !           593:     char       *help;          /* help message */
        !           594:     int                (*handler)();   /* routine to do actual setting */
        !           595:     int                *variable;
        !           596:     char       *actionexplanation;
        !           597: };
        !           598: 
        !           599: static struct togglelist Togglelist[] = {
        !           600:     { "autoflush",
        !           601:        "flushing of output when sending interrupt characters",
        !           602:            0,
        !           603:                &autoflush,
        !           604:                    "flush output when sending interrupt characters" },
        !           605:     { "autosynch",
        !           606:        "automatic sending of interrupt characters in urgent mode",
        !           607:            0,
        !           608:                &autosynch,
        !           609:                    "send interrupt characters in urgent mode" },
        !           610:     { "binary",
        !           611:        "sending and receiving of binary data",
        !           612:            togbinary,
        !           613:                0,
        !           614:                    0 },
        !           615:     { "inbinary",
        !           616:        "receiving of binary data",
        !           617:            togrbinary,
        !           618:                0,
        !           619:                    0 },
        !           620:     { "outbinary",
        !           621:        "sending of binary data",
        !           622:            togxbinary,
        !           623:                0,
        !           624:                    0 },
        !           625:     { "crlf",
        !           626:        "sending carriage returns as telnet <CR><LF>",
        !           627:            togcrlf,
        !           628:                &crlf,
        !           629:                    0 },
        !           630:     { "crmod",
        !           631:        "mapping of received carriage returns",
        !           632:            0,
        !           633:                &crmod,
        !           634:                    "map carriage return on output" },
        !           635:     { "localchars",
        !           636:        "local recognition of certain control characters",
        !           637:            lclchars,
        !           638:                &localchars,
        !           639:                    "recognize certain control characters" },
        !           640: #ifdef KERBEROS
        !           641:     { "kerberos",
        !           642:        "toggle use of Kerberos authentication",
        !           643:            0,
        !           644:                &kerberized,
        !           645:                    "use Kerberos authentication" },
        !           646: #endif
        !           647:     { " ", "", 0 },            /* empty line */
        !           648: #if    defined(unix) && defined(TN3270)
        !           649:     { "apitrace",
        !           650:        "(debugging) toggle tracing of API transactions",
        !           651:            0,
        !           652:                &apitrace,
        !           653:                    "trace API transactions" },
        !           654:     { "cursesdata",
        !           655:        "(debugging) toggle printing of hexadecimal curses data",
        !           656:            0,
        !           657:                &cursesdata,
        !           658:                    "print hexadecimal representation of curses data" },
        !           659: #endif /* defined(unix) && defined(TN3270) */
        !           660:     { "debug",
        !           661:        "debugging",
        !           662:            togdebug,
        !           663:                &debug,
        !           664:                    "turn on socket level debugging" },
        !           665:     { "netdata",
        !           666:        "printing of hexadecimal network data (debugging)",
        !           667:            0,
        !           668:                &netdata,
        !           669:                    "print hexadecimal representation of network traffic" },
        !           670:     { "prettydump",
        !           671:        "output of \"netdata\" to user readable format (debugging)",
        !           672:            0,
        !           673:                &prettydump,
        !           674:                    "print user readable output for \"netdata\"" },
        !           675:     { "options",
        !           676:        "viewing of options processing (debugging)",
        !           677:            0,
        !           678:                &showoptions,
        !           679:                    "show option processing" },
        !           680: #if    defined(unix)
        !           681:     { "termdata",
        !           682:        "(debugging) toggle printing of hexadecimal terminal data",
        !           683:            0,
        !           684:                &termdata,
        !           685:                    "print hexadecimal representation of terminal traffic" },
        !           686: #endif /* defined(unix) */
        !           687:     { "?",
        !           688:        0,
        !           689:            togglehelp },
        !           690:     { "help",
        !           691:        0,
        !           692:            togglehelp },
        !           693:     { 0 }
        !           694: };
        !           695: 
        !           696: static
        !           697: togglehelp()
        !           698: {
        !           699:     struct togglelist *c;
        !           700: 
        !           701:     for (c = Togglelist; c->name; c++) {
        !           702:        if (c->help) {
        !           703:            if (*c->help)
        !           704:                printf("%-15s toggle %s\n", c->name, c->help);
        !           705:            else
        !           706:                printf("\n");
        !           707:        }
        !           708:     }
        !           709:     printf("\n");
        !           710:     printf("%-15s %s\n", "?", "display help information");
        !           711:     return 0;
        !           712: }
        !           713: 
        !           714: static
        !           715: settogglehelp(set)
        !           716: int set;
        !           717: {
        !           718:     struct togglelist *c;
        !           719: 
        !           720:     for (c = Togglelist; c->name; c++) {
        !           721:        if (c->help) {
        !           722:            if (*c->help)
        !           723:                printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
        !           724:                                                c->help);
        !           725:            else
        !           726:                printf("\n");
        !           727:        }
        !           728:     }
        !           729: }
        !           730: 
        !           731: static char **
        !           732: getnexttoggle(name)
        !           733: char *name;
        !           734: {
        !           735:     struct togglelist *c = (struct togglelist *) name;
        !           736: 
        !           737:     return (char **) (c+1);
        !           738: }
        !           739: 
        !           740: static struct togglelist *
        !           741: gettoggle(name)
        !           742: char *name;
        !           743: {
        !           744:     return (struct togglelist *)
        !           745:                        genget(name, (char **) Togglelist, getnexttoggle);
        !           746: }
        !           747: 
        !           748: static
        !           749: toggle(argc, argv)
        !           750: int    argc;
        !           751: char   *argv[];
        !           752: {
        !           753:     int retval = 1;
        !           754:     char *name;
        !           755:     struct togglelist *c;
        !           756: 
        !           757:     if (argc < 2) {
        !           758:        fprintf(stderr,
        !           759:            "Need an argument to 'toggle' command.  'toggle ?' for help.\n");
        !           760:        return 0;
        !           761:     }
        !           762:     argc--;
        !           763:     argv++;
        !           764:     while (argc--) {
        !           765:        name = *argv++;
        !           766:        c = gettoggle(name);
        !           767:        if (Ambiguous(c)) {
        !           768:            fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
        !           769:                                        name);
        !           770:            return 0;
        !           771:        } else if (c == 0) {
        !           772:            fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
        !           773:                                        name);
        !           774:            return 0;
        !           775:        } else {
        !           776:            if (c->variable) {
        !           777:                *c->variable = !*c->variable;           /* invert it */
        !           778:                if (c->actionexplanation) {
        !           779:                    printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !           780:                                                        c->actionexplanation);
        !           781:                }
        !           782:            }
        !           783:            if (c->handler) {
        !           784:                retval &= (*c->handler)(-1);
        !           785:            }
        !           786:        }
        !           787:     }
        !           788:     return retval;
        !           789: }
        !           790: 
        !           791: /*
        !           792:  * The following perform the "set" command.
        !           793:  */
        !           794: 
        !           795: #ifdef USE_TERMIO
        !           796: struct termio new_tc = { 0 };
        !           797: #endif
        !           798: 
        !           799: struct setlist {
        !           800:     char *name;                                /* name */
        !           801:     char *help;                                /* help information */
        !           802:     void (*handler)();
        !           803:     cc_t *charp;                       /* where it is located at */
        !           804: };
        !           805: 
        !           806: static struct setlist Setlist[] = {
        !           807: #ifdef KLUDGELINEMODE
        !           808:     { "echo",  "character to toggle local echoing on/off", 0, &echoc },
        !           809: #endif
        !           810:     { "escape",        "character to escape back to telnet command mode", 0, &escape },
        !           811:     { "tracefile", "file to write trace intormation to", SetNetTrace, (cc_t *)NetTraceFile},
        !           812:     { " ", "" },
        !           813:     { " ", "The following need 'localchars' to be toggled true", 0, 0 },
        !           814:     { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp },
        !           815:     { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
        !           816:     { "quit",  "character to cause an Abort process", 0, termQuitCharp },
        !           817:     { "eof",   "character to cause an EOF ", 0, termEofCharp },
        !           818:     { " ", "" },
        !           819:     { " ", "The following are for local editing in linemode", 0, 0 },
        !           820:     { "erase", "character to use to erase a character", 0, termEraseCharp },
        !           821:     { "kill",  "character to use to erase a line", 0, termKillCharp },
        !           822:     { "lnext", "character to use for literal next", 0, termLiteralNextCharp },
        !           823:     { "susp",  "character to cause a Suspend Process", 0, termSuspCharp },
        !           824:     { "reprint", "character to use for line reprint", 0, termRprntCharp },
        !           825:     { "worderase", "character to use to erase a word", 0, termWerasCharp },
        !           826:     { "start", "character to use for XON", 0, termStartCharp },
        !           827:     { "stop",  "character to use for XOFF", 0, termStopCharp },
        !           828:     { "forw1", "alternate end of line character", 0, termForw1Charp },
        !           829:     { "forw2", "alternate end of line character", 0, termForw2Charp },
        !           830:     { 0 }
        !           831: };
        !           832: 
        !           833: #ifdef CRAY
        !           834: /* Work around compiler bug */
        !           835: _setlist_init()
        !           836: {
        !           837: #ifndef        KLUDGELINEMODE
        !           838: #define        N 4
        !           839: #else
        !           840: #define        N 5
        !           841: #endif
        !           842:        Setlist[N+0].charp = &termFlushChar;
        !           843:        Setlist[N+1].charp = &termIntChar;
        !           844:        Setlist[N+2].charp = &termQuitChar;
        !           845:        Setlist[N+3].charp = &termEofChar;
        !           846:        Setlist[N+6].charp = &termEraseChar;
        !           847:        Setlist[N+7].charp = &termKillChar;
        !           848:        Setlist[N+8].charp = &termLiteralNextChar;
        !           849:        Setlist[N+9].charp = &termSuspChar;
        !           850:        Setlist[N+10].charp = &termRprntChar;
        !           851:        Setlist[N+11].charp = &termWerasChar;
        !           852:        Setlist[N+12].charp = &termStartChar;
        !           853:        Setlist[N+13].charp = &termStopChar;
        !           854:        Setlist[N+14].charp = &termForw1Char;
        !           855:        Setlist[N+15].charp = &termForw2Char;
        !           856: #undef N
        !           857: }
        !           858: #endif /* CRAY */
        !           859: 
        !           860: static char **
        !           861: getnextset(name)
        !           862: char *name;
        !           863: {
        !           864:     struct setlist *c = (struct setlist *)name;
        !           865: 
        !           866:     return (char **) (c+1);
        !           867: }
        !           868: 
        !           869: static struct setlist *
        !           870: getset(name)
        !           871: char *name;
        !           872: {
        !           873:     return (struct setlist *) genget(name, (char **) Setlist, getnextset);
        !           874: }
        !           875: 
        !           876: set_escape_char(s)
        !           877: char *s;
        !           878: {
        !           879:        escape = (s && *s) ? special(s) : -1;
        !           880:        printf("escape character is '%s'.\n", control(escape));
        !           881: }
        !           882: 
        !           883: static
        !           884: setcmd(argc, argv)
        !           885: int    argc;
        !           886: char   *argv[];
        !           887: {
        !           888:     int value;
        !           889:     struct setlist *ct;
        !           890:     struct togglelist *c;
        !           891: 
        !           892:     if (argc < 2 || argc > 3) {
        !           893:        printf("Format is 'set Name Value'\n'set ?' for help.\n");
        !           894:        return 0;
        !           895:     }
        !           896:     if ((argc == 2) &&
        !           897:                ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) {
        !           898:        for (ct = Setlist; ct->name; ct++)
        !           899:            printf("%-15s %s\n", ct->name, ct->help);
        !           900:        printf("\n");
        !           901:        settogglehelp(1);
        !           902:        printf("%-15s %s\n", "?", "display help information");
        !           903:        return 0;
        !           904:     }
        !           905: 
        !           906:     ct = getset(argv[1]);
        !           907:     if (ct == 0) {
        !           908:        c = gettoggle(argv[1]);
        !           909:        if (c == 0) {
        !           910:            fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
        !           911:                        argv[1]);
        !           912:            return 0;
        !           913:        } else if (Ambiguous(c)) {
        !           914:            fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
        !           915:                        argv[1]);
        !           916:            return 0;
        !           917:        }
        !           918:        if (c->variable) {
        !           919:            if ((argc == 2) || (strcmp("on", argv[2]) == 0))
        !           920:                *c->variable = 1;
        !           921:            else if (strcmp("off", argv[2]) == 0)
        !           922:                *c->variable = 0;
        !           923:            else {
        !           924:                printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
        !           925:                return 0;
        !           926:            }
        !           927:            if (c->actionexplanation) {
        !           928:                printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !           929:                                                        c->actionexplanation);
        !           930:            }
        !           931:        }
        !           932:        if (c->handler)
        !           933:            (*c->handler)(1);
        !           934:     } else if (argc != 3) {
        !           935:        printf("Format is 'set Name Value'\n'set ?' for help.\n");
        !           936:        return 0;
        !           937:     } else if (Ambiguous(ct)) {
        !           938:        fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
        !           939:                        argv[1]);
        !           940:        return 0;
        !           941:     } else if (ct->handler) {
        !           942:        (*ct->handler)(argv[2]);
        !           943:        printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
        !           944:     } else {
        !           945:        if (strcmp("off", argv[2])) {
        !           946:            value = special(argv[2]);
        !           947:        } else {
        !           948:            value = -1;
        !           949:        }
        !           950:        *(ct->charp) = (cc_t)value;
        !           951:        printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        !           952:     }
        !           953:     slc_check();
        !           954:     return 1;
        !           955: }
        !           956: 
        !           957: static
        !           958: unsetcmd(argc, argv)
        !           959: int    argc;
        !           960: char   *argv[];
        !           961: {
        !           962:     struct setlist *ct;
        !           963:     struct togglelist *c;
        !           964:     register char *name;
        !           965: 
        !           966:     if (argc < 2) {
        !           967:        fprintf(stderr,
        !           968:            "Need an argument to 'unset' command.  'unset ?' for help.\n");
        !           969:        return 0;
        !           970:     }
        !           971:     if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) {
        !           972:        for (ct = Setlist; ct->name; ct++)
        !           973:            printf("%-15s %s\n", ct->name, ct->help);
        !           974:        printf("\n");
        !           975:        settogglehelp(0);
        !           976:        printf("%-15s %s\n", "?", "display help information");
        !           977:        return 0;
        !           978:     }
        !           979: 
        !           980:     argc--;
        !           981:     argv++;
        !           982:     while (argc--) {
        !           983:        name = *argv++;
        !           984:        ct = getset(name);
        !           985:        if (ct == 0) {
        !           986:            c = gettoggle(name);
        !           987:            if (c == 0) {
        !           988:                fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
        !           989:                        name);
        !           990:                return 0;
        !           991:            } else if (Ambiguous(c)) {
        !           992:                fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
        !           993:                        name);
        !           994:                return 0;
        !           995:            }
        !           996:            if (c->variable) {
        !           997:                *c->variable = 0;
        !           998:                if (c->actionexplanation) {
        !           999:                    printf("%s %s.\n", *c->variable? "Will" : "Won't",
        !          1000:                                                        c->actionexplanation);
        !          1001:                }
        !          1002:            }
        !          1003:            if (c->handler)
        !          1004:                (*c->handler)(0);
        !          1005:        } else if (Ambiguous(ct)) {
        !          1006:            fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
        !          1007:                        name);
        !          1008:            return 0;
        !          1009:        } else if (ct->handler) {
        !          1010:            (*ct->handler)(0);
        !          1011:            printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
        !          1012:        } else {
        !          1013:            *(ct->charp) = -1;
        !          1014:            printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
        !          1015:        }
        !          1016:     }
        !          1017:     return 1;
        !          1018: }
        !          1019: 
        !          1020: /*
        !          1021:  * The following are the data structures and routines for the
        !          1022:  * 'mode' command.
        !          1023:  */
        !          1024: #ifdef KLUDGELINEMODE
        !          1025: extern int kludgelinemode;
        !          1026: 
        !          1027: dokludgemode()
        !          1028: {
        !          1029:     kludgelinemode = 1;
        !          1030:     send_wont(TELOPT_LINEMODE, 1);
        !          1031:     send_dont(TELOPT_SGA, 1);
        !          1032:     send_dont(TELOPT_ECHO, 1);
        !          1033: }
        !          1034: #endif
        !          1035: 
        !          1036: static
        !          1037: dolinemode()
        !          1038: {
        !          1039: #ifdef KLUDGELINEMODE
        !          1040:     if (kludgelinemode)
        !          1041:        send_dont(TELOPT_SGA, 1);
        !          1042: #endif
        !          1043:     send_will(TELOPT_LINEMODE, 1);
        !          1044:     send_dont(TELOPT_ECHO, 1);
        !          1045:     return 1;
        !          1046: }
        !          1047: 
        !          1048: static
        !          1049: docharmode()
        !          1050: {
        !          1051: #ifdef KLUDGELINEMODE
        !          1052:     if (kludgelinemode)
        !          1053:        send_do(TELOPT_SGA, 1);
        !          1054:     else
        !          1055: #endif
        !          1056:     send_wont(TELOPT_LINEMODE, 1);
        !          1057:     send_do(TELOPT_ECHO, 1);
        !          1058:     return 1;
        !          1059: }
        !          1060: 
        !          1061: setmode(bit)
        !          1062: {
        !          1063:     return dolmmode(bit, 1);
        !          1064: }
        !          1065: 
        !          1066: clearmode(bit)
        !          1067: {
        !          1068:     return dolmmode(bit, 0);
        !          1069: }
        !          1070: 
        !          1071: dolmmode(bit, on)
        !          1072: int bit, on;
        !          1073: {
        !          1074:     char c;
        !          1075:     extern int linemode;
        !          1076: 
        !          1077:     if (my_want_state_is_wont(TELOPT_LINEMODE)) {
        !          1078:        printf("?Need to have LINEMODE option enabled first.\n");
        !          1079:        printf("'mode ?' for help.\n");
        !          1080:        return 0;
        !          1081:     }
        !          1082: 
        !          1083:     if (on)
        !          1084:        c = (linemode | bit);
        !          1085:     else
        !          1086:        c = (linemode & ~bit);
        !          1087:     lm_mode(&c, 1, 1);
        !          1088:     return 1;
        !          1089: }
        !          1090: 
        !          1091: struct modelist {
        !          1092:        char    *name;          /* command name */
        !          1093:        char    *help;          /* help string */
        !          1094:        int     (*handler)();   /* routine which executes command */
        !          1095:        int     needconnect;    /* Do we need to be connected to execute? */
        !          1096:        int     arg1;
        !          1097: };
        !          1098: 
        !          1099: extern int modehelp();
        !          1100: 
        !          1101: static struct modelist ModeList[] = {
        !          1102:     { "character", "Disable LINEMODE option",  docharmode, 1 },
        !          1103: #ifdef KLUDGELINEMODE
        !          1104:     { "",      "(or disable obsolete line-by-line mode)", 0 },
        !          1105: #endif
        !          1106:     { "line",  "Enable LINEMODE option",       dolinemode, 1 },
        !          1107: #ifdef KLUDGELINEMODE
        !          1108:     { "",      "(or enable obsolete line-by-line mode)", 0 },
        !          1109: #endif
        !          1110:     { "", "", 0 },
        !          1111:     { "",      "These require the LINEMODE option to be enabled", 0 },
        !          1112:     { "isig",  "Enable signal trapping",       setmode, 1, MODE_TRAPSIG },
        !          1113:     { "+isig", 0,                              setmode, 1, MODE_TRAPSIG },
        !          1114:     { "-isig", "Disable signal trapping",      clearmode, 1, MODE_TRAPSIG },
        !          1115:     { "edit",  "Enable character editing",     setmode, 1, MODE_EDIT },
        !          1116:     { "+edit", 0,                              setmode, 1, MODE_EDIT },
        !          1117:     { "-edit", "Disable character editing",    clearmode, 1, MODE_EDIT },
        !          1118:     { "softtabs", "Enable tab expansion",      setmode, 1, MODE_SOFT_TAB },
        !          1119:     { "+softtabs", 0,                          setmode, 1, MODE_SOFT_TAB },
        !          1120:     { "-softtabs", "Disable character editing",        clearmode, 1, MODE_SOFT_TAB },
        !          1121:     { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO },
        !          1122:     { "+litecho", 0,                           setmode, 1, MODE_LIT_ECHO },
        !          1123:     { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO },
        !          1124:     { "help",  0,                              modehelp, 0 },
        !          1125: #ifdef KLUDGELINEMODE
        !          1126:     { "kludgeline", 0,                         dokludgemode, 1 },
        !          1127: #endif
        !          1128:     { "", "", 0 },
        !          1129:     { "?",     "Print help information",       modehelp, 0 },
        !          1130:     { 0 },
        !          1131: };
        !          1132: 
        !          1133: static char **
        !          1134: getnextmode(name)
        !          1135: char *name;
        !          1136: {
        !          1137:     return (char **) (((struct modelist *)name)+1);
        !          1138: }
        !          1139: 
        !          1140: static struct modelist *
        !          1141: getmodecmd(name)
        !          1142: char *name;
        !          1143: {
        !          1144:     return (struct modelist *) genget(name, (char **) ModeList, getnextmode);
        !          1145: }
        !          1146: 
        !          1147: modehelp()
        !          1148: {
        !          1149:     struct modelist *mt;
        !          1150: 
        !          1151:     printf("format is:  'mode Mode', where 'Mode' is one of:\n\n");
        !          1152:     for (mt = ModeList; mt->name; mt++) {
        !          1153:        if (mt->help) {
        !          1154:            if (*mt->help)
        !          1155:                printf("%-15s %s\n", mt->name, mt->help);
        !          1156:            else
        !          1157:                printf("\n");
        !          1158:        }
        !          1159:     }
        !          1160:     return 0;
        !          1161: }
        !          1162: 
        !          1163: static
        !          1164: modecmd(argc, argv)
        !          1165: int    argc;
        !          1166: char   *argv[];
        !          1167: {
        !          1168:     struct modelist *mt;
        !          1169: 
        !          1170:     if (argc != 2) {
        !          1171:        printf("'mode' command requires an argument\n");
        !          1172:        printf("'mode ?' for help.\n");
        !          1173:     } else if ((mt = getmodecmd(argv[1])) == 0) {
        !          1174:        fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
        !          1175:     } else if (Ambiguous(mt)) {
        !          1176:        fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
        !          1177:     } else if (mt->needconnect && !connected) {
        !          1178:        printf("?Need to be connected first.\n");
        !          1179:        printf("'mode ?' for help.\n");
        !          1180:     } else if (mt->handler) {
        !          1181:        return (*mt->handler)(mt->arg1);
        !          1182:     }
        !          1183:     return 0;
        !          1184: }
        !          1185: 
        !          1186: /*
        !          1187:  * The following data structures and routines implement the
        !          1188:  * "display" command.
        !          1189:  */
        !          1190: 
        !          1191: static
        !          1192: display(argc, argv)
        !          1193: int    argc;
        !          1194: char   *argv[];
        !          1195: {
        !          1196: #define        dotog(tl)       if (tl->variable && tl->actionexplanation) { \
        !          1197:                            if (*tl->variable) { \
        !          1198:                                printf("will"); \
        !          1199:                            } else { \
        !          1200:                                printf("won't"); \
        !          1201:                            } \
        !          1202:                            printf(" %s.\n", tl->actionexplanation); \
        !          1203:                        }
        !          1204: 
        !          1205: #define        doset(sl)   if (sl->name && *sl->name != ' ') { \
        !          1206:                        if (sl->handler == 0) \
        !          1207:                            printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
        !          1208:                        else \
        !          1209:                            printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
        !          1210:                    }
        !          1211: 
        !          1212:     struct togglelist *tl;
        !          1213:     struct setlist *sl;
        !          1214: 
        !          1215:     if (argc == 1) {
        !          1216:        for (tl = Togglelist; tl->name; tl++) {
        !          1217:            dotog(tl);
        !          1218:        }
        !          1219:        printf("\n");
        !          1220:        for (sl = Setlist; sl->name; sl++) {
        !          1221:            doset(sl);
        !          1222:        }
        !          1223:     } else {
        !          1224:        int i;
        !          1225: 
        !          1226:        for (i = 1; i < argc; i++) {
        !          1227:            sl = getset(argv[i]);
        !          1228:            tl = gettoggle(argv[i]);
        !          1229:            if (Ambiguous(sl) || Ambiguous(tl)) {
        !          1230:                printf("?Ambiguous argument '%s'.\n", argv[i]);
        !          1231:                return 0;
        !          1232:            } else if (!sl && !tl) {
        !          1233:                printf("?Unknown argument '%s'.\n", argv[i]);
        !          1234:                return 0;
        !          1235:            } else {
        !          1236:                if (tl) {
        !          1237:                    dotog(tl);
        !          1238:                }
        !          1239:                if (sl) {
        !          1240:                    doset(sl);
        !          1241:                }
        !          1242:            }
        !          1243:        }
        !          1244:     }
        !          1245: /*@*/optionstatus();
        !          1246:     return 1;
        !          1247: #undef doset
        !          1248: #undef dotog
        !          1249: }
        !          1250: 
        !          1251: /*
        !          1252:  * The following are the data structures, and many of the routines,
        !          1253:  * relating to command processing.
        !          1254:  */
        !          1255: 
        !          1256: /*
        !          1257:  * Set the escape character.
        !          1258:  */
        !          1259: static
        !          1260: setescape(argc, argv)
        !          1261:        int argc;
        !          1262:        char *argv[];
        !          1263: {
        !          1264:        register char *arg;
        !          1265:        char buf[50];
        !          1266: 
        !          1267:        printf(
        !          1268:            "Deprecated usage - please use 'set escape%s%s' in the future.\n",
        !          1269:                                (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
        !          1270:        if (argc > 2)
        !          1271:                arg = argv[1];
        !          1272:        else {
        !          1273:                printf("new escape character: ");
        !          1274:                (void) gets(buf);
        !          1275:                arg = buf;
        !          1276:        }
        !          1277:        if (arg[0] != '\0')
        !          1278:                escape = arg[0];
        !          1279:        if (!In3270) {
        !          1280:                printf("Escape character is '%s'.\n", control(escape));
        !          1281:        }
        !          1282:        (void) fflush(stdout);
        !          1283:        return 1;
        !          1284: }
        !          1285: 
        !          1286: /*VARARGS*/
        !          1287: static
        !          1288: togcrmod()
        !          1289: {
        !          1290:     crmod = !crmod;
        !          1291:     printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
        !          1292:     printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
        !          1293:     (void) fflush(stdout);
        !          1294:     return 1;
        !          1295: }
        !          1296: 
        !          1297: /*VARARGS*/
        !          1298: suspend()
        !          1299: {
        !          1300: #ifdef SIGTSTP
        !          1301:     setcommandmode();
        !          1302:     {
        !          1303:        long oldrows, oldcols, newrows, newcols, err;
        !          1304: 
        !          1305:        err = TerminalWindowSize(&oldrows, &oldcols);
        !          1306:        (void) kill(0, SIGTSTP);
        !          1307:        err += TerminalWindowSize(&newrows, &newcols);
        !          1308:        if (connected && !err &&
        !          1309:            ((oldrows != newrows) || (oldcols != newcols))) {
        !          1310:                sendnaws();
        !          1311:        }
        !          1312:     }
        !          1313:     /* reget parameters in case they were changed */
        !          1314:     TerminalSaveState();
        !          1315:     setconnmode(0);
        !          1316: #else
        !          1317:     printf("Suspend is not supported.  Try the '!' command instead\n");
        !          1318: #endif
        !          1319:     return 1;
        !          1320: }
        !          1321: 
        !          1322: #if    !defined(TN3270)
        !          1323: /*ARGSUSED*/
        !          1324: shell(argc, argv)
        !          1325: int argc;
        !          1326: char *argv[];
        !          1327: {
        !          1328:     extern char *rindex();
        !          1329: 
        !          1330:     setcommandmode();
        !          1331:     switch(vfork()) {
        !          1332:     case -1:
        !          1333:        perror("Fork failed\n");
        !          1334:        break;
        !          1335: 
        !          1336:     case 0:
        !          1337:        {
        !          1338:            /*
        !          1339:             * Fire up the shell in the child.
        !          1340:             */
        !          1341:            register char *shell, *shellname;
        !          1342: 
        !          1343:            shell = getenv("SHELL");
        !          1344:            if (shell == NULL)
        !          1345:                shell = "/bin/sh";
        !          1346:            if ((shellname = rindex(shell, '/')) == 0)
        !          1347:                shellname = shell;
        !          1348:            else
        !          1349:                shellname++;
        !          1350:            if (argc > 1)
        !          1351:                execl(shell, shellname, "-c", &saveline[1], 0);
        !          1352:            else
        !          1353:                execl(shell, shellname, 0);
        !          1354:            perror("Execl");
        !          1355:            _exit(1);
        !          1356:        }
        !          1357:     default:
        !          1358:            (void)wait((int *)0);       /* Wait for the shell to complete */
        !          1359:     }
        !          1360: }
        !          1361: #endif /* !defined(TN3270) */
        !          1362: 
        !          1363: /*VARARGS*/
        !          1364: static
        !          1365: bye(argc, argv)
        !          1366: int    argc;           /* Number of arguments */
        !          1367: char   *argv[];        /* arguments */
        !          1368: {
        !          1369:     if (connected) {
        !          1370:        (void) shutdown(net, 2);
        !          1371:        printf("Connection closed.\n");
        !          1372:        (void) NetClose(net);
        !          1373:        connected = 0;
        !          1374:        /* reset options */
        !          1375:        tninit();
        !          1376: #if    defined(TN3270)
        !          1377:        SetIn3270();            /* Get out of 3270 mode */
        !          1378: #endif /* defined(TN3270) */
        !          1379:     }
        !          1380:     if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
        !          1381:        longjmp(toplevel, 1);
        !          1382:        /* NOTREACHED */
        !          1383:     }
        !          1384:     return 1;                  /* Keep lint, etc., happy */
        !          1385: }
        !          1386: 
        !          1387: /*VARARGS*/
        !          1388: quit()
        !          1389: {
        !          1390:        (void) call(bye, "bye", "fromquit", 0);
        !          1391:        Exit(0);
        !          1392:        /*NOTREACHED*/
        !          1393: }
        !          1394: 
        !          1395: /*
        !          1396:  * The SLC command.
        !          1397:  */
        !          1398: 
        !          1399: struct slclist {
        !          1400:        char    *name;
        !          1401:        char    *help;
        !          1402:        int     (*handler)();
        !          1403:        int     arg;
        !          1404: };
        !          1405: 
        !          1406: extern int slc_help();
        !          1407: extern int slc_mode_export(), slc_mode_import(), slcstate();
        !          1408: 
        !          1409: struct slclist SlcList[] = {
        !          1410:     { "export",        "Use local special character definitions",
        !          1411:                                                slc_mode_export,        0 },
        !          1412:     { "import",        "Use remote special character definitions",
        !          1413:                                                slc_mode_import,        1 },
        !          1414:     { "check", "Verify remote special character definitions",
        !          1415:                                                slc_mode_import,        0 },
        !          1416:     { "help",  0,                              slc_help,               0 },
        !          1417:     { "?",     "Print help information",       slc_help,               0 },
        !          1418:     { 0 },
        !          1419: };
        !          1420: 
        !          1421: static
        !          1422: slc_help()
        !          1423: {
        !          1424:     struct slclist *c;
        !          1425: 
        !          1426:     for (c = SlcList; c->name; c++) {
        !          1427:        if (c->help) {
        !          1428:            if (*c->help)
        !          1429:                printf("%-15s %s\n", c->name, c->help);
        !          1430:            else
        !          1431:                printf("\n");
        !          1432:        }
        !          1433:     }
        !          1434: }
        !          1435: 
        !          1436: static char **
        !          1437: getnextslc(name)
        !          1438: char *name;
        !          1439: {
        !          1440:     return (char **)(((struct slclist *)name)+1);
        !          1441: }
        !          1442: 
        !          1443: static struct slclist *
        !          1444: getslc(name)
        !          1445: char *name;
        !          1446: {
        !          1447:     return (struct slclist *)genget(name, (char **) SlcList, getnextslc);
        !          1448: }
        !          1449: 
        !          1450: static
        !          1451: slccmd(argc, argv)
        !          1452: int    argc;
        !          1453: char   *argv[];
        !          1454: {
        !          1455:     struct slclist *c;
        !          1456: 
        !          1457:     if (argc != 2) {
        !          1458:        fprintf(stderr,
        !          1459:            "Need an argument to 'slc' command.  'slc ?' for help.\n");
        !          1460:        return 0;
        !          1461:     }
        !          1462:     c = getslc(argv[1]);
        !          1463:     if (c == 0) {
        !          1464:         fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
        !          1465:                                argv[1]);
        !          1466:         return 0;
        !          1467:     }
        !          1468:     if (Ambiguous(c)) {
        !          1469:         fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
        !          1470:                                argv[1]);
        !          1471:         return 0;
        !          1472:     }
        !          1473:     (*c->handler)(c->arg);
        !          1474:     slcstate();
        !          1475:     return 1;
        !          1476: }
        !          1477: 
        !          1478: /*
        !          1479:  * The ENVIRON command.
        !          1480:  */
        !          1481: 
        !          1482: struct envlist {
        !          1483:        char    *name;
        !          1484:        char    *help;
        !          1485:        int     (*handler)();
        !          1486:        int     narg;
        !          1487: };
        !          1488: 
        !          1489: extern struct env_lst *env_define();
        !          1490: extern int env_undefine();
        !          1491: extern int env_export(), env_unexport();
        !          1492: extern int env_list(), env_help();
        !          1493: 
        !          1494: struct envlist EnvList[] = {
        !          1495:     { "define",        "Define an environment variable",
        !          1496:                                                (int (*)())env_define,  2 },
        !          1497:     { "undefine", "Undefine an environment variable",
        !          1498:                                                env_undefine,   1 },
        !          1499:     { "export",        "Mark an environment variable for automatic export",
        !          1500:                                                env_export,     1 },
        !          1501:     { "unexport", "Dont mark an environment variable for automatic export",
        !          1502:                                                env_unexport,   1 },
        !          1503:     { "list",  "List the current environment variables",
        !          1504:                                                env_list,       0 },
        !          1505:     { "help",  0,                              env_help,               0 },
        !          1506:     { "?",     "Print help information",       env_help,               0 },
        !          1507:     { 0 },
        !          1508: };
        !          1509: 
        !          1510: static
        !          1511: env_help()
        !          1512: {
        !          1513:     struct envlist *c;
        !          1514: 
        !          1515:     for (c = EnvList; c->name; c++) {
        !          1516:        if (c->help) {
        !          1517:            if (*c->help)
        !          1518:                printf("%-15s %s\n", c->name, c->help);
        !          1519:            else
        !          1520:                printf("\n");
        !          1521:        }
        !          1522:     }
        !          1523: }
        !          1524: 
        !          1525: static char **
        !          1526: getnextenv(name)
        !          1527: char *name;
        !          1528: {
        !          1529:     return (char **)(((struct envlist *)name)+1);
        !          1530: }
        !          1531: 
        !          1532: static struct envlist *
        !          1533: getenvcmd(name)
        !          1534: char *name;
        !          1535: {
        !          1536:     return (struct envlist *)genget(name, (char **) EnvList, getnextenv);
        !          1537: }
        !          1538: 
        !          1539: env_cmd(argc, argv)
        !          1540: int    argc;
        !          1541: char   *argv[];
        !          1542: {
        !          1543:     struct envlist *c;
        !          1544: 
        !          1545:     if (argc < 2) {
        !          1546:        fprintf(stderr,
        !          1547:            "Need an argument to 'environ' command.  'environ ?' for help.\n");
        !          1548:        return 0;
        !          1549:     }
        !          1550:     c = getenvcmd(argv[1]);
        !          1551:     if (c == 0) {
        !          1552:         fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
        !          1553:                                argv[1]);
        !          1554:         return 0;
        !          1555:     }
        !          1556:     if (Ambiguous(c)) {
        !          1557:         fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
        !          1558:                                argv[1]);
        !          1559:         return 0;
        !          1560:     }
        !          1561:     if (c->narg + 2 != argc) {
        !          1562:        fprintf(stderr,
        !          1563:            "Need %s%d argument%s to 'environ %s' command.  'environ ?' for help.\n",
        !          1564:                c->narg < argc + 2 ? "only " : "",
        !          1565:                c->narg, c->narg == 1 ? "" : "s", c->name);
        !          1566:        return 0;
        !          1567:     }
        !          1568:     (void)(*c->handler)(argv[2], argv[3]);
        !          1569:     return 1;
        !          1570: }
        !          1571: 
        !          1572: struct env_lst {
        !          1573:        struct env_lst *next;   /* pointer to next structure */
        !          1574:        struct env_lst *prev;   /* pointer to next structure */
        !          1575:        char *var;              /* pointer to variable name */
        !          1576:        char *value;            /* pointer to varialbe value */
        !          1577:        int export;             /* 1 -> export with default list of variables */
        !          1578: };
        !          1579: 
        !          1580: struct env_lst envlisthead;
        !          1581: 
        !          1582: struct env_lst *
        !          1583: env_find(var)
        !          1584: {
        !          1585:        register struct env_lst *ep;
        !          1586: 
        !          1587:        for (ep = envlisthead.next; ep; ep = ep->next) {
        !          1588:                if (strcmp(ep->var, var) == 0)
        !          1589:                        return(ep);
        !          1590:        }
        !          1591:        return(NULL);
        !          1592: }
        !          1593: 
        !          1594: env_init()
        !          1595: {
        !          1596:        extern char **environ, *index();
        !          1597:        register char **epp, *cp;
        !          1598:        register struct env_lst *ep;
        !          1599: 
        !          1600:        for (epp = environ; *epp; epp++) {
        !          1601:                if (cp = index(*epp, '=')) {
        !          1602:                        *cp = '\0';
        !          1603:                        ep = env_define(*epp, cp+1);
        !          1604:                        ep->export = 0;
        !          1605:                        *cp = '=';
        !          1606:                }
        !          1607:        }
        !          1608:        /*
        !          1609:         * Special case for DISPLAY variable.  If it is ":0.0" or
        !          1610:         * "unix:0.0", we have to get rid of "unix" and insert our
        !          1611:         * hostname.
        !          1612:         */
        !          1613:        if ((ep = env_find("DISPLAY")) &&
        !          1614:            ((*ep->value == ':') || (strncmp(ep->value, "unix:", 5) == 0))) {
        !          1615:                char hbuf[256+1];
        !          1616:                char *cp2 = index(ep->value, ':');
        !          1617: 
        !          1618:                gethostname(hbuf, 256);
        !          1619:                hbuf[256] = '\0';
        !          1620:                cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
        !          1621:                sprintf(cp, "%s%s", hbuf, cp2);
        !          1622:                free(ep->value);
        !          1623:                ep->value = cp;
        !          1624:        }
        !          1625: #ifdef notdef
        !          1626:        /*
        !          1627:         * If USER is not defined, but LOGNAME is, then add
        !          1628:         * USER with the value from LOGNAME.
        !          1629:         */
        !          1630:        if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME")))
        !          1631:                env_define("USER", ep->value);
        !          1632:        env_export("USER");
        !          1633: #endif
        !          1634:        env_export("DISPLAY");
        !          1635:        env_export("PRINTER");
        !          1636: }
        !          1637: 
        !          1638: struct env_lst *
        !          1639: env_define(var, value)
        !          1640: char *var, *value;
        !          1641: {
        !          1642:        register struct env_lst *ep;
        !          1643:        extern char *savestr();
        !          1644: 
        !          1645:        if (ep = env_find(var)) {
        !          1646:                if (ep->var)
        !          1647:                        free(ep->var);
        !          1648:                if (ep->value)
        !          1649:                        free(ep->value);
        !          1650:        } else {
        !          1651:                ep = (struct env_lst *)malloc(sizeof(struct env_lst));
        !          1652:                ep->next = envlisthead.next;
        !          1653:                envlisthead.next = ep;
        !          1654:                ep->prev = &envlisthead;
        !          1655:                if (ep->next)
        !          1656:                        ep->next->prev = ep;
        !          1657:        }
        !          1658:        ep->export = 1;
        !          1659:        ep->var = savestr(var);
        !          1660:        ep->value = savestr(value);
        !          1661:        return(ep);
        !          1662: }
        !          1663: 
        !          1664: env_undefine(var)
        !          1665: char *var;
        !          1666: {
        !          1667:        register struct env_lst *ep;
        !          1668: 
        !          1669:        if (ep = env_find(var)) {
        !          1670:                ep->prev->next = ep->next;
        !          1671:                ep->next->prev = ep->prev;
        !          1672:                if (ep->var)
        !          1673:                        free(ep->var);
        !          1674:                if (ep->value)
        !          1675:                        free(ep->value);
        !          1676:                free(ep);
        !          1677:        }
        !          1678: }
        !          1679: 
        !          1680: env_export(var)
        !          1681: char *var;
        !          1682: {
        !          1683:        register struct env_lst *ep;
        !          1684: 
        !          1685:        if (ep = env_find(var))
        !          1686:                ep->export = 1;
        !          1687: }
        !          1688: 
        !          1689: env_unexport(var)
        !          1690: char *var;
        !          1691: {
        !          1692:        register struct env_lst *ep;
        !          1693: 
        !          1694:        if (ep = env_find(var))
        !          1695:                ep->export = 0;
        !          1696: }
        !          1697: 
        !          1698: env_list()
        !          1699: {
        !          1700:        register struct env_lst *ep;
        !          1701: 
        !          1702:        for (ep = envlisthead.next; ep; ep = ep->next) {
        !          1703:                printf("%c %-20s %s\n", ep->export ? '*' : ' ',
        !          1704:                                        ep->var, ep->value);
        !          1705:        }
        !          1706: }
        !          1707: 
        !          1708: char *
        !          1709: env_default(init)
        !          1710: {
        !          1711:        static struct env_lst *nep = NULL;
        !          1712: 
        !          1713:        if (init) {
        !          1714:                nep = &envlisthead;
        !          1715:                return;
        !          1716:        }
        !          1717:        if (nep) {
        !          1718:                while (nep = nep->next) {
        !          1719:                        if (nep->export)
        !          1720:                                return(nep->var);
        !          1721:                }
        !          1722:        }
        !          1723:        return(NULL);
        !          1724: }
        !          1725: 
        !          1726: char *
        !          1727: env_getvalue(var)
        !          1728: char *var;
        !          1729: {
        !          1730:        register struct env_lst *ep;
        !          1731: 
        !          1732:        if (ep = env_find(var))
        !          1733:                return(ep->value);
        !          1734:        return(NULL);
        !          1735: }
        !          1736: 
        !          1737: char *
        !          1738: savestr(s)
        !          1739: register char *s;
        !          1740: {
        !          1741:        register char *ret;
        !          1742:        if (ret = (char *)malloc(strlen(s)+1))
        !          1743:                strcpy(ret, s);
        !          1744:        return(ret);
        !          1745: }
        !          1746: 
        !          1747: #if    defined(unix)
        !          1748: #ifdef notdef
        !          1749: /*
        !          1750:  * Some information about our file descriptors.
        !          1751:  */
        !          1752: 
        !          1753: char *
        !          1754: decodeflags(mask)
        !          1755: int mask;
        !          1756: {
        !          1757:     static char buffer[100];
        !          1758: #define do(m,s) \
        !          1759:        if (mask&(m)) { \
        !          1760:            strcat(buffer, (s)); \
        !          1761:        }
        !          1762: 
        !          1763:     buffer[0] = 0;                     /* Terminate it */
        !          1764: 
        !          1765: #ifdef FREAD
        !          1766:     do(FREAD, " FREAD");
        !          1767: #endif
        !          1768: #ifdef FWRITE
        !          1769:     do(FWRITE, " FWRITE");
        !          1770: #endif
        !          1771: #ifdef F_DUPFP
        !          1772:     do(F_DUPFD, " F_DUPFD");
        !          1773: #endif
        !          1774: #ifdef FNDELAY
        !          1775:     do(FNDELAY, " FNDELAY");
        !          1776: #endif
        !          1777: #ifdef FAPPEND
        !          1778:     do(FAPPEND, " FAPPEND");
        !          1779: #endif
        !          1780: #ifdef FMARK
        !          1781:     do(FMARK, " FMARK");
        !          1782: #endif
        !          1783: #ifdef FDEFER
        !          1784:     do(FDEFER, " FDEFER");
        !          1785: #endif
        !          1786: #ifdef FASYNC
        !          1787:     do(FASYNC, " FASYNC");
        !          1788: #endif
        !          1789: #ifdef FSHLOCK
        !          1790:     do(FSHLOCK, " FSHLOCK");
        !          1791: #endif
        !          1792: #ifdef FEXLOCK
        !          1793:     do(FEXLOCK, " FEXLOCK");
        !          1794: #endif
        !          1795: #ifdef FCREAT
        !          1796:     do(FCREAT, " FCREAT");
        !          1797: #endif
        !          1798: #ifdef FTRUNC
        !          1799:     do(FTRUNC, " FTRUNC");
        !          1800: #endif
        !          1801: #ifdef FEXCL
        !          1802:     do(FEXCL, " FEXCL");
        !          1803: #endif
        !          1804: 
        !          1805:     return buffer;
        !          1806: }
        !          1807: #undef do
        !          1808: #endif /* notdef */
        !          1809: 
        !          1810: #if defined(TN3270)
        !          1811: static void
        !          1812: filestuff(fd)
        !          1813: int fd;
        !          1814: {
        !          1815:     int res;
        !          1816: 
        !          1817: #ifdef F_GETOWN
        !          1818:     setconnmode(0);
        !          1819:     res = fcntl(fd, F_GETOWN, 0);
        !          1820:     setcommandmode();
        !          1821: 
        !          1822:     if (res == -1) {
        !          1823:        perror("fcntl");
        !          1824:        return;
        !          1825:     }
        !          1826:     printf("\tOwner is %d.\n", res);
        !          1827: #endif
        !          1828: 
        !          1829:     setconnmode(0);
        !          1830:     res = fcntl(fd, F_GETFL, 0);
        !          1831:     setcommandmode();
        !          1832: 
        !          1833:     if (res == -1) {
        !          1834:        perror("fcntl");
        !          1835:        return;
        !          1836:     }
        !          1837:     printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
        !          1838: }
        !          1839: #endif /* defined(TN3270) */
        !          1840: 
        !          1841: 
        !          1842: #endif /* defined(unix) */
        !          1843: 
        !          1844: /*
        !          1845:  * Print status about the connection.
        !          1846:  */
        !          1847: /*ARGSUSED*/
        !          1848: static
        !          1849: status(argc, argv)
        !          1850: int    argc;
        !          1851: char   *argv[];
        !          1852: {
        !          1853:     if (connected) {
        !          1854:        printf("Connected to %s.\n", hostname);
        !          1855:        if ((argc < 2) || strcmp(argv[1], "notmuch")) {
        !          1856:            int mode = getconnmode();
        !          1857: 
        !          1858:            if (my_want_state_is_will(TELOPT_LINEMODE)) {
        !          1859:                printf("Operating with LINEMODE option\n");
        !          1860:                printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
        !          1861:                printf("%s catching of signals\n",
        !          1862:                                        (mode&MODE_TRAPSIG) ? "Local" : "No");
        !          1863:                slcstate();
        !          1864: #ifdef KLUDGELINEMODE
        !          1865:            } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
        !          1866:                printf("Operating in obsolete linemode\n");
        !          1867: #endif
        !          1868:            } else {
        !          1869:                printf("Operating in single character mode\n");
        !          1870:                if (localchars)
        !          1871:                    printf("Catching signals locally\n");
        !          1872:            }
        !          1873:            printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
        !          1874:            if (my_want_state_is_will(TELOPT_LFLOW))
        !          1875:                printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
        !          1876:        }
        !          1877:     } else {
        !          1878:        printf("No connection.\n");
        !          1879:     }
        !          1880: #   if !defined(TN3270)
        !          1881:     printf("Escape character is '%s'.\n", control(escape));
        !          1882:     (void) fflush(stdout);
        !          1883: #   else /* !defined(TN3270) */
        !          1884:     if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
        !          1885:        printf("Escape character is '%s'.\n", control(escape));
        !          1886:     }
        !          1887: #   if defined(unix)
        !          1888:     if ((argc >= 2) && !strcmp(argv[1], "everything")) {
        !          1889:        printf("SIGIO received %d time%s.\n",
        !          1890:                                sigiocount, (sigiocount == 1)? "":"s");
        !          1891:        if (In3270) {
        !          1892:            printf("Process ID %d, process group %d.\n",
        !          1893:                                            getpid(), getpgrp(getpid()));
        !          1894:            printf("Terminal input:\n");
        !          1895:            filestuff(tin);
        !          1896:            printf("Terminal output:\n");
        !          1897:            filestuff(tout);
        !          1898:            printf("Network socket:\n");
        !          1899:            filestuff(net);
        !          1900:        }
        !          1901:     }
        !          1902:     if (In3270 && transcom) {
        !          1903:        printf("Transparent mode command is '%s'.\n", transcom);
        !          1904:     }
        !          1905: #   endif /* defined(unix) */
        !          1906:     (void) fflush(stdout);
        !          1907:     if (In3270) {
        !          1908:        return 0;
        !          1909:     }
        !          1910: #   endif /* defined(TN3270) */
        !          1911:     return 1;
        !          1912: }
        !          1913: 
        !          1914: 
        !          1915: #if    defined(NEED_GETTOS)
        !          1916: struct tosent {
        !          1917:        char    *t_name;        /* name */
        !          1918:        char    **t_aliases;    /* alias list */
        !          1919:        char    *t_proto;       /* protocol */
        !          1920:        int     t_tos;          /* Type Of Service bits */
        !          1921: };
        !          1922: 
        !          1923: struct tosent *
        !          1924: gettosbyname(name, proto)
        !          1925: char *name, *proto;
        !          1926: {
        !          1927:        static struct tosent te;
        !          1928:        static char *aliasp = 0;
        !          1929: 
        !          1930:        te.t_name = name;
        !          1931:        te.t_aliases = &aliasp;
        !          1932:        te.t_proto = proto;
        !          1933:        te.t_tos = 020; /* Low Delay bit */
        !          1934:        return(&te);
        !          1935: }
        !          1936: #endif
        !          1937: 
        !          1938: extern int autologin;
        !          1939: 
        !          1940: int
        !          1941: tn(argc, argv)
        !          1942:        int argc;
        !          1943:        char *argv[];
        !          1944: {
        !          1945:     register struct hostent *host = 0;
        !          1946:     struct sockaddr_in sin;
        !          1947:     struct servent *sp = 0;
        !          1948:     static char        hnamebuf[32];
        !          1949:     unsigned long temp, inet_addr();
        !          1950:     extern char *inet_ntoa();
        !          1951: #if    defined(SRCRT) && defined(IPPROTO_IP)
        !          1952:     char *srp = 0, *strrchr();
        !          1953:     unsigned long sourceroute(), srlen;
        !          1954: #endif
        !          1955: #if defined(HAS_IP_TOS) || defined(NEED_GETTOS)
        !          1956:     struct tosent *tp;
        !          1957: #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
        !          1958:     char *cmd, *hostp = 0, *portp = 0, *user = 0;
        !          1959: 
        !          1960: 
        !          1961:     if (connected) {
        !          1962:        printf("?Already connected to %s\n", hostname);
        !          1963:        return 0;
        !          1964:     }
        !          1965:     if (argc < 2) {
        !          1966:        (void) strcpy(line, "Connect ");
        !          1967:        printf("(to) ");
        !          1968:        (void) gets(&line[strlen(line)]);
        !          1969:        makeargv();
        !          1970:        argc = margc;
        !          1971:        argv = margv;
        !          1972:     }
        !          1973:     cmd = *argv;
        !          1974:     --argc; ++argv;
        !          1975:     while (argc) {
        !          1976:        if (strcmp(*argv, "-l") == 0) {
        !          1977:            --argc; ++argv;
        !          1978:            if (argc == 0)
        !          1979:                goto usage;
        !          1980:            user = *argv++;
        !          1981:            --argc;
        !          1982:            continue;
        !          1983:        }
        !          1984:        if (hostp == 0) {
        !          1985:            hostp = *argv++;
        !          1986:            --argc;
        !          1987:            continue;
        !          1988:        }
        !          1989:        if (portp == 0) {
        !          1990:            portp = *argv++;
        !          1991:            --argc;
        !          1992:            continue;
        !          1993:        }
        !          1994:     usage:
        !          1995:        printf("usage: %s [-l user] host-name [port]\n", cmd);
        !          1996:        return 0;
        !          1997:     }
        !          1998: #if    defined(SRCRT) && defined(IPPROTO_IP)
        !          1999:     if (hostp[0] == '@' || hostp[0] == '!') {
        !          2000:        if ((hostname = strrchr(hostp, ':')) == NULL)
        !          2001:            hostname = strrchr(hostp, '@');
        !          2002:        hostname++;
        !          2003:        srp = 0;
        !          2004:        temp = sourceroute(hostp, &srp, &srlen);
        !          2005:        if (temp == 0) {
        !          2006:            herror(srp);
        !          2007:            return 0;
        !          2008:        } else if (temp == -1) {
        !          2009:            printf("Bad source route option: %s\n", hostp);
        !          2010:            return 0;
        !          2011:        } else {
        !          2012:            sin.sin_addr.s_addr = temp;
        !          2013:            sin.sin_family = AF_INET;
        !          2014:        }
        !          2015:     } else {
        !          2016: #endif
        !          2017:        temp = inet_addr(hostp);
        !          2018:        if (temp != (unsigned long) -1) {
        !          2019:            sin.sin_addr.s_addr = temp;
        !          2020:            sin.sin_family = AF_INET;
        !          2021:            (void) strcpy(hnamebuf, hostp);
        !          2022:            hostname = hnamebuf;
        !          2023:        } else {
        !          2024:            host = gethostbyname(hostp);
        !          2025:            if (host) {
        !          2026:                sin.sin_family = host->h_addrtype;
        !          2027: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !          2028:                memcpy((caddr_t)&sin.sin_addr,
        !          2029:                                host->h_addr_list[0], host->h_length);
        !          2030: #else  /* defined(h_addr) */
        !          2031:                memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
        !          2032: #endif /* defined(h_addr) */
        !          2033:                hostname = host->h_name;
        !          2034:            } else {
        !          2035:                herror(hostp);
        !          2036:                return 0;
        !          2037:            }
        !          2038:        }
        !          2039: #if    defined(SRCRT) && defined(IPPROTO_IP)
        !          2040:     }
        !          2041: #endif
        !          2042:     if (portp) {
        !          2043:        if (*portp == '-') {
        !          2044:            portp++;
        !          2045:            telnetport = 1;
        !          2046:        } else
        !          2047:            telnetport = 0;
        !          2048:        sin.sin_port = atoi(portp);
        !          2049:        if (sin.sin_port == 0) {
        !          2050:            sp = getservbyname(portp, "tcp");
        !          2051:            if (sp)
        !          2052:                sin.sin_port = sp->s_port;
        !          2053:            else {
        !          2054:                printf("%s: bad port number\n", portp);
        !          2055:                return 0;
        !          2056:            }
        !          2057:        } else {
        !          2058: #if    !defined(htons)
        !          2059:            u_short htons();
        !          2060: #endif /* !defined(htons) */
        !          2061:            sin.sin_port = htons(sin.sin_port);
        !          2062:        }
        !          2063:     } else {
        !          2064:        if (sp == 0) {
        !          2065:            sp = getservbyname("telnet", "tcp");
        !          2066:            if (sp == 0) {
        !          2067:                fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
        !          2068:                return 0;
        !          2069:            }
        !          2070:            sin.sin_port = sp->s_port;
        !          2071:        }
        !          2072:        telnetport = 1;
        !          2073:     }
        !          2074:     printf("Trying %s...\n", inet_ntoa(sin.sin_addr));
        !          2075:     do {
        !          2076:        net = socket(AF_INET, SOCK_STREAM, 0);
        !          2077:        if (net < 0) {
        !          2078:            perror("telnet: socket");
        !          2079:            return 0;
        !          2080:        }
        !          2081: #if    defined(SRCRT) && defined(IPPROTO_IP)
        !          2082:        if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
        !          2083:                perror("setsockopt (IP_OPTIONS)");
        !          2084: #endif
        !          2085: #if    defined(HAS_IP_TOS) || defined(NEED_GETTOS)
        !          2086:        if ((tp = gettosbyname("telnet", "tcp")) &&
        !          2087:            (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
        !          2088:                perror("telnet: setsockopt TOS (ignored)");
        !          2089: #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */
        !          2090: 
        !          2091:        if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
        !          2092:                perror("setsockopt (SO_DEBUG)");
        !          2093:        }
        !          2094: 
        !          2095:        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
        !          2096: #if    defined(h_addr)         /* In 4.3, this is a #define */
        !          2097:            if (host && host->h_addr_list[1]) {
        !          2098:                int oerrno = errno;
        !          2099: 
        !          2100:                fprintf(stderr, "telnet: connect to address %s: ",
        !          2101:                                                inet_ntoa(sin.sin_addr));
        !          2102:                errno = oerrno;
        !          2103:                perror((char *)0);
        !          2104:                host->h_addr_list++;
        !          2105:                memcpy((caddr_t)&sin.sin_addr, 
        !          2106:                        host->h_addr_list[0], host->h_length);
        !          2107:                (void) NetClose(net);
        !          2108:                continue;
        !          2109:            }
        !          2110: #endif /* defined(h_addr) */
        !          2111:            perror("telnet: Unable to connect to remote host");
        !          2112:            return 0;
        !          2113:        }
        !          2114:        connected++;
        !          2115:     } while (connected == 0);
        !          2116:     cmdrc(hostp, hostname);
        !          2117:     if (autologin && user == NULL) {
        !          2118:        struct passwd *pw;
        !          2119:        uid_t uid = getuid();
        !          2120: 
        !          2121:        user = getlogin();
        !          2122:        if (user == NULL ||
        !          2123:            (pw = getpwnam(user)) && pw->pw_uid != uid)
        !          2124:                if (pw = getpwuid(uid))
        !          2125:                        user = pw->pw_name;
        !          2126:                else
        !          2127:                        user = NULL;
        !          2128:     }
        !          2129:     if (user) {
        !          2130:        env_define("USER", user);
        !          2131:        env_export("USER");
        !          2132:     }
        !          2133:     (void) call(status, "status", "notmuch", 0);
        !          2134:     if (setjmp(peerdied) == 0)
        !          2135:        telnet();
        !          2136:     (void) NetClose(net);
        !          2137:     ExitString("Connection closed by foreign host.\n",1);
        !          2138:     /*NOTREACHED*/
        !          2139: }
        !          2140: 
        !          2141: 
        !          2142: #define HELPINDENT (sizeof ("connect"))
        !          2143: 
        !          2144: static char
        !          2145:        openhelp[] =    "connect to a site",
        !          2146:        closehelp[] =   "close current connection",
        !          2147:        quithelp[] =    "exit telnet",
        !          2148:        statushelp[] =  "print status information",
        !          2149:        helphelp[] =    "print help information",
        !          2150:        sendhelp[] =    "transmit special characters ('send ?' for more)",
        !          2151:        sethelp[] =     "set operating parameters ('set ?' for more)",
        !          2152:        unsethelp[] =   "unset operating parameters ('unset ?' for more)",
        !          2153:        togglestring[] ="toggle operating parameters ('toggle ?' for more)",
        !          2154:        slchelp[] =     "change state of special charaters ('slc ?' for more)",
        !          2155:        displayhelp[] = "display operating parameters",
        !          2156: #if    defined(TN3270) && defined(unix)
        !          2157:        transcomhelp[] = "specify Unix command for transparent mode pipe",
        !          2158: #endif /* defined(TN3270) && defined(unix) */
        !          2159: #if    defined(unix)
        !          2160:        zhelp[] =       "suspend telnet",
        !          2161: #endif /* defined(unix) */
        !          2162:        shellhelp[] =   "invoke a subshell",
        !          2163:        envhelp[] =     "change environment variables ('environ ?' for more)",
        !          2164:        modestring[] = "try to enter line or character mode ('mode ?' for more)";
        !          2165: 
        !          2166: extern int     help(), shell();
        !          2167: 
        !          2168: static Command cmdtab[] = {
        !          2169:        { "close",      closehelp,      bye,            1 },
        !          2170:        { "display",    displayhelp,    display,        0 },
        !          2171:        { "mode",       modestring,     modecmd,        0 },
        !          2172:        { "open",       openhelp,       tn,             0 },
        !          2173:        { "quit",       quithelp,       quit,           0 },
        !          2174:        { "send",       sendhelp,       sendcmd,        0 },
        !          2175:        { "set",        sethelp,        setcmd,         0 },
        !          2176:        { "unset",      unsethelp,      unsetcmd,       0 },
        !          2177:        { "status",     statushelp,     status,         0 },
        !          2178:        { "toggle",     togglestring,   toggle,         0 },
        !          2179:        { "slc",        slchelp,        slccmd,         0 },
        !          2180: #if    defined(TN3270) && defined(unix)
        !          2181:        { "transcom",   transcomhelp,   settranscom,    0 },
        !          2182: #endif /* defined(TN3270) && defined(unix) */
        !          2183: #if    defined(unix)
        !          2184:        { "z",          zhelp,          suspend,        0 },
        !          2185: #endif /* defined(unix) */
        !          2186: #if    defined(TN3270)
        !          2187:        { "!",          shellhelp,      shell,          1 },
        !          2188: #else
        !          2189:        { "!",          shellhelp,      shell,          0 },
        !          2190: #endif
        !          2191:        { "environ",    envhelp,        env_cmd,        0 },
        !          2192:        { "?",          helphelp,       help,           0 },
        !          2193:        0
        !          2194: };
        !          2195: 
        !          2196: static char    crmodhelp[] =   "deprecated command -- use 'toggle crmod' instead";
        !          2197: static char    escapehelp[] =  "deprecated command -- use 'set escape' instead";
        !          2198: 
        !          2199: static Command cmdtab2[] = {
        !          2200:        { "help",       0,              help,           0 },
        !          2201:        { "escape",     escapehelp,     setescape,      0 },
        !          2202:        { "crmod",      crmodhelp,      togcrmod,       0 },
        !          2203:        0
        !          2204: };
        !          2205: 
        !          2206: 
        !          2207: /*
        !          2208:  * Call routine with argc, argv set from args (terminated by 0).
        !          2209:  */
        !          2210: 
        !          2211: /*VARARGS1*/
        !          2212: static
        !          2213: call(va_alist)
        !          2214: va_dcl
        !          2215: {
        !          2216:     va_list ap;
        !          2217:     typedef int (*intrtn_t)();
        !          2218:     intrtn_t routine;
        !          2219:     char *args[100];
        !          2220:     int argno = 0;
        !          2221: 
        !          2222:     va_start(ap);
        !          2223:     routine = (va_arg(ap, intrtn_t));
        !          2224:     while ((args[argno++] = va_arg(ap, char *)) != 0) {
        !          2225:        ;
        !          2226:     }
        !          2227:     va_end(ap);
        !          2228:     return (*routine)(argno-1, args);
        !          2229: }
        !          2230: 
        !          2231: 
        !          2232: static char **
        !          2233: getnextcmd(name)
        !          2234: char *name;
        !          2235: {
        !          2236:     Command *c = (Command *) name;
        !          2237: 
        !          2238:     return (char **) (c+1);
        !          2239: }
        !          2240: 
        !          2241: static Command *
        !          2242: getcmd(name)
        !          2243: char *name;
        !          2244: {
        !          2245:     Command *cm;
        !          2246: 
        !          2247:     if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) {
        !          2248:        return cm;
        !          2249:     } else {
        !          2250:        return (Command *) genget(name, (char **) cmdtab2, getnextcmd);
        !          2251:     }
        !          2252: }
        !          2253: 
        !          2254: void
        !          2255: command(top, tbuf, cnt)
        !          2256:        int top;
        !          2257:        char *tbuf;
        !          2258:        int cnt;
        !          2259: {
        !          2260:     register Command *c;
        !          2261: 
        !          2262:     setcommandmode();
        !          2263:     if (!top) {
        !          2264:        putchar('\n');
        !          2265: #if    defined(unix)
        !          2266:     } else {
        !          2267:        (void) signal(SIGINT, SIG_DFL);
        !          2268:        (void) signal(SIGQUIT, SIG_DFL);
        !          2269: #endif /* defined(unix) */
        !          2270:     }
        !          2271:     for (;;) {
        !          2272:        printf("%s> ", prompt);
        !          2273:        if (tbuf) {
        !          2274:            register char *cp;
        !          2275:            cp = line;
        !          2276:            while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
        !          2277:                cnt--;
        !          2278:            tbuf = 0;
        !          2279:            if (cp == line || *--cp != '\n' || cp == line)
        !          2280:                goto getline;
        !          2281:            *cp = '\0';
        !          2282:            printf("%s\n", line);
        !          2283:        } else {
        !          2284:        getline:
        !          2285:            if (gets(line) == NULL) {
        !          2286:                if (feof(stdin) || ferror(stdin)) {
        !          2287:                    (void) quit();
        !          2288:                    /*NOTREACHED*/
        !          2289:                }
        !          2290:                break;
        !          2291:            }
        !          2292:        }
        !          2293:        if (line[0] == 0)
        !          2294:            break;
        !          2295:        makeargv();
        !          2296:        if (margv[0] == 0) {
        !          2297:            break;
        !          2298:        }
        !          2299:        c = getcmd(margv[0]);
        !          2300:        if (Ambiguous(c)) {
        !          2301:            printf("?Ambiguous command\n");
        !          2302:            continue;
        !          2303:        }
        !          2304:        if (c == 0) {
        !          2305:            printf("?Invalid command\n");
        !          2306:            continue;
        !          2307:        }
        !          2308:        if (c->needconnect && !connected) {
        !          2309:            printf("?Need to be connected first.\n");
        !          2310:            continue;
        !          2311:        }
        !          2312:        if ((*c->handler)(margc, margv)) {
        !          2313:            break;
        !          2314:        }
        !          2315:     }
        !          2316:     if (!top) {
        !          2317:        if (!connected) {
        !          2318:            longjmp(toplevel, 1);
        !          2319:            /*NOTREACHED*/
        !          2320:        }
        !          2321: #if    defined(TN3270)
        !          2322:        if (shell_active == 0) {
        !          2323:            setconnmode(0);
        !          2324:        }
        !          2325: #else  /* defined(TN3270) */
        !          2326:        setconnmode(0);
        !          2327: #endif /* defined(TN3270) */
        !          2328:     }
        !          2329: }
        !          2330: 
        !          2331: /*
        !          2332:  * Help command.
        !          2333:  */
        !          2334: static
        !          2335: help(argc, argv)
        !          2336:        int argc;
        !          2337:        char *argv[];
        !          2338: {
        !          2339:        register Command *c;
        !          2340: 
        !          2341:        if (argc == 1) {
        !          2342:                printf("Commands may be abbreviated.  Commands are:\n\n");
        !          2343:                for (c = cmdtab; c->name; c++)
        !          2344:                        if (c->help) {
        !          2345:                                printf("%-*s\t%s\n", HELPINDENT, c->name,
        !          2346:                                                                    c->help);
        !          2347:                        }
        !          2348:                return 0;
        !          2349:        }
        !          2350:        while (--argc > 0) {
        !          2351:                register char *arg;
        !          2352:                arg = *++argv;
        !          2353:                c = getcmd(arg);
        !          2354:                if (Ambiguous(c))
        !          2355:                        printf("?Ambiguous help command %s\n", arg);
        !          2356:                else if (c == (Command *)0)
        !          2357:                        printf("?Invalid help command %s\n", arg);
        !          2358:                else
        !          2359:                        printf("%s\n", c->help);
        !          2360:        }
        !          2361:        return 0;
        !          2362: }
        !          2363: 
        !          2364: static char *rcname = 0;
        !          2365: static char rcbuf[128];
        !          2366: 
        !          2367: cmdrc(m1, m2)
        !          2368:        char *m1, *m2;
        !          2369: {
        !          2370:     register Command *c;
        !          2371:     FILE *rcfile;
        !          2372:     int gotmachine = 0;
        !          2373:     int l1 = strlen(m1);
        !          2374:     int l2 = strlen(m2);
        !          2375:     char m1save[64];
        !          2376: 
        !          2377:     strcpy(m1save, m1);
        !          2378:     m1 = m1save;
        !          2379: 
        !          2380:     if (rcname == 0) {
        !          2381:        rcname = getenv("HOME");
        !          2382:        if (rcname)
        !          2383:            strcpy(rcbuf, rcname);
        !          2384:        else
        !          2385:            rcbuf[0] = '\0';
        !          2386:        strcat(rcbuf, "/.telnetrc");
        !          2387:        rcname = rcbuf;
        !          2388:     }
        !          2389: 
        !          2390:     if ((rcfile = fopen(rcname, "r")) == 0) {
        !          2391:        return;
        !          2392:     }
        !          2393: 
        !          2394:     for (;;) {
        !          2395:        if (fgets(line, sizeof(line), rcfile) == NULL)
        !          2396:            break;
        !          2397:        if (line[0] == 0)
        !          2398:            break;
        !          2399:        if (line[0] == '#')
        !          2400:            continue;
        !          2401:        if (gotmachine == 0) {
        !          2402:            if (isspace(line[0]))
        !          2403:                continue;
        !          2404:            if (strncasecmp(line, m1, l1) == 0)
        !          2405:                strncpy(line, &line[l1], sizeof(line) - l1);
        !          2406:            else if (strncasecmp(line, m2, l2) == 0)
        !          2407:                strncpy(line, &line[l2], sizeof(line) - l2);
        !          2408:            else
        !          2409:                continue;
        !          2410:            gotmachine = 1;
        !          2411:        } else {
        !          2412:            if (!isspace(line[0])) {
        !          2413:                gotmachine = 0;
        !          2414:                continue;
        !          2415:            }
        !          2416:        }
        !          2417:        makeargv();
        !          2418:        if (margv[0] == 0)
        !          2419:            continue;
        !          2420:        c = getcmd(margv[0]);
        !          2421:        if (Ambiguous(c)) {
        !          2422:            printf("?Ambiguous command: %s\n", margv[0]);
        !          2423:            continue;
        !          2424:        }
        !          2425:        if (c == 0) {
        !          2426:            printf("?Invalid command: %s\n", margv[0]);
        !          2427:            continue;
        !          2428:        }
        !          2429:        /*
        !          2430:         * This should never happen...
        !          2431:         */
        !          2432:        if (c->needconnect && !connected) {
        !          2433:            printf("?Need to be connected first for %s.\n", margv[0]);
        !          2434:            continue;
        !          2435:        }
        !          2436:        (*c->handler)(margc, margv);
        !          2437:     }
        !          2438:     fclose(rcfile);
        !          2439: }
        !          2440: 
        !          2441: #if    defined(SRCRT) && defined(IPPROTO_IP)
        !          2442: 
        !          2443: /*
        !          2444:  * Source route is handed in as
        !          2445:  *     [!]@hop1@hop2...[@|:]dst
        !          2446:  * If the leading ! is present, it is a
        !          2447:  * strict source route, otherwise it is
        !          2448:  * assmed to be a loose source route.
        !          2449:  *
        !          2450:  * We fill in the source route option as
        !          2451:  *     hop1,hop2,hop3...dest
        !          2452:  * and return a pointer to hop1, which will
        !          2453:  * be the address to connect() to.
        !          2454:  *
        !          2455:  * Arguments:
        !          2456:  *     arg:    pointer to route list to decipher
        !          2457:  *
        !          2458:  *     cpp:    If *cpp is not equal to NULL, this is a
        !          2459:  *             pointer to a pointer to a character array
        !          2460:  *             that should be filled in with the option.
        !          2461:  *
        !          2462:  *     lenp:   pointer to an integer that contains the
        !          2463:  *             length of *cpp if *cpp != NULL.
        !          2464:  *
        !          2465:  * Return values:
        !          2466:  *
        !          2467:  *     Returns the address of the host to connect to.  If the
        !          2468:  *     return value is -1, there was a syntax error in the
        !          2469:  *     option, either unknown characters, or too many hosts.
        !          2470:  *     If the return value is 0, one of the hostnames in the
        !          2471:  *     path is unknown, and *cpp is set to point to the bad
        !          2472:  *     hostname.
        !          2473:  *
        !          2474:  *     *cpp:   If *cpp was equal to NULL, it will be filled
        !          2475:  *             in with a pointer to our static area that has
        !          2476:  *             the option filled in.  This will be 32bit aligned.
        !          2477:  * 
        !          2478:  *     *lenp:  This will be filled in with how long the option
        !          2479:  *             pointed to by *cpp is.
        !          2480:  *     
        !          2481:  */
        !          2482: unsigned long
        !          2483: sourceroute(arg, cpp, lenp)
        !          2484: char   *arg;
        !          2485: char   **cpp;
        !          2486: int    *lenp;
        !          2487: {
        !          2488:        static char lsr[44];
        !          2489:        char *cp, *cp2, *lsrp, *lsrep, *index();
        !          2490:        register int tmp;
        !          2491:        struct in_addr sin_addr;
        !          2492:        register struct hostent *host = 0;
        !          2493:        register char c;
        !          2494: 
        !          2495:        /*
        !          2496:         * Verify the arguments, and make sure we have
        !          2497:         * at least 7 bytes for the option.
        !          2498:         */
        !          2499:        if (cpp == NULL || lenp == NULL)
        !          2500:                return((unsigned long)-1);
        !          2501:        if (*cpp != NULL && *lenp < 7)
        !          2502:                return((unsigned long)-1);
        !          2503:        /*
        !          2504:         * Decide whether we have a buffer passed to us,
        !          2505:         * or if we need to use our own static buffer.
        !          2506:         */
        !          2507:        if (*cpp) {
        !          2508:                lsrp = *cpp;
        !          2509:                lsrep = lsrp + *lenp;
        !          2510:        } else {
        !          2511:                *cpp = lsrp = lsr;
        !          2512:                lsrep = lsrp + 44;
        !          2513:        }
        !          2514: 
        !          2515:        cp = arg;
        !          2516: 
        !          2517:        /*
        !          2518:         * Next, decide whether we have a loose source
        !          2519:         * route or a strict source route, and fill in
        !          2520:         * the begining of the option.
        !          2521:         */
        !          2522:        if (*cp == '!') {
        !          2523:                cp++;
        !          2524:                *lsrp++ = IPOPT_SSRR;
        !          2525:        } else
        !          2526:                *lsrp++ = IPOPT_LSRR;
        !          2527: 
        !          2528:        if (*cp != '@')
        !          2529:                return((unsigned long)-1);
        !          2530: 
        !          2531:        lsrp++;         /* skip over length, we'll fill it in later */
        !          2532:        *lsrp++ = 4;
        !          2533: 
        !          2534:        cp++;
        !          2535: 
        !          2536:        sin_addr.s_addr = 0;
        !          2537: 
        !          2538:        for (c = 0;;) {
        !          2539:                if (c == ':')
        !          2540:                        cp2 = 0;
        !          2541:                else for (cp2 = cp; c = *cp2; cp2++) {
        !          2542:                        if (c == ',') {
        !          2543:                                *cp2++ = '\0';
        !          2544:                                if (*cp2 == '@')
        !          2545:                                        cp2++;
        !          2546:                        } else if (c == '@') {
        !          2547:                                *cp2++ = '\0';
        !          2548:                        } else if (c == ':') {
        !          2549:                                *cp2++ = '\0';
        !          2550:                        } else
        !          2551:                                continue;
        !          2552:                        break;
        !          2553:                }
        !          2554:                if (!c)
        !          2555:                        cp2 = 0;
        !          2556: 
        !          2557:                if ((tmp = inet_addr(cp)) != -1) {
        !          2558:                        sin_addr.s_addr = tmp;
        !          2559:                } else if (host = gethostbyname(cp)) {
        !          2560: #if    defined(h_addr)
        !          2561:                        memcpy((caddr_t)&sin_addr,
        !          2562:                                host->h_addr_list[0], host->h_length);
        !          2563: #else
        !          2564:                        memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length);
        !          2565: #endif
        !          2566:                } else {
        !          2567:                        *cpp = cp;
        !          2568:                        return(0);
        !          2569:                }
        !          2570:                memcpy(lsrp, (char *)&sin_addr, 4);
        !          2571:                lsrp += 4;
        !          2572:                if (cp2)
        !          2573:                        cp = cp2;
        !          2574:                else
        !          2575:                        break;
        !          2576:                /*
        !          2577:                 * Check to make sure there is space for next address
        !          2578:                 */
        !          2579:                if (lsrp + 4 > lsrep)
        !          2580:                        return((unsigned long)-1);
        !          2581:        }
        !          2582:        if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) {
        !          2583:                *cpp = 0;
        !          2584:                *lenp = 0;
        !          2585:                return((unsigned long)-1);
        !          2586:        }
        !          2587:        *lsrp++ = IPOPT_NOP; /* 32 bit word align it */
        !          2588:        *lenp = lsrp - *cpp;
        !          2589:        return(sin_addr.s_addr);
        !          2590: }
        !          2591: #endif
        !          2592: 
        !          2593: #if    defined(NOSTRNCASECMP)
        !          2594: strncasecmp(p1, p2, len)
        !          2595: register char *p1, *p2;
        !          2596: int len;
        !          2597: {
        !          2598:     while (len--) {
        !          2599:        if (tolower(*p1) != tolower(*p2))
        !          2600:           return(tolower(*p1) - tolower(*p2));
        !          2601:        if (*p1 == '\0')
        !          2602:            return(0);
        !          2603:        p1++, p2++;
        !          2604:     }
        !          2605:     return(0);
        !          2606: }
        !          2607: #endif

unix.superglobalmegacorp.com

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