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