1*9217Ssam static char sccsid[] = "@(#)telnet.c 4.12 (Berkeley) 11/14/82"; 26000Sroot /* 36000Sroot * User telnet program. 46000Sroot */ 5*9217Ssam #include <sys/types.h> 6*9217Ssam #include <sys/socket.h> 7*9217Ssam 8*9217Ssam #include <netinet/in.h> 9*9217Ssam 106000Sroot #include <stdio.h> 116000Sroot #include <ctype.h> 126000Sroot #include <errno.h> 136000Sroot #include <signal.h> 146000Sroot #include <sgtty.h> 156000Sroot #include <setjmp.h> 168345Ssam #include <netdb.h> 17*9217Ssam 186024Ssam #define TELOPTS 196000Sroot #include "telnet.h" 206000Sroot 216000Sroot #define ctrl(x) ((x) & 037) 226000Sroot #define strip(x) ((x)&0177) 236000Sroot 246000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 258378Ssam char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; 266000Sroot 276000Sroot char hisopts[256]; 286000Sroot char myopts[256]; 296000Sroot 306000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 316000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 326000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 336000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 346000Sroot 356000Sroot int connected; 366000Sroot int net; 376024Ssam int showoptions; 387377Sfeldman int options; 396000Sroot char *prompt; 407377Sfeldman char escape = ctrl(']'); 416000Sroot 426000Sroot char line[200]; 436000Sroot int margc; 446000Sroot char *margv[20]; 456000Sroot 466000Sroot jmp_buf toplevel; 476000Sroot jmp_buf peerdied; 486000Sroot 496000Sroot extern int errno; 506000Sroot 516000Sroot int tn(), quit(), suspend(), bye(), help(); 526024Ssam int setescape(), status(), toggle(), setoptions(); 536000Sroot 548378Ssam #define HELPINDENT (sizeof ("connect")) 556000Sroot 566000Sroot struct cmd { 576000Sroot char *name; 586000Sroot char *help; 596000Sroot int (*handler)(); 606000Sroot }; 616000Sroot 626000Sroot char ohelp[] = "connect to a site"; 636000Sroot char chelp[] = "close current connection"; 646000Sroot char qhelp[] = "exit telnet"; 656000Sroot char zhelp[] = "suspend telnet"; 666000Sroot char ehelp[] = "set escape character"; 676000Sroot char shelp[] = "print status information"; 686000Sroot char hhelp[] = "print help information"; 696024Ssam char phelp[] = "toggle viewing of options processing"; 706000Sroot 716000Sroot struct cmd cmdtab[] = { 726000Sroot { "open", ohelp, tn }, 736000Sroot { "close", chelp, bye }, 746000Sroot { "quit", qhelp, quit }, 756000Sroot { "z", zhelp, suspend }, 766000Sroot { "escape", ehelp, setescape }, 776000Sroot { "status", shelp, status }, 786024Ssam { "options", phelp, setoptions }, 796000Sroot { "?", hhelp, help }, 806000Sroot 0 816000Sroot }; 826000Sroot 838345Ssam struct sockaddr_in sin = { AF_INET }; 846000Sroot 856000Sroot int intr(), deadpeer(); 866000Sroot char *control(); 876000Sroot struct cmd *getcmd(); 888345Ssam struct servent *sp; 896000Sroot 908378Ssam struct sgttyb ostbuf; 918378Ssam struct tchars otchars; 928378Ssam int odisc; 938378Ssam 946000Sroot main(argc, argv) 956000Sroot int argc; 966000Sroot char *argv[]; 976000Sroot { 988345Ssam sp = getservbyname("telnet", "tcp"); 998345Ssam if (sp == 0) { 1008345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 1018345Ssam exit(1); 1028345Ssam } 1038378Ssam ioctl(0, TIOCGETP, (char *)&ostbuf); 1048378Ssam ioctl(0, TIOCGETC, (char *)&otchars); 1058378Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1066000Sroot setbuf(stdin, 0); 1076000Sroot setbuf(stdout, 0); 1086000Sroot prompt = argv[0]; 1097377Sfeldman if (argc > 1 && !strcmp(argv[1], "-d")) 1107377Sfeldman options = SO_DEBUG, argv++, argc--; 1116000Sroot if (argc != 1) { 1126000Sroot if (setjmp(toplevel) != 0) 1136000Sroot exit(0); 1146000Sroot tn(argc, argv); 1156000Sroot } 1166000Sroot setjmp(toplevel); 1176000Sroot for (;;) 1186000Sroot command(1); 1196000Sroot } 1206000Sroot 1218377Ssam char *hostname; 1228377Ssam char hnamebuf[32]; 1236000Sroot 1246000Sroot tn(argc, argv) 1256000Sroot int argc; 1266000Sroot char *argv[]; 1276000Sroot { 1286000Sroot register int c; 1298377Ssam register struct hostent *host; 1306000Sroot 1316000Sroot if (connected) { 1328377Ssam printf("?Already connected to %s\n", hostname); 1336000Sroot return; 1346000Sroot } 1356000Sroot if (argc < 2) { 1366000Sroot strcpy(line, "Connect "); 1376000Sroot printf("(to) "); 1386000Sroot gets(&line[strlen(line)]); 1396000Sroot makeargv(); 1406000Sroot argc = margc; 1416000Sroot argv = margv; 1426000Sroot } 1436000Sroot if (argc > 3) { 1446000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1456000Sroot return; 1466000Sroot } 1478345Ssam host = gethostbyname(argv[1]); 1488377Ssam if (host) { 149*9217Ssam sin.sin_family = host->h_addrtype; 150*9217Ssam bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length); 1518377Ssam hostname = host->h_name; 1528377Ssam } else { 153*9217Ssam sin.sin_family = AF_INET; 1548377Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1558377Ssam if (sin.sin_addr.s_addr == -1) { 1568377Ssam printf("%s: unknown host\n", argv[1]); 1578377Ssam return; 1588377Ssam } 1598377Ssam strcpy(hnamebuf, argv[1]); 1608377Ssam hostname = hnamebuf; 1616000Sroot } 1628345Ssam sin.sin_port = sp->s_port; 1636024Ssam if (argc == 3) { 1646024Ssam sin.sin_port = atoi(argv[2]); 1656024Ssam if (sin.sin_port < 0) { 1666024Ssam printf("%s: bad port number\n", argv[2]); 1676024Ssam return; 1686024Ssam } 1696024Ssam } 1708345Ssam sin.sin_port = htons(sin.sin_port); 171*9217Ssam net = socket(0, SOCK_STREAM, 0, 0); 172*9217Ssam if (net < 0) { 173*9217Ssam perror("telnet: socket"); 1746000Sroot return; 1756000Sroot } 1766000Sroot sigset(SIGINT, intr); 1776000Sroot sigset(SIGPIPE, deadpeer); 1786000Sroot printf("Trying...\n"); 179*9217Ssam if (connect(net, (caddr_t)&sin, sizeof (sin), 0) < 0) { 180*9217Ssam perror("telnet: connect"); 1816000Sroot sigset(SIGINT, SIG_DFL); 1826000Sroot return; 1836000Sroot } 1846000Sroot connected++; 1856000Sroot call(status, "status", 0); 1866000Sroot if (setjmp(peerdied) == 0) 1876000Sroot telnet(net); 1886000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1896000Sroot exit(1); 1906000Sroot } 1916000Sroot 1926000Sroot /* 1936000Sroot * Print status about the connection. 1946000Sroot */ 1956000Sroot /*VARARGS*/ 1966000Sroot status() 1976000Sroot { 1986000Sroot if (connected) 1998377Ssam printf("Connected to %s.\n", hostname); 2006000Sroot else 2016000Sroot printf("No connection.\n"); 2026000Sroot printf("Escape character is '%s'.\n", control(escape)); 2036000Sroot } 2046000Sroot 2056000Sroot makeargv() 2066000Sroot { 2076000Sroot register char *cp; 2086000Sroot register char **argp = margv; 2096000Sroot 2106000Sroot margc = 0; 2116000Sroot for (cp = line; *cp;) { 2126000Sroot while (isspace(*cp)) 2136000Sroot cp++; 2146000Sroot if (*cp == '\0') 2156000Sroot break; 2166000Sroot *argp++ = cp; 2176000Sroot margc += 1; 2186000Sroot while (*cp != '\0' && !isspace(*cp)) 2196000Sroot cp++; 2206000Sroot if (*cp == '\0') 2216000Sroot break; 2226000Sroot *cp++ = '\0'; 2236000Sroot } 2246000Sroot *argp++ = 0; 2256000Sroot } 2266000Sroot 2276000Sroot /*VARARGS*/ 2286000Sroot suspend() 2296000Sroot { 2306000Sroot register int save; 2316000Sroot 2326000Sroot save = mode(0); 2338378Ssam kill(0, SIGTSTP); 2348378Ssam /* reget parameters in case they were changed */ 2358378Ssam ioctl(0, TIOCGETP, (char *)&ostbuf); 2368378Ssam ioctl(0, TIOCGETC, (char *)&otchars); 2378378Ssam ioctl(0, TIOCGETD, (char *)&odisc); 2388378Ssam (void) mode(save); 2396000Sroot } 2406000Sroot 2416000Sroot /*VARARGS*/ 2426000Sroot bye() 2436000Sroot { 2446000Sroot int how = 2; 2458378Ssam register char *op; 2466000Sroot 2478378Ssam (void) mode(0); 2486000Sroot if (connected) { 249*9217Ssam #ifndef notdef 2506000Sroot ioctl(net, SIOCDONE, &how); 251*9217Ssam #endif 2526000Sroot printf("Connection closed.\n"); 2536000Sroot close(net); 2546000Sroot connected = 0; 2558378Ssam /* reset his options */ 2568378Ssam for (op = hisopts; op < &hisopts[256]; op++) 2578378Ssam *op = 0; 2586000Sroot } 2596000Sroot } 2606000Sroot 2616000Sroot /*VARARGS*/ 2626000Sroot quit() 2636000Sroot { 2646000Sroot call(bye, "bye", 0); 2656000Sroot exit(0); 2666000Sroot } 2676000Sroot 2686000Sroot /* 2696000Sroot * Help command. 2706000Sroot * Call each command handler with argc == 0 and argv[0] == name. 2716000Sroot */ 2726000Sroot help(argc, argv) 2736000Sroot int argc; 2746000Sroot char *argv[]; 2756000Sroot { 2766000Sroot register struct cmd *c; 2776000Sroot 2786000Sroot if (argc == 1) { 2796000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2806000Sroot for (c = cmdtab; c->name; c++) 2816000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2826000Sroot return; 2836000Sroot } 2846000Sroot while (--argc > 0) { 2856000Sroot register char *arg; 2866000Sroot arg = *++argv; 2876000Sroot c = getcmd(arg); 2886000Sroot if (c == (struct cmd *)-1) 2896000Sroot printf("?Ambiguous help command %s\n", arg); 2906000Sroot else if (c == (struct cmd *)0) 2916000Sroot printf("?Invalid help command %s\n", arg); 2926000Sroot else 2936000Sroot printf("%s\n", c->help); 2946000Sroot } 2956000Sroot } 2966000Sroot 2976000Sroot /* 2986000Sroot * Call routine with argc, argv set from args (terminated by 0). 2996000Sroot * VARARGS2 3006000Sroot */ 3016000Sroot call(routine, args) 3026000Sroot int (*routine)(); 3036000Sroot int args; 3046000Sroot { 3056000Sroot register int *argp; 3066000Sroot register int argc; 3076000Sroot 3086000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 3096000Sroot ; 3106000Sroot (*routine)(argc, &args); 3116000Sroot } 3126000Sroot 3136000Sroot mode(f) 3146000Sroot register int f; 3156000Sroot { 3166000Sroot struct sgttyb stbuf; 3178378Ssam static int prevmode = 0; 3188378Ssam struct tchars tchars; 3198378Ssam int onoff, disc, old; 3206000Sroot 3218378Ssam if (prevmode == f) 3228378Ssam return (f); 3238378Ssam old = prevmode; 3248378Ssam prevmode = f; 3258378Ssam stbuf = ostbuf; 3268378Ssam tchars = otchars; 3276000Sroot switch (f) { 3288378Ssam 3296000Sroot case 0: 3308378Ssam disc = odisc; 3316000Sroot onoff = 0; 3326000Sroot break; 3336000Sroot 3346000Sroot case 1: 3356000Sroot case 2: 3368378Ssam stbuf.sg_flags |= CBREAK; 3378378Ssam if (f == 1) 3388378Ssam stbuf.sg_flags &= ~ECHO; 3398378Ssam else 3408378Ssam stbuf.sg_flags |= ECHO; 3418378Ssam tchars.t_intrc = tchars.t_quitc = -1; 342*9217Ssam tchars.t_stopc = tchars.t_startc = -1; 3438378Ssam disc = OTTYDISC; 3446000Sroot onoff = 1; 3456000Sroot } 3468378Ssam ioctl(fileno(stdin), TIOCSETD, &disc); 3478378Ssam ioctl(fileno(stdin), TIOCSETC, &tchars); 3486000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 3496000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3506000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3516000Sroot return (old); 3526000Sroot } 3536000Sroot 3546000Sroot char sibuf[BUFSIZ], *sbp; 3556000Sroot char tibuf[BUFSIZ], *tbp; 3566000Sroot int scc, tcc; 3576000Sroot 3586000Sroot /* 3596000Sroot * Select from tty and network... 3606000Sroot */ 3616000Sroot telnet(s) 3626000Sroot int s; 3636000Sroot { 3646000Sroot register int c; 3656000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3666000Sroot int on = 1; 3676000Sroot 3688378Ssam (void) mode(2); 3696000Sroot ioctl(s, FIONBIO, &on); 3706000Sroot for (;;) { 3716000Sroot int ibits = 0, obits = 0; 3726000Sroot 3736000Sroot if (nfrontp - nbackp) 3746000Sroot obits |= (1 << s); 3756000Sroot else 3766000Sroot ibits |= (1 << tin); 3776000Sroot if (tfrontp - tbackp) 3786000Sroot obits |= (1 << tout); 3796000Sroot else 3806000Sroot ibits |= (1 << s); 3816000Sroot if (scc < 0 && tcc < 0) 3826000Sroot break; 383*9217Ssam select(16, &ibits, &obits, 0, 0); 3846000Sroot if (ibits == 0 && obits == 0) { 3856000Sroot sleep(5); 3866000Sroot continue; 3876000Sroot } 3886000Sroot 3896000Sroot /* 3906000Sroot * Something to read from the network... 3916000Sroot */ 3926000Sroot if (ibits & (1 << s)) { 3938378Ssam scc = read(s, sibuf, sizeof (sibuf)); 3946000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3956000Sroot scc = 0; 3966000Sroot else { 3976000Sroot if (scc <= 0) 3986000Sroot break; 3996000Sroot sbp = sibuf; 4006000Sroot } 4016000Sroot } 4026000Sroot 4036000Sroot /* 4046000Sroot * Something to read from the tty... 4056000Sroot */ 4066000Sroot if (ibits & (1 << tin)) { 4078378Ssam tcc = read(tin, tibuf, sizeof (tibuf)); 4086000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 4096000Sroot tcc = 0; 4106000Sroot else { 4116000Sroot if (tcc <= 0) 4126000Sroot break; 4136000Sroot tbp = tibuf; 4146000Sroot } 4156000Sroot } 4166000Sroot 4176000Sroot while (tcc > 0) { 4186000Sroot register int c; 4196000Sroot 4206000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 4216000Sroot break; 4226000Sroot c = *tbp++ & 0377, tcc--; 4236000Sroot if (strip(c) == escape) { 4246000Sroot command(0); 4256000Sroot tcc = 0; 4266000Sroot break; 4276000Sroot } 4286000Sroot *nfrontp++ = c; 4296000Sroot } 4306000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4316000Sroot netflush(s); 4326000Sroot if (scc > 0) 4336000Sroot telrcv(); 4346000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4356000Sroot ttyflush(tout); 4366000Sroot } 4378378Ssam (void) mode(0); 4386000Sroot } 4396000Sroot 4406000Sroot command(top) 4416000Sroot int top; 4426000Sroot { 4436000Sroot register struct cmd *c; 4446000Sroot int oldmode, wasopen; 4456000Sroot 4466000Sroot oldmode = mode(0); 4476000Sroot if (!top) 4486000Sroot putchar('\n'); 4496000Sroot else 4506000Sroot sigset(SIGINT, SIG_DFL); 4516000Sroot for (;;) { 4526000Sroot printf("%s> ", prompt); 4536000Sroot if (gets(line) == 0) 4546000Sroot break; 4556000Sroot if (line[0] == 0) 4566000Sroot break; 4576000Sroot makeargv(); 4586000Sroot c = getcmd(margv[0]); 4596000Sroot if (c == (struct cmd *)-1) { 4606000Sroot printf("?Ambiguous command\n"); 4616000Sroot continue; 4626000Sroot } 4636000Sroot if (c == 0) { 4646000Sroot printf("?Invalid command\n"); 4656000Sroot continue; 4666000Sroot } 4676000Sroot (*c->handler)(margc, margv); 4686000Sroot if (c->handler != help) 4696000Sroot break; 4706000Sroot } 4716000Sroot if (!top) { 4726000Sroot if (!connected) 4736000Sroot longjmp(toplevel, 1); 4748378Ssam (void) mode(oldmode); 4756000Sroot } 4766000Sroot } 4776000Sroot 4786000Sroot /* 4796000Sroot * Telnet receiver states for fsm 4806000Sroot */ 4816000Sroot #define TS_DATA 0 4826000Sroot #define TS_IAC 1 4836000Sroot #define TS_WILL 2 4846000Sroot #define TS_WONT 3 4856000Sroot #define TS_DO 4 4866000Sroot #define TS_DONT 5 4876000Sroot 4886000Sroot telrcv() 4896000Sroot { 4906000Sroot register int c; 4916000Sroot static int state = TS_DATA; 4926000Sroot 4936000Sroot while (scc > 0) { 4946000Sroot c = *sbp++ & 0377, scc--; 4956000Sroot switch (state) { 4966000Sroot 4976000Sroot case TS_DATA: 4986000Sroot if (c == IAC) 4996000Sroot state = TS_IAC; 5006000Sroot else 5016000Sroot *tfrontp++ = c; 5026000Sroot continue; 5036000Sroot 5046000Sroot case TS_IAC: 5056000Sroot switch (c) { 5066000Sroot 5076000Sroot case WILL: 5086000Sroot state = TS_WILL; 5096000Sroot continue; 5106000Sroot 5116000Sroot case WONT: 5126000Sroot state = TS_WONT; 5136000Sroot continue; 5146000Sroot 5156000Sroot case DO: 5166000Sroot state = TS_DO; 5176000Sroot continue; 5186000Sroot 5196000Sroot case DONT: 5206000Sroot state = TS_DONT; 5216000Sroot continue; 5226000Sroot 5236000Sroot case DM: 5246000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5256000Sroot break; 5266000Sroot 5276000Sroot case NOP: 5286000Sroot case GA: 5296000Sroot break; 5306000Sroot 5316000Sroot default: 5326000Sroot break; 5336000Sroot } 5346000Sroot state = TS_DATA; 5356000Sroot continue; 5366000Sroot 5376000Sroot case TS_WILL: 5388345Ssam printoption("RCVD", will, c, !hisopts[c]); 5396000Sroot if (!hisopts[c]) 5406000Sroot willoption(c); 5416000Sroot state = TS_DATA; 5426000Sroot continue; 5436000Sroot 5446000Sroot case TS_WONT: 5458345Ssam printoption("RCVD", wont, c, hisopts[c]); 5466000Sroot if (hisopts[c]) 5476000Sroot wontoption(c); 5486000Sroot state = TS_DATA; 5496000Sroot continue; 5506000Sroot 5516000Sroot case TS_DO: 5528345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5536000Sroot if (!myopts[c]) 5546000Sroot dooption(c); 5556000Sroot state = TS_DATA; 5566000Sroot continue; 5576000Sroot 5586000Sroot case TS_DONT: 5598345Ssam printoption("RCVD", dont, c, myopts[c]); 5606000Sroot if (myopts[c]) { 5616000Sroot myopts[c] = 0; 5626000Sroot sprintf(nfrontp, wont, c); 5638378Ssam nfrontp += sizeof (wont) - 2; 5648345Ssam printoption("SENT", wont, c); 5656000Sroot } 5666000Sroot state = TS_DATA; 5676000Sroot continue; 5686000Sroot } 5696000Sroot } 5706000Sroot } 5716000Sroot 5726000Sroot willoption(option) 5736000Sroot int option; 5746000Sroot { 5756000Sroot char *fmt; 5766000Sroot 5776000Sroot switch (option) { 5786000Sroot 5796000Sroot case TELOPT_ECHO: 5808378Ssam (void) mode(1); 5816000Sroot 5826000Sroot case TELOPT_SGA: 5836000Sroot hisopts[option] = 1; 5846000Sroot fmt = doopt; 5856000Sroot break; 5866000Sroot 5876000Sroot case TELOPT_TM: 5886000Sroot fmt = dont; 5896000Sroot break; 5906000Sroot 5916000Sroot default: 5926000Sroot fmt = dont; 5936000Sroot break; 5946000Sroot } 5956024Ssam sprintf(nfrontp, fmt, option); 5968378Ssam nfrontp += sizeof (dont) - 2; 5978345Ssam printoption("SENT", fmt, option); 5986000Sroot } 5996000Sroot 6006000Sroot wontoption(option) 6016000Sroot int option; 6026000Sroot { 6036000Sroot char *fmt; 6046000Sroot 6056000Sroot switch (option) { 6066000Sroot 6076000Sroot case TELOPT_ECHO: 6088378Ssam (void) mode(2); 6096000Sroot 6106000Sroot case TELOPT_SGA: 6116000Sroot hisopts[option] = 0; 6126000Sroot fmt = dont; 6136000Sroot break; 6146000Sroot 6156000Sroot default: 6166000Sroot fmt = dont; 6176000Sroot } 6186000Sroot sprintf(nfrontp, fmt, option); 6198378Ssam nfrontp += sizeof (doopt) - 2; 6208345Ssam printoption("SENT", fmt, option); 6216000Sroot } 6226000Sroot 6236000Sroot dooption(option) 6246000Sroot int option; 6256000Sroot { 6266000Sroot char *fmt; 6276000Sroot 6286000Sroot switch (option) { 6296000Sroot 6306000Sroot case TELOPT_TM: 6316000Sroot fmt = wont; 6326000Sroot break; 6336000Sroot 6346000Sroot case TELOPT_SGA: 6356000Sroot fmt = will; 6366000Sroot break; 6376000Sroot 6386000Sroot default: 6396000Sroot fmt = wont; 6406000Sroot break; 6416000Sroot } 6426000Sroot sprintf(nfrontp, fmt, option); 6438378Ssam nfrontp += sizeof (doopt) - 2; 6448345Ssam printoption("SENT", fmt, option); 6456000Sroot } 6466000Sroot 6476000Sroot /* 6486000Sroot * Set the escape character. 6496000Sroot */ 6506000Sroot setescape(argc, argv) 6516000Sroot int argc; 6526000Sroot char *argv[]; 6536000Sroot { 6546000Sroot register char *arg; 6556000Sroot char buf[50]; 6566000Sroot 6576000Sroot if (argc > 2) 6586000Sroot arg = argv[1]; 6596000Sroot else { 6606000Sroot printf("new escape character: "); 6616000Sroot gets(buf); 6626000Sroot arg = buf; 6636000Sroot } 6646000Sroot if (arg[0] != '\0') 6656000Sroot escape = arg[0]; 6666000Sroot printf("Escape character is '%s'.\n", control(escape)); 6676000Sroot } 6686000Sroot 6696024Ssam /*VARARGS*/ 6706024Ssam setoptions() 6716024Ssam { 6726024Ssam showoptions = !showoptions; 6736024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 6746024Ssam } 6756024Ssam 6766000Sroot /* 6776000Sroot * Construct a control character sequence 6786000Sroot * for a special character. 6796000Sroot */ 6806000Sroot char * 6816000Sroot control(c) 6826000Sroot register int c; 6836000Sroot { 6846000Sroot static char buf[3]; 6856000Sroot 6866000Sroot if (c == 0177) 6876000Sroot return ("^?"); 6886000Sroot if (c >= 040) { 6896000Sroot buf[0] = c; 6906000Sroot buf[1] = 0; 6916000Sroot } else { 6926000Sroot buf[0] = '^'; 6936000Sroot buf[1] = '@'+c; 6946000Sroot buf[2] = 0; 6956000Sroot } 6966000Sroot return (buf); 6976000Sroot } 6986000Sroot 6996000Sroot struct cmd * 7006000Sroot getcmd(name) 7016000Sroot register char *name; 7026000Sroot { 7036000Sroot register char *p, *q; 7046000Sroot register struct cmd *c, *found; 7056000Sroot register int nmatches, longest; 7066000Sroot 7076000Sroot longest = 0; 7086000Sroot nmatches = 0; 7096000Sroot found = 0; 7106000Sroot for (c = cmdtab; p = c->name; c++) { 7116000Sroot for (q = name; *q == *p++; q++) 7126000Sroot if (*q == 0) /* exact match? */ 7136000Sroot return (c); 7146000Sroot if (!*q) { /* the name was a prefix */ 7156000Sroot if (q - name > longest) { 7166000Sroot longest = q - name; 7176000Sroot nmatches = 1; 7186000Sroot found = c; 7196000Sroot } else if (q - name == longest) 7206000Sroot nmatches++; 7216000Sroot } 7226000Sroot } 7236000Sroot if (nmatches > 1) 7246000Sroot return ((struct cmd *)-1); 7256000Sroot return (found); 7266000Sroot } 7276000Sroot 7286000Sroot deadpeer() 7296000Sroot { 7306000Sroot sigset(SIGPIPE, deadpeer); 7318378Ssam (void) mode(0); 7326000Sroot longjmp(peerdied, -1); 7336000Sroot } 7346000Sroot 7356000Sroot intr() 7366000Sroot { 7376000Sroot sigset(SIGINT, intr); 7388378Ssam (void) mode(0); 7396000Sroot longjmp(toplevel, -1); 7406000Sroot } 7416000Sroot 7426000Sroot ttyflush(fd) 7436000Sroot { 7446000Sroot int n; 7456000Sroot 7466000Sroot if ((n = tfrontp - tbackp) > 0) 7476000Sroot n = write(fd, tbackp, n); 7488345Ssam if (n < 0) 7498345Ssam return; 7506000Sroot tbackp += n; 7516000Sroot if (tbackp == tfrontp) 7526000Sroot tbackp = tfrontp = ttyobuf; 7536000Sroot } 7546000Sroot 7556000Sroot netflush(fd) 7566000Sroot { 7576000Sroot int n; 7586000Sroot 7596000Sroot if ((n = nfrontp - nbackp) > 0) 7606000Sroot n = write(fd, nbackp, n); 7616501Ssam if (n < 0) { 7626501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 7638378Ssam (void) mode(0); 7648377Ssam perror(hostname); 7656501Ssam close(fd); 7666501Ssam longjmp(peerdied, -1); 7676501Ssam /*NOTREACHED*/ 7686501Ssam } 7696000Sroot n = 0; 7706501Ssam } 7716000Sroot nbackp += n; 7726000Sroot if (nbackp == nfrontp) 7736000Sroot nbackp = nfrontp = netobuf; 7746000Sroot } 7756024Ssam 7766293Sroot /*VARARGS*/ 7776293Sroot printoption(direction, fmt, option, what) 7786024Ssam char *direction, *fmt; 7796293Sroot int option, what; 7806024Ssam { 7818345Ssam if (!showoptions) 7828345Ssam return; 7836024Ssam printf("%s ", direction); 7846024Ssam if (fmt == doopt) 7856024Ssam fmt = "do"; 7866024Ssam else if (fmt == dont) 7876024Ssam fmt = "dont"; 7886024Ssam else if (fmt == will) 7896024Ssam fmt = "will"; 7906024Ssam else if (fmt == wont) 7916024Ssam fmt = "wont"; 7926024Ssam else 7936024Ssam fmt = "???"; 7946024Ssam if (option < TELOPT_SUPDUP) 7956293Sroot printf("%s %s", fmt, telopts[option]); 7966024Ssam else 7976293Sroot printf("%s %d", fmt, option); 7986293Sroot if (*direction == '<') { 7996293Sroot printf("\r\n"); 8006293Sroot return; 8016293Sroot } 8026293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 8036024Ssam } 804