|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.