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