111758Ssam #ifndef lint 2*13076Ssam static char sccsid[] = "@(#)telnet.c 4.21 (Berkeley) 06/13/83"; 311758Ssam #endif 411758Ssam 56000Sroot /* 66000Sroot * User telnet program. 76000Sroot */ 89217Ssam #include <sys/types.h> 99217Ssam #include <sys/socket.h> 109972Ssam #include <sys/ioctl.h> 119217Ssam 129217Ssam #include <netinet/in.h> 139217Ssam 1412212Ssam #define TELOPTS 1512212Ssam #include <arpa/telnet.h> 1612212Ssam 176000Sroot #include <stdio.h> 186000Sroot #include <ctype.h> 196000Sroot #include <errno.h> 206000Sroot #include <signal.h> 216000Sroot #include <setjmp.h> 228345Ssam #include <netdb.h> 239217Ssam 246000Sroot #define strip(x) ((x)&0177) 256000Sroot 266000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 278378Ssam char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; 286000Sroot 296000Sroot char hisopts[256]; 306000Sroot char myopts[256]; 316000Sroot 326000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 336000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 346000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 356000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 366000Sroot 376000Sroot int connected; 386000Sroot int net; 399972Ssam int showoptions = 0; 407377Sfeldman int options; 4110339Ssam int debug = 0; 429972Ssam int crmod = 0; 436000Sroot char *prompt; 449972Ssam char escape = CTRL(]); 456000Sroot 466000Sroot char line[200]; 476000Sroot int margc; 486000Sroot char *margv[20]; 496000Sroot 506000Sroot jmp_buf toplevel; 516000Sroot jmp_buf peerdied; 526000Sroot 536000Sroot extern int errno; 546000Sroot 556000Sroot int tn(), quit(), suspend(), bye(), help(); 566024Ssam int setescape(), status(), toggle(), setoptions(); 5710603Ssam int setcrmod(), setdebug(); 586000Sroot 598378Ssam #define HELPINDENT (sizeof ("connect")) 606000Sroot 616000Sroot struct cmd { 6211758Ssam char *name; /* command name */ 6311758Ssam char *help; /* help string */ 6411758Ssam int (*handler)(); /* routine which executes command */ 656000Sroot }; 666000Sroot 6711758Ssam char openhelp[] = "connect to a site"; 6811758Ssam char closehelp[] = "close current connection"; 6911758Ssam char quithelp[] = "exit telnet"; 7011758Ssam char zhelp[] = "suspend telnet"; 7111758Ssam char debughelp[] = "toggle debugging"; 7211758Ssam char escapehelp[] = "set escape character"; 7311758Ssam char statushelp[] = "print status information"; 7411758Ssam char helphelp[] = "print help information"; 7511758Ssam char optionshelp[] = "toggle viewing of options processing"; 7611758Ssam char crmodhelp[] = "toggle mapping of received carriage returns"; 776000Sroot 786000Sroot struct cmd cmdtab[] = { 7911758Ssam { "open", openhelp, tn }, 8011758Ssam { "close", closehelp, bye }, 8111758Ssam { "quit", quithelp, quit }, 826000Sroot { "z", zhelp, suspend }, 8311758Ssam { "escape", escapehelp, setescape }, 8411758Ssam { "status", statushelp, status }, 8511758Ssam { "options", optionshelp, setoptions }, 8611758Ssam { "crmod", crmodhelp, setcrmod }, 8711758Ssam { "debug", debughelp, setdebug }, 8811758Ssam { "?", helphelp, help }, 896000Sroot 0 906000Sroot }; 916000Sroot 929972Ssam struct sockaddr_in sin; 936000Sroot 946000Sroot int intr(), deadpeer(); 956000Sroot char *control(); 966000Sroot struct cmd *getcmd(); 978345Ssam struct servent *sp; 986000Sroot 99*13076Ssam struct tchars otc; 100*13076Ssam struct ltchars oltc; 101*13076Ssam struct sgttyb ottyb; 1028378Ssam 1036000Sroot main(argc, argv) 1046000Sroot int argc; 1056000Sroot char *argv[]; 1066000Sroot { 1078345Ssam sp = getservbyname("telnet", "tcp"); 1088345Ssam if (sp == 0) { 1098345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 1108345Ssam exit(1); 1118345Ssam } 112*13076Ssam ioctl(0, TIOCGETP, (char *)&ottyb); 113*13076Ssam ioctl(0, TIOCGETC, (char *)&otc); 114*13076Ssam ioctl(0, TIOCGLTC, (char *)&oltc); 1156000Sroot setbuf(stdin, 0); 1166000Sroot setbuf(stdout, 0); 1176000Sroot prompt = argv[0]; 1187377Sfeldman if (argc > 1 && !strcmp(argv[1], "-d")) 1197377Sfeldman options = SO_DEBUG, argv++, argc--; 1206000Sroot if (argc != 1) { 1216000Sroot if (setjmp(toplevel) != 0) 1226000Sroot exit(0); 1236000Sroot tn(argc, argv); 1246000Sroot } 1256000Sroot setjmp(toplevel); 1266000Sroot for (;;) 1276000Sroot command(1); 1286000Sroot } 1296000Sroot 1308377Ssam char *hostname; 1318377Ssam char hnamebuf[32]; 1326000Sroot 1336000Sroot tn(argc, argv) 1346000Sroot int argc; 1356000Sroot char *argv[]; 1366000Sroot { 1376000Sroot register int c; 1388377Ssam register struct hostent *host; 1396000Sroot 1406000Sroot if (connected) { 1418377Ssam printf("?Already connected to %s\n", hostname); 1426000Sroot return; 1436000Sroot } 1446000Sroot if (argc < 2) { 1456000Sroot strcpy(line, "Connect "); 1466000Sroot printf("(to) "); 1476000Sroot gets(&line[strlen(line)]); 1486000Sroot makeargv(); 1496000Sroot argc = margc; 1506000Sroot argv = margv; 1516000Sroot } 1526000Sroot if (argc > 3) { 1536000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1546000Sroot return; 1556000Sroot } 1568345Ssam host = gethostbyname(argv[1]); 1578377Ssam if (host) { 1589217Ssam sin.sin_family = host->h_addrtype; 1599217Ssam bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length); 1608377Ssam hostname = host->h_name; 1618377Ssam } else { 1629217Ssam sin.sin_family = AF_INET; 1638377Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1648377Ssam if (sin.sin_addr.s_addr == -1) { 1658377Ssam printf("%s: unknown host\n", argv[1]); 1668377Ssam return; 1678377Ssam } 1688377Ssam strcpy(hnamebuf, argv[1]); 1698377Ssam hostname = hnamebuf; 1706000Sroot } 1718345Ssam sin.sin_port = sp->s_port; 1726024Ssam if (argc == 3) { 1736024Ssam sin.sin_port = atoi(argv[2]); 1746024Ssam if (sin.sin_port < 0) { 1756024Ssam printf("%s: bad port number\n", argv[2]); 1766024Ssam return; 1776024Ssam } 1789968Ssam sin.sin_port = htons(sin.sin_port); 1796024Ssam } 1809287Ssam net = socket(AF_INET, SOCK_STREAM, 0, 0); 1819217Ssam if (net < 0) { 1829217Ssam perror("telnet: socket"); 1836000Sroot return; 1846000Sroot } 18511758Ssam if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 18611758Ssam perror("setsockopt (SO_DEBUG)"); 18712989Ssam signal(SIGINT, intr); 18812989Ssam signal(SIGPIPE, deadpeer); 1896000Sroot printf("Trying...\n"); 1909217Ssam if (connect(net, (caddr_t)&sin, sizeof (sin), 0) < 0) { 1919217Ssam perror("telnet: connect"); 19212989Ssam signal(SIGINT, SIG_DFL); 1936000Sroot return; 1946000Sroot } 1956000Sroot connected++; 1966000Sroot call(status, "status", 0); 1976000Sroot if (setjmp(peerdied) == 0) 1986000Sroot telnet(net); 1996000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 2006000Sroot exit(1); 2016000Sroot } 2026000Sroot 2036000Sroot /* 2046000Sroot * Print status about the connection. 2056000Sroot */ 2066000Sroot /*VARARGS*/ 2076000Sroot status() 2086000Sroot { 2096000Sroot if (connected) 2108377Ssam printf("Connected to %s.\n", hostname); 2116000Sroot else 2126000Sroot printf("No connection.\n"); 2136000Sroot printf("Escape character is '%s'.\n", control(escape)); 2149972Ssam fflush(stdout); 2156000Sroot } 2166000Sroot 2176000Sroot makeargv() 2186000Sroot { 2196000Sroot register char *cp; 2206000Sroot register char **argp = margv; 2216000Sroot 2226000Sroot margc = 0; 2236000Sroot for (cp = line; *cp;) { 2246000Sroot while (isspace(*cp)) 2256000Sroot cp++; 2266000Sroot if (*cp == '\0') 2276000Sroot break; 2286000Sroot *argp++ = cp; 2296000Sroot margc += 1; 2306000Sroot while (*cp != '\0' && !isspace(*cp)) 2316000Sroot cp++; 2326000Sroot if (*cp == '\0') 2336000Sroot break; 2346000Sroot *cp++ = '\0'; 2356000Sroot } 2366000Sroot *argp++ = 0; 2376000Sroot } 2386000Sroot 2396000Sroot /*VARARGS*/ 2406000Sroot suspend() 2416000Sroot { 2426000Sroot register int save; 2436000Sroot 2446000Sroot save = mode(0); 2458378Ssam kill(0, SIGTSTP); 2468378Ssam /* reget parameters in case they were changed */ 247*13076Ssam ioctl(0, TIOCGETP, (char *)&ottyb); 248*13076Ssam ioctl(0, TIOCGETC, (char *)&otc); 249*13076Ssam ioctl(0, TIOCGLTC, (char *)&oltc); 2508378Ssam (void) mode(save); 2516000Sroot } 2526000Sroot 2536000Sroot /*VARARGS*/ 2546000Sroot bye() 2556000Sroot { 2568378Ssam register char *op; 2576000Sroot 2588378Ssam (void) mode(0); 2596000Sroot if (connected) { 26011758Ssam shutdown(net, 2); 2616000Sroot printf("Connection closed.\n"); 2626000Sroot close(net); 2636000Sroot connected = 0; 2648378Ssam /* reset his options */ 2658378Ssam for (op = hisopts; op < &hisopts[256]; op++) 2668378Ssam *op = 0; 2676000Sroot } 2686000Sroot } 2696000Sroot 2706000Sroot /*VARARGS*/ 2716000Sroot quit() 2726000Sroot { 2736000Sroot call(bye, "bye", 0); 2746000Sroot exit(0); 2756000Sroot } 2766000Sroot 2776000Sroot /* 2786000Sroot * Help command. 2796000Sroot */ 2806000Sroot help(argc, argv) 2816000Sroot int argc; 2826000Sroot char *argv[]; 2836000Sroot { 2846000Sroot register struct cmd *c; 2856000Sroot 2866000Sroot if (argc == 1) { 2876000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2886000Sroot for (c = cmdtab; c->name; c++) 2896000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2906000Sroot return; 2916000Sroot } 2926000Sroot while (--argc > 0) { 2936000Sroot register char *arg; 2946000Sroot arg = *++argv; 2956000Sroot c = getcmd(arg); 2966000Sroot if (c == (struct cmd *)-1) 2976000Sroot printf("?Ambiguous help command %s\n", arg); 2986000Sroot else if (c == (struct cmd *)0) 2996000Sroot printf("?Invalid help command %s\n", arg); 3006000Sroot else 3016000Sroot printf("%s\n", c->help); 3026000Sroot } 3036000Sroot } 3046000Sroot 3056000Sroot /* 3066000Sroot * Call routine with argc, argv set from args (terminated by 0). 3076000Sroot * VARARGS2 3086000Sroot */ 3096000Sroot call(routine, args) 3106000Sroot int (*routine)(); 3116000Sroot int args; 3126000Sroot { 3136000Sroot register int *argp; 3146000Sroot register int argc; 3156000Sroot 3166000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 3176000Sroot ; 3186000Sroot (*routine)(argc, &args); 3196000Sroot } 3206000Sroot 321*13076Ssam struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 322*13076Ssam struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 3239972Ssam 3246000Sroot mode(f) 3256000Sroot register int f; 3266000Sroot { 3278378Ssam static int prevmode = 0; 328*13076Ssam struct tchars *tc; 329*13076Ssam struct ltchars *ltc; 330*13076Ssam struct sgttyb sb; 331*13076Ssam int onoff, old; 3326000Sroot 3338378Ssam if (prevmode == f) 3348378Ssam return (f); 3358378Ssam old = prevmode; 3368378Ssam prevmode = f; 337*13076Ssam sb = ottyb; 3386000Sroot switch (f) { 3398378Ssam 3406000Sroot case 0: 3416000Sroot onoff = 0; 3429972Ssam tc = &otc; 343*13076Ssam ltc = &oltc; 3446000Sroot break; 3456000Sroot 3466000Sroot case 1: 3476000Sroot case 2: 348*13076Ssam sb.sg_flags |= CBREAK; 3498378Ssam if (f == 1) 350*13076Ssam sb.sg_flags &= ~(ECHO|CRMOD); 3518378Ssam else 352*13076Ssam sb.sg_flags |= ECHO|CRMOD; 353*13076Ssam sb.sg_erase = sb.sg_kill = -1; 3549972Ssam tc = ¬c; 355*13076Ssam ltc = &noltc; 3566000Sroot onoff = 1; 3579972Ssam break; 3589972Ssam 3599972Ssam default: 3609972Ssam return; 3616000Sroot } 362*13076Ssam ioctl(fileno(stdin), TIOCSLTC, (char *)ltc); 363*13076Ssam ioctl(fileno(stdin), TIOCSETC, (char *)tc); 364*13076Ssam ioctl(fileno(stdin), TIOCSETP, (char *)&sb); 3656000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3666000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3676000Sroot return (old); 3686000Sroot } 3696000Sroot 3706000Sroot char sibuf[BUFSIZ], *sbp; 3716000Sroot char tibuf[BUFSIZ], *tbp; 3726000Sroot int scc, tcc; 3736000Sroot 3746000Sroot /* 3756000Sroot * Select from tty and network... 3766000Sroot */ 3776000Sroot telnet(s) 3786000Sroot int s; 3796000Sroot { 3806000Sroot register int c; 3816000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3826000Sroot int on = 1; 3836000Sroot 3848378Ssam (void) mode(2); 3856000Sroot ioctl(s, FIONBIO, &on); 3866000Sroot for (;;) { 3876000Sroot int ibits = 0, obits = 0; 3886000Sroot 3896000Sroot if (nfrontp - nbackp) 3906000Sroot obits |= (1 << s); 3916000Sroot else 3926000Sroot ibits |= (1 << tin); 3936000Sroot if (tfrontp - tbackp) 3946000Sroot obits |= (1 << tout); 3956000Sroot else 3966000Sroot ibits |= (1 << s); 3976000Sroot if (scc < 0 && tcc < 0) 3986000Sroot break; 3999217Ssam select(16, &ibits, &obits, 0, 0); 4006000Sroot if (ibits == 0 && obits == 0) { 4016000Sroot sleep(5); 4026000Sroot continue; 4036000Sroot } 4046000Sroot 4056000Sroot /* 4066000Sroot * Something to read from the network... 4076000Sroot */ 4086000Sroot if (ibits & (1 << s)) { 4098378Ssam scc = read(s, sibuf, sizeof (sibuf)); 4106000Sroot if (scc < 0 && errno == EWOULDBLOCK) 4116000Sroot scc = 0; 4126000Sroot else { 4136000Sroot if (scc <= 0) 4146000Sroot break; 4156000Sroot sbp = sibuf; 4166000Sroot } 4176000Sroot } 4186000Sroot 4196000Sroot /* 4206000Sroot * Something to read from the tty... 4216000Sroot */ 4226000Sroot if (ibits & (1 << tin)) { 4238378Ssam tcc = read(tin, tibuf, sizeof (tibuf)); 4246000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 4256000Sroot tcc = 0; 4266000Sroot else { 4276000Sroot if (tcc <= 0) 4286000Sroot break; 4296000Sroot tbp = tibuf; 4306000Sroot } 4316000Sroot } 4326000Sroot 4336000Sroot while (tcc > 0) { 4346000Sroot register int c; 4356000Sroot 4366000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 4376000Sroot break; 4386000Sroot c = *tbp++ & 0377, tcc--; 4396000Sroot if (strip(c) == escape) { 4406000Sroot command(0); 4416000Sroot tcc = 0; 4426000Sroot break; 4436000Sroot } 44411758Ssam if (c == IAC) 44511758Ssam *nfrontp++ = c; 4466000Sroot *nfrontp++ = c; 4476000Sroot } 4486000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4496000Sroot netflush(s); 4506000Sroot if (scc > 0) 4516000Sroot telrcv(); 4526000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4536000Sroot ttyflush(tout); 4546000Sroot } 4558378Ssam (void) mode(0); 4566000Sroot } 4576000Sroot 4586000Sroot command(top) 4596000Sroot int top; 4606000Sroot { 4616000Sroot register struct cmd *c; 4626000Sroot int oldmode, wasopen; 4636000Sroot 4646000Sroot oldmode = mode(0); 4656000Sroot if (!top) 4666000Sroot putchar('\n'); 4676000Sroot else 46812989Ssam signal(SIGINT, SIG_DFL); 4696000Sroot for (;;) { 4706000Sroot printf("%s> ", prompt); 4716000Sroot if (gets(line) == 0) 4726000Sroot break; 4736000Sroot if (line[0] == 0) 4746000Sroot break; 4756000Sroot makeargv(); 4766000Sroot c = getcmd(margv[0]); 4776000Sroot if (c == (struct cmd *)-1) { 4786000Sroot printf("?Ambiguous command\n"); 4796000Sroot continue; 4806000Sroot } 4816000Sroot if (c == 0) { 4826000Sroot printf("?Invalid command\n"); 4836000Sroot continue; 4846000Sroot } 4856000Sroot (*c->handler)(margc, margv); 4866000Sroot if (c->handler != help) 4876000Sroot break; 4886000Sroot } 4896000Sroot if (!top) { 4906000Sroot if (!connected) 4916000Sroot longjmp(toplevel, 1); 4928378Ssam (void) mode(oldmode); 4936000Sroot } 4946000Sroot } 4956000Sroot 4966000Sroot /* 4976000Sroot * Telnet receiver states for fsm 4986000Sroot */ 4996000Sroot #define TS_DATA 0 5006000Sroot #define TS_IAC 1 5016000Sroot #define TS_WILL 2 5026000Sroot #define TS_WONT 3 5036000Sroot #define TS_DO 4 5046000Sroot #define TS_DONT 5 5056000Sroot 5066000Sroot telrcv() 5076000Sroot { 5086000Sroot register int c; 5096000Sroot static int state = TS_DATA; 5106000Sroot 5116000Sroot while (scc > 0) { 5126000Sroot c = *sbp++ & 0377, scc--; 5136000Sroot switch (state) { 5146000Sroot 5156000Sroot case TS_DATA: 5169972Ssam if (c == IAC) { 5176000Sroot state = TS_IAC; 5189972Ssam continue; 5199972Ssam } 5209972Ssam *tfrontp++ = c; 5219972Ssam /* 5229972Ssam * This hack is needed since we can't set 5239972Ssam * CRMOD on output only. Machines like MULTICS 5249972Ssam * like to send \r without \n; since we must 5259972Ssam * turn off CRMOD to get proper input, the mapping 5269972Ssam * is done here (sigh). 5279972Ssam */ 5289972Ssam if (c == '\r' && crmod) 5299972Ssam *tfrontp++ = '\n'; 5306000Sroot continue; 5316000Sroot 5326000Sroot case TS_IAC: 5336000Sroot switch (c) { 5346000Sroot 5356000Sroot case WILL: 5366000Sroot state = TS_WILL; 5376000Sroot continue; 5386000Sroot 5396000Sroot case WONT: 5406000Sroot state = TS_WONT; 5416000Sroot continue; 5426000Sroot 5436000Sroot case DO: 5446000Sroot state = TS_DO; 5456000Sroot continue; 5466000Sroot 5476000Sroot case DONT: 5486000Sroot state = TS_DONT; 5496000Sroot continue; 5506000Sroot 5516000Sroot case DM: 5526000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5536000Sroot break; 5546000Sroot 5556000Sroot case NOP: 5566000Sroot case GA: 5576000Sroot break; 5586000Sroot 5596000Sroot default: 5606000Sroot break; 5616000Sroot } 5626000Sroot state = TS_DATA; 5636000Sroot continue; 5646000Sroot 5656000Sroot case TS_WILL: 5668345Ssam printoption("RCVD", will, c, !hisopts[c]); 5676000Sroot if (!hisopts[c]) 5686000Sroot willoption(c); 5696000Sroot state = TS_DATA; 5706000Sroot continue; 5716000Sroot 5726000Sroot case TS_WONT: 5738345Ssam printoption("RCVD", wont, c, hisopts[c]); 5746000Sroot if (hisopts[c]) 5756000Sroot wontoption(c); 5766000Sroot state = TS_DATA; 5776000Sroot continue; 5786000Sroot 5796000Sroot case TS_DO: 5808345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5816000Sroot if (!myopts[c]) 5826000Sroot dooption(c); 5836000Sroot state = TS_DATA; 5846000Sroot continue; 5856000Sroot 5866000Sroot case TS_DONT: 5878345Ssam printoption("RCVD", dont, c, myopts[c]); 5886000Sroot if (myopts[c]) { 5896000Sroot myopts[c] = 0; 5906000Sroot sprintf(nfrontp, wont, c); 5918378Ssam nfrontp += sizeof (wont) - 2; 5928345Ssam printoption("SENT", wont, c); 5936000Sroot } 5946000Sroot state = TS_DATA; 5956000Sroot continue; 5966000Sroot } 5976000Sroot } 5986000Sroot } 5996000Sroot 6006000Sroot willoption(option) 6016000Sroot int option; 6026000Sroot { 6036000Sroot char *fmt; 6046000Sroot 6056000Sroot switch (option) { 6066000Sroot 6076000Sroot case TELOPT_ECHO: 6088378Ssam (void) mode(1); 6096000Sroot 6106000Sroot case TELOPT_SGA: 6116000Sroot hisopts[option] = 1; 6126000Sroot fmt = doopt; 6136000Sroot break; 6146000Sroot 6156000Sroot case TELOPT_TM: 6166000Sroot fmt = dont; 6176000Sroot break; 6186000Sroot 6196000Sroot default: 6206000Sroot fmt = dont; 6216000Sroot break; 6226000Sroot } 6236024Ssam sprintf(nfrontp, fmt, option); 6248378Ssam nfrontp += sizeof (dont) - 2; 6258345Ssam printoption("SENT", fmt, option); 6266000Sroot } 6276000Sroot 6286000Sroot wontoption(option) 6296000Sroot int option; 6306000Sroot { 6316000Sroot char *fmt; 6326000Sroot 6336000Sroot switch (option) { 6346000Sroot 6356000Sroot case TELOPT_ECHO: 6368378Ssam (void) mode(2); 6376000Sroot 6386000Sroot case TELOPT_SGA: 6396000Sroot hisopts[option] = 0; 6406000Sroot fmt = dont; 6416000Sroot break; 6426000Sroot 6436000Sroot default: 6446000Sroot fmt = dont; 6456000Sroot } 6466000Sroot sprintf(nfrontp, fmt, option); 6478378Ssam nfrontp += sizeof (doopt) - 2; 6488345Ssam printoption("SENT", fmt, option); 6496000Sroot } 6506000Sroot 6516000Sroot dooption(option) 6526000Sroot int option; 6536000Sroot { 6546000Sroot char *fmt; 6556000Sroot 6566000Sroot switch (option) { 6576000Sroot 6586000Sroot case TELOPT_TM: 6596000Sroot fmt = wont; 6606000Sroot break; 6616000Sroot 6626000Sroot case TELOPT_SGA: 6636000Sroot fmt = will; 6646000Sroot break; 6656000Sroot 6666000Sroot default: 6676000Sroot fmt = wont; 6686000Sroot break; 6696000Sroot } 6706000Sroot sprintf(nfrontp, fmt, option); 6718378Ssam nfrontp += sizeof (doopt) - 2; 6728345Ssam printoption("SENT", fmt, option); 6736000Sroot } 6746000Sroot 6756000Sroot /* 6766000Sroot * Set the escape character. 6776000Sroot */ 6786000Sroot setescape(argc, argv) 6796000Sroot int argc; 6806000Sroot char *argv[]; 6816000Sroot { 6826000Sroot register char *arg; 6836000Sroot char buf[50]; 6846000Sroot 6856000Sroot if (argc > 2) 6866000Sroot arg = argv[1]; 6876000Sroot else { 6886000Sroot printf("new escape character: "); 6896000Sroot gets(buf); 6906000Sroot arg = buf; 6916000Sroot } 6926000Sroot if (arg[0] != '\0') 6936000Sroot escape = arg[0]; 6946000Sroot printf("Escape character is '%s'.\n", control(escape)); 6959972Ssam fflush(stdout); 6966000Sroot } 6976000Sroot 6986024Ssam /*VARARGS*/ 6996024Ssam setoptions() 7006024Ssam { 7019972Ssam 7026024Ssam showoptions = !showoptions; 7036024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 7049972Ssam fflush(stdout); 7056024Ssam } 7066024Ssam 7079972Ssam /*VARARGS*/ 7089972Ssam setcrmod() 7099972Ssam { 7109972Ssam 7119972Ssam crmod = !crmod; 7129972Ssam printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); 7139972Ssam fflush(stdout); 7149972Ssam } 7159972Ssam 71610339Ssam /*VARARGS*/ 71710339Ssam setdebug() 71810339Ssam { 71910339Ssam 72010339Ssam debug = !debug; 72110339Ssam printf("%s turn on socket level debugging.\n", 72210339Ssam debug ? "Will" : "Wont"); 72310339Ssam fflush(stdout); 72411758Ssam if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 72511758Ssam perror("setsockopt (SO_DEBUG)"); 72610339Ssam } 72710339Ssam 7286000Sroot /* 7296000Sroot * Construct a control character sequence 7306000Sroot * for a special character. 7316000Sroot */ 7326000Sroot char * 7336000Sroot control(c) 7346000Sroot register int c; 7356000Sroot { 7366000Sroot static char buf[3]; 7376000Sroot 7386000Sroot if (c == 0177) 7396000Sroot return ("^?"); 7406000Sroot if (c >= 040) { 7416000Sroot buf[0] = c; 7426000Sroot buf[1] = 0; 7436000Sroot } else { 7446000Sroot buf[0] = '^'; 7456000Sroot buf[1] = '@'+c; 7466000Sroot buf[2] = 0; 7476000Sroot } 7486000Sroot return (buf); 7496000Sroot } 7506000Sroot 7516000Sroot struct cmd * 7526000Sroot getcmd(name) 7536000Sroot register char *name; 7546000Sroot { 7556000Sroot register char *p, *q; 7566000Sroot register struct cmd *c, *found; 7576000Sroot register int nmatches, longest; 7586000Sroot 7596000Sroot longest = 0; 7606000Sroot nmatches = 0; 7616000Sroot found = 0; 7626000Sroot for (c = cmdtab; p = c->name; c++) { 7636000Sroot for (q = name; *q == *p++; q++) 7646000Sroot if (*q == 0) /* exact match? */ 7656000Sroot return (c); 7666000Sroot if (!*q) { /* the name was a prefix */ 7676000Sroot if (q - name > longest) { 7686000Sroot longest = q - name; 7696000Sroot nmatches = 1; 7706000Sroot found = c; 7716000Sroot } else if (q - name == longest) 7726000Sroot nmatches++; 7736000Sroot } 7746000Sroot } 7756000Sroot if (nmatches > 1) 7766000Sroot return ((struct cmd *)-1); 7776000Sroot return (found); 7786000Sroot } 7796000Sroot 7806000Sroot deadpeer() 7816000Sroot { 7828378Ssam (void) mode(0); 7836000Sroot longjmp(peerdied, -1); 7846000Sroot } 7856000Sroot 7866000Sroot intr() 7876000Sroot { 7888378Ssam (void) mode(0); 7896000Sroot longjmp(toplevel, -1); 7906000Sroot } 7916000Sroot 7926000Sroot ttyflush(fd) 7936000Sroot { 7946000Sroot int n; 7956000Sroot 7966000Sroot if ((n = tfrontp - tbackp) > 0) 7976000Sroot n = write(fd, tbackp, n); 7988345Ssam if (n < 0) 7998345Ssam return; 8006000Sroot tbackp += n; 8016000Sroot if (tbackp == tfrontp) 8026000Sroot tbackp = tfrontp = ttyobuf; 8036000Sroot } 8046000Sroot 8056000Sroot netflush(fd) 8066000Sroot { 8076000Sroot int n; 8086000Sroot 8096000Sroot if ((n = nfrontp - nbackp) > 0) 8106000Sroot n = write(fd, nbackp, n); 8116501Ssam if (n < 0) { 8126501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 8138378Ssam (void) mode(0); 8148377Ssam perror(hostname); 8156501Ssam close(fd); 8166501Ssam longjmp(peerdied, -1); 8176501Ssam /*NOTREACHED*/ 8186501Ssam } 8196000Sroot n = 0; 8206501Ssam } 8216000Sroot nbackp += n; 8226000Sroot if (nbackp == nfrontp) 8236000Sroot nbackp = nfrontp = netobuf; 8246000Sroot } 8256024Ssam 8266293Sroot /*VARARGS*/ 8276293Sroot printoption(direction, fmt, option, what) 8286024Ssam char *direction, *fmt; 8296293Sroot int option, what; 8306024Ssam { 8318345Ssam if (!showoptions) 8328345Ssam return; 8336024Ssam printf("%s ", direction); 8346024Ssam if (fmt == doopt) 8356024Ssam fmt = "do"; 8366024Ssam else if (fmt == dont) 8376024Ssam fmt = "dont"; 8386024Ssam else if (fmt == will) 8396024Ssam fmt = "will"; 8406024Ssam else if (fmt == wont) 8416024Ssam fmt = "wont"; 8426024Ssam else 8436024Ssam fmt = "???"; 8446024Ssam if (option < TELOPT_SUPDUP) 8456293Sroot printf("%s %s", fmt, telopts[option]); 8466024Ssam else 8476293Sroot printf("%s %d", fmt, option); 8486293Sroot if (*direction == '<') { 8496293Sroot printf("\r\n"); 8506293Sroot return; 8516293Sroot } 8526293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 8536024Ssam } 854