1*8378Ssam static char sccsid[] = "@(#)telnet.c 4.11 (Berkeley) 10/07/82"; 26000Sroot /* 36000Sroot * User telnet program. 46000Sroot */ 56000Sroot #include <stdio.h> 66000Sroot #include <ctype.h> 76000Sroot #include <errno.h> 86000Sroot #include <signal.h> 96000Sroot #include <sgtty.h> 106000Sroot #include <setjmp.h> 116000Sroot #include <sys/types.h> 126000Sroot #include <sys/socket.h> 136000Sroot #include <net/in.h> 148345Ssam #include <netdb.h> 156024Ssam #define TELOPTS 166000Sroot #include "telnet.h" 176000Sroot 186000Sroot #define ctrl(x) ((x) & 037) 196000Sroot #define strip(x) ((x)&0177) 206000Sroot #define INFINITY 10000000 216000Sroot 226000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 23*8378Ssam char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; 246000Sroot 256000Sroot char hisopts[256]; 266000Sroot char myopts[256]; 276000Sroot 286000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 296000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 306000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 316000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 326000Sroot 336000Sroot int connected; 346000Sroot int net; 356024Ssam int showoptions; 367377Sfeldman int options; 376000Sroot char *prompt; 387377Sfeldman char escape = ctrl(']'); 396000Sroot 406000Sroot char line[200]; 416000Sroot int margc; 426000Sroot char *margv[20]; 436000Sroot 446000Sroot jmp_buf toplevel; 456000Sroot jmp_buf peerdied; 466000Sroot 476000Sroot extern int errno; 486000Sroot 496000Sroot int tn(), quit(), suspend(), bye(), help(); 506024Ssam int setescape(), status(), toggle(), setoptions(); 516000Sroot 52*8378Ssam #define HELPINDENT (sizeof ("connect")) 536000Sroot 546000Sroot struct cmd { 556000Sroot char *name; 566000Sroot char *help; 576000Sroot int (*handler)(); 586000Sroot }; 596000Sroot 606000Sroot char ohelp[] = "connect to a site"; 616000Sroot char chelp[] = "close current connection"; 626000Sroot char qhelp[] = "exit telnet"; 636000Sroot char zhelp[] = "suspend telnet"; 646000Sroot char ehelp[] = "set escape character"; 656000Sroot char shelp[] = "print status information"; 666000Sroot char hhelp[] = "print help information"; 676024Ssam char phelp[] = "toggle viewing of options processing"; 686000Sroot 696000Sroot struct cmd cmdtab[] = { 706000Sroot { "open", ohelp, tn }, 716000Sroot { "close", chelp, bye }, 726000Sroot { "quit", qhelp, quit }, 736000Sroot { "z", zhelp, suspend }, 746000Sroot { "escape", ehelp, setescape }, 756000Sroot { "status", shelp, status }, 766024Ssam { "options", phelp, setoptions }, 776000Sroot { "?", hhelp, help }, 786000Sroot 0 796000Sroot }; 806000Sroot 818345Ssam struct sockaddr_in sin = { AF_INET }; 826000Sroot 836000Sroot int intr(), deadpeer(); 846000Sroot char *control(); 856000Sroot struct cmd *getcmd(); 868345Ssam struct servent *sp; 876000Sroot 88*8378Ssam struct sgttyb ostbuf; 89*8378Ssam struct tchars otchars; 90*8378Ssam int odisc; 91*8378Ssam 926000Sroot main(argc, argv) 936000Sroot int argc; 946000Sroot char *argv[]; 956000Sroot { 968345Ssam sp = getservbyname("telnet", "tcp"); 978345Ssam if (sp == 0) { 988345Ssam fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 998345Ssam exit(1); 1008345Ssam } 101*8378Ssam ioctl(0, TIOCGETP, (char *)&ostbuf); 102*8378Ssam ioctl(0, TIOCGETC, (char *)&otchars); 103*8378Ssam ioctl(0, TIOCGETD, (char *)&odisc); 1046000Sroot setbuf(stdin, 0); 1056000Sroot setbuf(stdout, 0); 1066000Sroot prompt = argv[0]; 1077377Sfeldman if (argc > 1 && !strcmp(argv[1], "-d")) 1087377Sfeldman options = SO_DEBUG, argv++, argc--; 1096000Sroot if (argc != 1) { 1106000Sroot if (setjmp(toplevel) != 0) 1116000Sroot exit(0); 1126000Sroot tn(argc, argv); 1136000Sroot } 1146000Sroot setjmp(toplevel); 1156000Sroot for (;;) 1166000Sroot command(1); 1176000Sroot } 1186000Sroot 1198377Ssam char *hostname; 1208377Ssam char hnamebuf[32]; 1216000Sroot 1226000Sroot tn(argc, argv) 1236000Sroot int argc; 1246000Sroot char *argv[]; 1256000Sroot { 1266000Sroot register int c; 1278377Ssam register struct hostent *host; 1286000Sroot 1296000Sroot if (connected) { 1308377Ssam printf("?Already connected to %s\n", hostname); 1316000Sroot return; 1326000Sroot } 1336000Sroot if (argc < 2) { 1346000Sroot strcpy(line, "Connect "); 1356000Sroot printf("(to) "); 1366000Sroot gets(&line[strlen(line)]); 1376000Sroot makeargv(); 1386000Sroot argc = margc; 1396000Sroot argv = margv; 1406000Sroot } 1416000Sroot if (argc > 3) { 1426000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1436000Sroot return; 1446000Sroot } 1458345Ssam host = gethostbyname(argv[1]); 1468377Ssam if (host) { 1478377Ssam bcopy(host->h_addr, &sin.sin_addr, host->h_length); 1488377Ssam hostname = host->h_name; 1498377Ssam } else { 1508377Ssam sin.sin_addr.s_addr = inet_addr(argv[1]); 1518377Ssam if (sin.sin_addr.s_addr == -1) { 1528377Ssam printf("%s: unknown host\n", argv[1]); 1538377Ssam return; 1548377Ssam } 1558377Ssam strcpy(hnamebuf, argv[1]); 1568377Ssam hostname = hnamebuf; 1576000Sroot } 1588345Ssam sin.sin_port = sp->s_port; 1596024Ssam if (argc == 3) { 1606024Ssam sin.sin_port = atoi(argv[2]); 1616024Ssam if (sin.sin_port < 0) { 1626024Ssam printf("%s: bad port number\n", argv[2]); 1636024Ssam return; 1646024Ssam } 1656024Ssam } 1668345Ssam sin.sin_port = htons(sin.sin_port); 1677377Sfeldman if ((net = socket(SOCK_STREAM, 0, 0, options)) < 0) { 1686000Sroot perror("socket"); 1696000Sroot return; 1706000Sroot } 1716000Sroot sigset(SIGINT, intr); 1726000Sroot sigset(SIGPIPE, deadpeer); 1736000Sroot printf("Trying...\n"); 1746000Sroot if (connect(net, &sin)) { 1756000Sroot perror("connect"); 1766000Sroot sigset(SIGINT, SIG_DFL); 1776000Sroot return; 1786000Sroot } 1796000Sroot connected++; 1806000Sroot call(status, "status", 0); 1816000Sroot if (setjmp(peerdied) == 0) 1826000Sroot telnet(net); 1836000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1846000Sroot exit(1); 1856000Sroot } 1866000Sroot 1876000Sroot /* 1886000Sroot * Print status about the connection. 1896000Sroot */ 1906000Sroot /*VARARGS*/ 1916000Sroot status() 1926000Sroot { 1936000Sroot if (connected) 1948377Ssam printf("Connected to %s.\n", hostname); 1956000Sroot else 1966000Sroot printf("No connection.\n"); 1976000Sroot printf("Escape character is '%s'.\n", control(escape)); 1986000Sroot } 1996000Sroot 2006000Sroot makeargv() 2016000Sroot { 2026000Sroot register char *cp; 2036000Sroot register char **argp = margv; 2046000Sroot 2056000Sroot margc = 0; 2066000Sroot for (cp = line; *cp;) { 2076000Sroot while (isspace(*cp)) 2086000Sroot cp++; 2096000Sroot if (*cp == '\0') 2106000Sroot break; 2116000Sroot *argp++ = cp; 2126000Sroot margc += 1; 2136000Sroot while (*cp != '\0' && !isspace(*cp)) 2146000Sroot cp++; 2156000Sroot if (*cp == '\0') 2166000Sroot break; 2176000Sroot *cp++ = '\0'; 2186000Sroot } 2196000Sroot *argp++ = 0; 2206000Sroot } 2216000Sroot 2226000Sroot /*VARARGS*/ 2236000Sroot suspend() 2246000Sroot { 2256000Sroot register int save; 2266000Sroot 2276000Sroot save = mode(0); 228*8378Ssam kill(0, SIGTSTP); 229*8378Ssam /* reget parameters in case they were changed */ 230*8378Ssam ioctl(0, TIOCGETP, (char *)&ostbuf); 231*8378Ssam ioctl(0, TIOCGETC, (char *)&otchars); 232*8378Ssam ioctl(0, TIOCGETD, (char *)&odisc); 233*8378Ssam (void) mode(save); 2346000Sroot } 2356000Sroot 2366000Sroot /*VARARGS*/ 2376000Sroot bye() 2386000Sroot { 2396000Sroot int how = 2; 240*8378Ssam register char *op; 2416000Sroot 242*8378Ssam (void) mode(0); 2436000Sroot if (connected) { 2446000Sroot ioctl(net, SIOCDONE, &how); 2456000Sroot printf("Connection closed.\n"); 2466000Sroot close(net); 2476000Sroot connected = 0; 248*8378Ssam /* reset his options */ 249*8378Ssam for (op = hisopts; op < &hisopts[256]; op++) 250*8378Ssam *op = 0; 2516000Sroot } 2526000Sroot } 2536000Sroot 2546000Sroot /*VARARGS*/ 2556000Sroot quit() 2566000Sroot { 2576000Sroot call(bye, "bye", 0); 2586000Sroot exit(0); 2596000Sroot } 2606000Sroot 2616000Sroot /* 2626000Sroot * Help command. 2636000Sroot * Call each command handler with argc == 0 and argv[0] == name. 2646000Sroot */ 2656000Sroot help(argc, argv) 2666000Sroot int argc; 2676000Sroot char *argv[]; 2686000Sroot { 2696000Sroot register struct cmd *c; 2706000Sroot 2716000Sroot if (argc == 1) { 2726000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2736000Sroot for (c = cmdtab; c->name; c++) 2746000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2756000Sroot return; 2766000Sroot } 2776000Sroot while (--argc > 0) { 2786000Sroot register char *arg; 2796000Sroot arg = *++argv; 2806000Sroot c = getcmd(arg); 2816000Sroot if (c == (struct cmd *)-1) 2826000Sroot printf("?Ambiguous help command %s\n", arg); 2836000Sroot else if (c == (struct cmd *)0) 2846000Sroot printf("?Invalid help command %s\n", arg); 2856000Sroot else 2866000Sroot printf("%s\n", c->help); 2876000Sroot } 2886000Sroot } 2896000Sroot 2906000Sroot /* 2916000Sroot * Call routine with argc, argv set from args (terminated by 0). 2926000Sroot * VARARGS2 2936000Sroot */ 2946000Sroot call(routine, args) 2956000Sroot int (*routine)(); 2966000Sroot int args; 2976000Sroot { 2986000Sroot register int *argp; 2996000Sroot register int argc; 3006000Sroot 3016000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 3026000Sroot ; 3036000Sroot (*routine)(argc, &args); 3046000Sroot } 3056000Sroot 3066000Sroot mode(f) 3076000Sroot register int f; 3086000Sroot { 3096000Sroot struct sgttyb stbuf; 310*8378Ssam static int prevmode = 0; 311*8378Ssam struct tchars tchars; 312*8378Ssam int onoff, disc, old; 3136000Sroot 314*8378Ssam if (prevmode == f) 315*8378Ssam return (f); 316*8378Ssam old = prevmode; 317*8378Ssam prevmode = f; 318*8378Ssam stbuf = ostbuf; 319*8378Ssam tchars = otchars; 3206000Sroot switch (f) { 321*8378Ssam 3226000Sroot case 0: 323*8378Ssam disc = odisc; 3246000Sroot onoff = 0; 3256000Sroot break; 3266000Sroot 3276000Sroot case 1: 3286000Sroot case 2: 329*8378Ssam stbuf.sg_flags |= CBREAK; 330*8378Ssam if (f == 1) 331*8378Ssam stbuf.sg_flags &= ~ECHO; 332*8378Ssam else 333*8378Ssam stbuf.sg_flags |= ECHO; 334*8378Ssam tchars.t_intrc = tchars.t_quitc = -1; 335*8378Ssam disc = OTTYDISC; 3366000Sroot onoff = 1; 3376000Sroot } 338*8378Ssam ioctl(fileno(stdin), TIOCSETD, &disc); 339*8378Ssam ioctl(fileno(stdin), TIOCSETC, &tchars); 3406000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 3416000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3426000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3436000Sroot return (old); 3446000Sroot } 3456000Sroot 3466000Sroot char sibuf[BUFSIZ], *sbp; 3476000Sroot char tibuf[BUFSIZ], *tbp; 3486000Sroot int scc, tcc; 3496000Sroot 3506000Sroot /* 3516000Sroot * Select from tty and network... 3526000Sroot */ 3536000Sroot telnet(s) 3546000Sroot int s; 3556000Sroot { 3566000Sroot register int c; 3576000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3586000Sroot int on = 1; 3596000Sroot 360*8378Ssam (void) mode(2); 3616000Sroot ioctl(s, FIONBIO, &on); 3626000Sroot for (;;) { 3636000Sroot int ibits = 0, obits = 0; 3646000Sroot 3656000Sroot if (nfrontp - nbackp) 3666000Sroot obits |= (1 << s); 3676000Sroot else 3686000Sroot ibits |= (1 << tin); 3696000Sroot if (tfrontp - tbackp) 3706000Sroot obits |= (1 << tout); 3716000Sroot else 3726000Sroot ibits |= (1 << s); 3736000Sroot if (scc < 0 && tcc < 0) 3746000Sroot break; 3756000Sroot select(32, &ibits, &obits, INFINITY); 3766000Sroot if (ibits == 0 && obits == 0) { 3776000Sroot sleep(5); 3786000Sroot continue; 3796000Sroot } 3806000Sroot 3816000Sroot /* 3826000Sroot * Something to read from the network... 3836000Sroot */ 3846000Sroot if (ibits & (1 << s)) { 385*8378Ssam scc = read(s, sibuf, sizeof (sibuf)); 3866000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3876000Sroot scc = 0; 3886000Sroot else { 3896000Sroot if (scc <= 0) 3906000Sroot break; 3916000Sroot sbp = sibuf; 3926000Sroot } 3936000Sroot } 3946000Sroot 3956000Sroot /* 3966000Sroot * Something to read from the tty... 3976000Sroot */ 3986000Sroot if (ibits & (1 << tin)) { 399*8378Ssam tcc = read(tin, tibuf, sizeof (tibuf)); 4006000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 4016000Sroot tcc = 0; 4026000Sroot else { 4036000Sroot if (tcc <= 0) 4046000Sroot break; 4056000Sroot tbp = tibuf; 4066000Sroot } 4076000Sroot } 4086000Sroot 4096000Sroot while (tcc > 0) { 4106000Sroot register int c; 4116000Sroot 4126000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 4136000Sroot break; 4146000Sroot c = *tbp++ & 0377, tcc--; 4156000Sroot if (strip(c) == escape) { 4166000Sroot command(0); 4176000Sroot tcc = 0; 4186000Sroot break; 4196000Sroot } 4206000Sroot *nfrontp++ = c; 4216000Sroot } 4226000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4236000Sroot netflush(s); 4246000Sroot if (scc > 0) 4256000Sroot telrcv(); 4266000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4276000Sroot ttyflush(tout); 4286000Sroot } 429*8378Ssam (void) mode(0); 4306000Sroot } 4316000Sroot 4326000Sroot command(top) 4336000Sroot int top; 4346000Sroot { 4356000Sroot register struct cmd *c; 4366000Sroot int oldmode, wasopen; 4376000Sroot 4386000Sroot oldmode = mode(0); 4396000Sroot if (!top) 4406000Sroot putchar('\n'); 4416000Sroot else 4426000Sroot sigset(SIGINT, SIG_DFL); 4436000Sroot for (;;) { 4446000Sroot printf("%s> ", prompt); 4456000Sroot if (gets(line) == 0) 4466000Sroot break; 4476000Sroot if (line[0] == 0) 4486000Sroot break; 4496000Sroot makeargv(); 4506000Sroot c = getcmd(margv[0]); 4516000Sroot if (c == (struct cmd *)-1) { 4526000Sroot printf("?Ambiguous command\n"); 4536000Sroot continue; 4546000Sroot } 4556000Sroot if (c == 0) { 4566000Sroot printf("?Invalid command\n"); 4576000Sroot continue; 4586000Sroot } 4596000Sroot (*c->handler)(margc, margv); 4606000Sroot if (c->handler != help) 4616000Sroot break; 4626000Sroot } 4636000Sroot if (!top) { 4646000Sroot if (!connected) 4656000Sroot longjmp(toplevel, 1); 466*8378Ssam (void) mode(oldmode); 4676000Sroot } 4686000Sroot } 4696000Sroot 4706000Sroot /* 4716000Sroot * Telnet receiver states for fsm 4726000Sroot */ 4736000Sroot #define TS_DATA 0 4746000Sroot #define TS_IAC 1 4756000Sroot #define TS_WILL 2 4766000Sroot #define TS_WONT 3 4776000Sroot #define TS_DO 4 4786000Sroot #define TS_DONT 5 4796000Sroot 4806000Sroot telrcv() 4816000Sroot { 4826000Sroot register int c; 4836000Sroot static int state = TS_DATA; 4846000Sroot 4856000Sroot while (scc > 0) { 4866000Sroot c = *sbp++ & 0377, scc--; 4876000Sroot switch (state) { 4886000Sroot 4896000Sroot case TS_DATA: 4906000Sroot if (c == IAC) 4916000Sroot state = TS_IAC; 4926000Sroot else 4936000Sroot *tfrontp++ = c; 4946000Sroot continue; 4956000Sroot 4966000Sroot case TS_IAC: 4976000Sroot switch (c) { 4986000Sroot 4996000Sroot case WILL: 5006000Sroot state = TS_WILL; 5016000Sroot continue; 5026000Sroot 5036000Sroot case WONT: 5046000Sroot state = TS_WONT; 5056000Sroot continue; 5066000Sroot 5076000Sroot case DO: 5086000Sroot state = TS_DO; 5096000Sroot continue; 5106000Sroot 5116000Sroot case DONT: 5126000Sroot state = TS_DONT; 5136000Sroot continue; 5146000Sroot 5156000Sroot case DM: 5166000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 5176000Sroot break; 5186000Sroot 5196000Sroot case NOP: 5206000Sroot case GA: 5216000Sroot break; 5226000Sroot 5236000Sroot default: 5246000Sroot break; 5256000Sroot } 5266000Sroot state = TS_DATA; 5276000Sroot continue; 5286000Sroot 5296000Sroot case TS_WILL: 5308345Ssam printoption("RCVD", will, c, !hisopts[c]); 5316000Sroot if (!hisopts[c]) 5326000Sroot willoption(c); 5336000Sroot state = TS_DATA; 5346000Sroot continue; 5356000Sroot 5366000Sroot case TS_WONT: 5378345Ssam printoption("RCVD", wont, c, hisopts[c]); 5386000Sroot if (hisopts[c]) 5396000Sroot wontoption(c); 5406000Sroot state = TS_DATA; 5416000Sroot continue; 5426000Sroot 5436000Sroot case TS_DO: 5448345Ssam printoption("RCVD", doopt, c, !myopts[c]); 5456000Sroot if (!myopts[c]) 5466000Sroot dooption(c); 5476000Sroot state = TS_DATA; 5486000Sroot continue; 5496000Sroot 5506000Sroot case TS_DONT: 5518345Ssam printoption("RCVD", dont, c, myopts[c]); 5526000Sroot if (myopts[c]) { 5536000Sroot myopts[c] = 0; 5546000Sroot sprintf(nfrontp, wont, c); 555*8378Ssam nfrontp += sizeof (wont) - 2; 5568345Ssam printoption("SENT", wont, c); 5576000Sroot } 5586000Sroot state = TS_DATA; 5596000Sroot continue; 5606000Sroot } 5616000Sroot } 5626000Sroot } 5636000Sroot 5646000Sroot willoption(option) 5656000Sroot int option; 5666000Sroot { 5676000Sroot char *fmt; 5686000Sroot 5696000Sroot switch (option) { 5706000Sroot 5716000Sroot case TELOPT_ECHO: 572*8378Ssam (void) mode(1); 5736000Sroot 5746000Sroot case TELOPT_SGA: 5756000Sroot hisopts[option] = 1; 5766000Sroot fmt = doopt; 5776000Sroot break; 5786000Sroot 5796000Sroot case TELOPT_TM: 5806000Sroot fmt = dont; 5816000Sroot break; 5826000Sroot 5836000Sroot default: 5846000Sroot fmt = dont; 5856000Sroot break; 5866000Sroot } 5876024Ssam sprintf(nfrontp, fmt, option); 588*8378Ssam nfrontp += sizeof (dont) - 2; 5898345Ssam printoption("SENT", fmt, option); 5906000Sroot } 5916000Sroot 5926000Sroot wontoption(option) 5936000Sroot int option; 5946000Sroot { 5956000Sroot char *fmt; 5966000Sroot 5976000Sroot switch (option) { 5986000Sroot 5996000Sroot case TELOPT_ECHO: 600*8378Ssam (void) mode(2); 6016000Sroot 6026000Sroot case TELOPT_SGA: 6036000Sroot hisopts[option] = 0; 6046000Sroot fmt = dont; 6056000Sroot break; 6066000Sroot 6076000Sroot default: 6086000Sroot fmt = dont; 6096000Sroot } 6106000Sroot sprintf(nfrontp, fmt, option); 611*8378Ssam nfrontp += sizeof (doopt) - 2; 6128345Ssam printoption("SENT", fmt, option); 6136000Sroot } 6146000Sroot 6156000Sroot dooption(option) 6166000Sroot int option; 6176000Sroot { 6186000Sroot char *fmt; 6196000Sroot 6206000Sroot switch (option) { 6216000Sroot 6226000Sroot case TELOPT_TM: 6236000Sroot fmt = wont; 6246000Sroot break; 6256000Sroot 6266000Sroot case TELOPT_SGA: 6276000Sroot fmt = will; 6286000Sroot break; 6296000Sroot 6306000Sroot default: 6316000Sroot fmt = wont; 6326000Sroot break; 6336000Sroot } 6346000Sroot sprintf(nfrontp, fmt, option); 635*8378Ssam nfrontp += sizeof (doopt) - 2; 6368345Ssam printoption("SENT", fmt, option); 6376000Sroot } 6386000Sroot 6396000Sroot /* 6406000Sroot * Set the escape character. 6416000Sroot */ 6426000Sroot setescape(argc, argv) 6436000Sroot int argc; 6446000Sroot char *argv[]; 6456000Sroot { 6466000Sroot register char *arg; 6476000Sroot char buf[50]; 6486000Sroot 6496000Sroot if (argc > 2) 6506000Sroot arg = argv[1]; 6516000Sroot else { 6526000Sroot printf("new escape character: "); 6536000Sroot gets(buf); 6546000Sroot arg = buf; 6556000Sroot } 6566000Sroot if (arg[0] != '\0') 6576000Sroot escape = arg[0]; 6586000Sroot printf("Escape character is '%s'.\n", control(escape)); 6596000Sroot } 6606000Sroot 6616024Ssam /*VARARGS*/ 6626024Ssam setoptions() 6636024Ssam { 6646024Ssam showoptions = !showoptions; 6656024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 6666024Ssam } 6676024Ssam 6686000Sroot /* 6696000Sroot * Construct a control character sequence 6706000Sroot * for a special character. 6716000Sroot */ 6726000Sroot char * 6736000Sroot control(c) 6746000Sroot register int c; 6756000Sroot { 6766000Sroot static char buf[3]; 6776000Sroot 6786000Sroot if (c == 0177) 6796000Sroot return ("^?"); 6806000Sroot if (c >= 040) { 6816000Sroot buf[0] = c; 6826000Sroot buf[1] = 0; 6836000Sroot } else { 6846000Sroot buf[0] = '^'; 6856000Sroot buf[1] = '@'+c; 6866000Sroot buf[2] = 0; 6876000Sroot } 6886000Sroot return (buf); 6896000Sroot } 6906000Sroot 6916000Sroot struct cmd * 6926000Sroot getcmd(name) 6936000Sroot register char *name; 6946000Sroot { 6956000Sroot register char *p, *q; 6966000Sroot register struct cmd *c, *found; 6976000Sroot register int nmatches, longest; 6986000Sroot 6996000Sroot longest = 0; 7006000Sroot nmatches = 0; 7016000Sroot found = 0; 7026000Sroot for (c = cmdtab; p = c->name; c++) { 7036000Sroot for (q = name; *q == *p++; q++) 7046000Sroot if (*q == 0) /* exact match? */ 7056000Sroot return (c); 7066000Sroot if (!*q) { /* the name was a prefix */ 7076000Sroot if (q - name > longest) { 7086000Sroot longest = q - name; 7096000Sroot nmatches = 1; 7106000Sroot found = c; 7116000Sroot } else if (q - name == longest) 7126000Sroot nmatches++; 7136000Sroot } 7146000Sroot } 7156000Sroot if (nmatches > 1) 7166000Sroot return ((struct cmd *)-1); 7176000Sroot return (found); 7186000Sroot } 7196000Sroot 7206000Sroot deadpeer() 7216000Sroot { 7226000Sroot sigset(SIGPIPE, deadpeer); 723*8378Ssam (void) mode(0); 7246000Sroot longjmp(peerdied, -1); 7256000Sroot } 7266000Sroot 7276000Sroot intr() 7286000Sroot { 7296000Sroot sigset(SIGINT, intr); 730*8378Ssam (void) mode(0); 7316000Sroot longjmp(toplevel, -1); 7326000Sroot } 7336000Sroot 7346000Sroot ttyflush(fd) 7356000Sroot { 7366000Sroot int n; 7376000Sroot 7386000Sroot if ((n = tfrontp - tbackp) > 0) 7396000Sroot n = write(fd, tbackp, n); 7408345Ssam if (n < 0) 7418345Ssam return; 7426000Sroot tbackp += n; 7436000Sroot if (tbackp == tfrontp) 7446000Sroot tbackp = tfrontp = ttyobuf; 7456000Sroot } 7466000Sroot 7476000Sroot netflush(fd) 7486000Sroot { 7496000Sroot int n; 7506000Sroot 7516000Sroot if ((n = nfrontp - nbackp) > 0) 7526000Sroot n = write(fd, nbackp, n); 7536501Ssam if (n < 0) { 7546501Ssam if (errno != ENOBUFS && errno != EWOULDBLOCK) { 755*8378Ssam (void) mode(0); 7568377Ssam perror(hostname); 7576501Ssam close(fd); 7586501Ssam longjmp(peerdied, -1); 7596501Ssam /*NOTREACHED*/ 7606501Ssam } 7616000Sroot n = 0; 7626501Ssam } 7636000Sroot nbackp += n; 7646000Sroot if (nbackp == nfrontp) 7656000Sroot nbackp = nfrontp = netobuf; 7666000Sroot } 7676024Ssam 7686293Sroot /*VARARGS*/ 7696293Sroot printoption(direction, fmt, option, what) 7706024Ssam char *direction, *fmt; 7716293Sroot int option, what; 7726024Ssam { 7738345Ssam if (!showoptions) 7748345Ssam return; 7756024Ssam printf("%s ", direction); 7766024Ssam if (fmt == doopt) 7776024Ssam fmt = "do"; 7786024Ssam else if (fmt == dont) 7796024Ssam fmt = "dont"; 7806024Ssam else if (fmt == will) 7816024Ssam fmt = "will"; 7826024Ssam else if (fmt == wont) 7836024Ssam fmt = "wont"; 7846024Ssam else 7856024Ssam fmt = "???"; 7866024Ssam if (option < TELOPT_SUPDUP) 7876293Sroot printf("%s %s", fmt, telopts[option]); 7886024Ssam else 7896293Sroot printf("%s %d", fmt, option); 7906293Sroot if (*direction == '<') { 7916293Sroot printf("\r\n"); 7926293Sroot return; 7936293Sroot } 7946293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 7956024Ssam } 796