1*6024Ssam /* telnet.c 4.2 82/03/01 */ 26000Sroot 36000Sroot /* 46000Sroot * User telnet program. 56000Sroot */ 66000Sroot #include <stdio.h> 76000Sroot #include <ctype.h> 86000Sroot #include <errno.h> 96000Sroot #include <signal.h> 106000Sroot #include <sgtty.h> 116000Sroot #include <setjmp.h> 126000Sroot #include <sys/types.h> 136000Sroot #include <sys/socket.h> 146000Sroot #include <net/in.h> 15*6024Ssam #define TELOPTS 166000Sroot #include "telnet.h" 176000Sroot 186000Sroot #define ctrl(x) ((x) & 037) 196000Sroot #define strip(x) ((x)&0177) 206000Sroot #define INFINITY 10000000 216000Sroot #define swab(x) ((((x) >> 8) | ((x) << 8)) & 0xffff) 226000Sroot 236000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 246000Sroot char netobuf[BUFSIZ] = 256000Sroot { IAC, DO, TELOPT_ECHO, IAC, DO, TELOPT_SGA, 266000Sroot IAC, WONT, TELOPT_SGA }, 276000Sroot *nfrontp = netobuf + 9, *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; 39*6024Ssam int showoptions; 406000Sroot char *prompt; 416000Sroot char escape = ctrl('_'); 426000Sroot 436000Sroot char line[200]; 446000Sroot int margc; 456000Sroot char *margv[20]; 466000Sroot 476000Sroot jmp_buf toplevel; 486000Sroot jmp_buf peerdied; 496000Sroot 506000Sroot extern int errno; 516000Sroot 526000Sroot int tn(), quit(), suspend(), bye(), help(); 53*6024Ssam int setescape(), status(), toggle(), setoptions(); 546000Sroot 556000Sroot #define HELPINDENT (sizeof("connect")) 566000Sroot 576000Sroot struct cmd { 586000Sroot char *name; 596000Sroot char *help; 606000Sroot int (*handler)(); 616000Sroot }; 626000Sroot 636000Sroot char ohelp[] = "connect to a site"; 646000Sroot char chelp[] = "close current connection"; 656000Sroot char qhelp[] = "exit telnet"; 666000Sroot char zhelp[] = "suspend telnet"; 676000Sroot char ehelp[] = "set escape character"; 686000Sroot char shelp[] = "print status information"; 696000Sroot char hhelp[] = "print help information"; 70*6024Ssam char phelp[] = "toggle viewing of options processing"; 716000Sroot 726000Sroot struct cmd cmdtab[] = { 736000Sroot { "open", ohelp, tn }, 746000Sroot { "close", chelp, bye }, 756000Sroot { "quit", qhelp, quit }, 766000Sroot { "z", zhelp, suspend }, 776000Sroot { "escape", ehelp, setescape }, 786000Sroot { "status", shelp, status }, 79*6024Ssam { "options", phelp, setoptions }, 806000Sroot { "?", hhelp, help }, 816000Sroot 0 826000Sroot }; 836000Sroot 846000Sroot struct sockaddr_in sin = { AF_INET, swab(IPPORT_TELNET) }; 856000Sroot 866000Sroot int intr(), deadpeer(); 876000Sroot char *control(); 886000Sroot struct cmd *getcmd(); 896000Sroot 906000Sroot main(argc, argv) 916000Sroot int argc; 926000Sroot char *argv[]; 936000Sroot { 946000Sroot setbuf(stdin, 0); 956000Sroot setbuf(stdout, 0); 966000Sroot prompt = argv[0]; 976000Sroot if (argc != 1) { 986000Sroot if (setjmp(toplevel) != 0) 996000Sroot exit(0); 1006000Sroot tn(argc, argv); 1016000Sroot } 1026000Sroot setjmp(toplevel); 1036000Sroot for (;;) 1046000Sroot command(1); 1056000Sroot } 1066000Sroot 1076000Sroot char host_name[100]; 1086000Sroot 1096000Sroot tn(argc, argv) 1106000Sroot int argc; 1116000Sroot char *argv[]; 1126000Sroot { 1136000Sroot register int c; 1146000Sroot 1156000Sroot if (connected) { 1166000Sroot printf("?Already connected to %s\n", host_name); 1176000Sroot return; 1186000Sroot } 1196000Sroot if (argc < 2) { 1206000Sroot strcpy(line, "Connect "); 1216000Sroot printf("(to) "); 1226000Sroot gets(&line[strlen(line)]); 1236000Sroot makeargv(); 1246000Sroot argc = margc; 1256000Sroot argv = margv; 1266000Sroot } 1276000Sroot if (argc > 3) { 1286000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1296000Sroot return; 1306000Sroot } 1316000Sroot sin.sin_addr.s_addr = rhost(&argv[1]); 132*6024Ssam if (sin.sin_addr.s_addr <= 0) { 1336000Sroot printf("%s: unknown host\n", argv[1]); 1346000Sroot return; 1356000Sroot } 136*6024Ssam if (argc == 3) { 137*6024Ssam sin.sin_port = atoi(argv[2]); 138*6024Ssam if (sin.sin_port < 0) { 139*6024Ssam printf("%s: bad port number\n", argv[2]); 140*6024Ssam return; 141*6024Ssam } 142*6024Ssam } 1436000Sroot if ((net = socket(SOCK_STREAM, 0, 0, 0)) < 0) { 1446000Sroot perror("socket"); 1456000Sroot return; 1466000Sroot } 1476000Sroot sigset(SIGINT, intr); 1486000Sroot sigset(SIGPIPE, deadpeer); 1496000Sroot printf("Trying...\n"); 1506000Sroot if (connect(net, &sin)) { 1516000Sroot perror("connect"); 1526000Sroot sigset(SIGINT, SIG_DFL); 1536000Sroot return; 1546000Sroot } 1556000Sroot strcpy(host_name, argv[1]); 1566000Sroot connected++; 1576000Sroot call(status, "status", 0); 1586000Sroot if (setjmp(peerdied) == 0) 1596000Sroot telnet(net); 1606000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1616000Sroot exit(1); 1626000Sroot } 1636000Sroot 1646000Sroot /* 1656000Sroot * Print status about the connection. 1666000Sroot */ 1676000Sroot /*VARARGS*/ 1686000Sroot status() 1696000Sroot { 1706000Sroot if (connected) 1716000Sroot printf("Connected to %s.\n", host_name); 1726000Sroot else 1736000Sroot printf("No connection.\n"); 1746000Sroot printf("Escape character is '%s'.\n", control(escape)); 1756000Sroot } 1766000Sroot 1776000Sroot makeargv() 1786000Sroot { 1796000Sroot register char *cp; 1806000Sroot register char **argp = margv; 1816000Sroot 1826000Sroot margc = 0; 1836000Sroot for (cp = line; *cp;) { 1846000Sroot while (isspace(*cp)) 1856000Sroot cp++; 1866000Sroot if (*cp == '\0') 1876000Sroot break; 1886000Sroot *argp++ = cp; 1896000Sroot margc += 1; 1906000Sroot while (*cp != '\0' && !isspace(*cp)) 1916000Sroot cp++; 1926000Sroot if (*cp == '\0') 1936000Sroot break; 1946000Sroot *cp++ = '\0'; 1956000Sroot } 1966000Sroot *argp++ = 0; 1976000Sroot } 1986000Sroot 1996000Sroot /*VARARGS*/ 2006000Sroot suspend() 2016000Sroot { 2026000Sroot register int save; 2036000Sroot 2046000Sroot save = mode(0); 2056000Sroot kill(0, SIGTSTP); /* get whole process group */ 2066000Sroot mode(save); 2076000Sroot } 2086000Sroot 2096000Sroot /*VARARGS*/ 2106000Sroot bye() 2116000Sroot { 2126000Sroot int how = 2; 2136000Sroot 2146000Sroot mode(0); 2156000Sroot if (connected) { 2166000Sroot ioctl(net, SIOCDONE, &how); 2176000Sroot printf("Connection closed.\n"); 2186000Sroot close(net); 2196000Sroot connected = 0; 2206000Sroot } 2216000Sroot } 2226000Sroot 2236000Sroot /*VARARGS*/ 2246000Sroot quit() 2256000Sroot { 2266000Sroot call(bye, "bye", 0); 2276000Sroot exit(0); 2286000Sroot } 2296000Sroot 2306000Sroot /* 2316000Sroot * Help command. 2326000Sroot * Call each command handler with argc == 0 and argv[0] == name. 2336000Sroot */ 2346000Sroot help(argc, argv) 2356000Sroot int argc; 2366000Sroot char *argv[]; 2376000Sroot { 2386000Sroot register struct cmd *c; 2396000Sroot 2406000Sroot if (argc == 1) { 2416000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2426000Sroot for (c = cmdtab; c->name; c++) 2436000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2446000Sroot return; 2456000Sroot } 2466000Sroot while (--argc > 0) { 2476000Sroot register char *arg; 2486000Sroot arg = *++argv; 2496000Sroot c = getcmd(arg); 2506000Sroot if (c == (struct cmd *)-1) 2516000Sroot printf("?Ambiguous help command %s\n", arg); 2526000Sroot else if (c == (struct cmd *)0) 2536000Sroot printf("?Invalid help command %s\n", arg); 2546000Sroot else 2556000Sroot printf("%s\n", c->help); 2566000Sroot } 2576000Sroot } 2586000Sroot 2596000Sroot /* 2606000Sroot * Call routine with argc, argv set from args (terminated by 0). 2616000Sroot * VARARGS2 2626000Sroot */ 2636000Sroot call(routine, args) 2646000Sroot int (*routine)(); 2656000Sroot int args; 2666000Sroot { 2676000Sroot register int *argp; 2686000Sroot register int argc; 2696000Sroot 2706000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 2716000Sroot ; 2726000Sroot (*routine)(argc, &args); 2736000Sroot } 2746000Sroot 2756000Sroot mode(f) 2766000Sroot register int f; 2776000Sroot { 2786000Sroot register int old; 2796000Sroot struct sgttyb stbuf; 2806000Sroot static int ttymode = 0; 2816000Sroot int onoff; 2826000Sroot 2836000Sroot ioctl(fileno(stdin), TIOCGETP, &stbuf); 2846000Sroot old = ttymode; 2856000Sroot ttymode = f; 2866000Sroot switch (f) { 2876000Sroot case 0: 2886000Sroot stbuf.sg_flags &= ~RAW; 2896000Sroot stbuf.sg_flags |= ECHO|CRMOD; 2906000Sroot onoff = 0; 2916000Sroot break; 2926000Sroot 2936000Sroot case 1: 2946000Sroot stbuf.sg_flags |= RAW; 2956000Sroot stbuf.sg_flags &= ~(ECHO|CRMOD); 2966000Sroot onoff = 1; 2976000Sroot break; 2986000Sroot 2996000Sroot case 2: 3006000Sroot stbuf.sg_flags |= RAW; 3016000Sroot stbuf.sg_flags |= ECHO|CRMOD; 3026000Sroot onoff = 1; 3036000Sroot } 3046000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 3056000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3066000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3076000Sroot return (old); 3086000Sroot } 3096000Sroot 3106000Sroot char sibuf[BUFSIZ], *sbp; 3116000Sroot char tibuf[BUFSIZ], *tbp; 3126000Sroot int scc, tcc; 3136000Sroot 3146000Sroot /* 3156000Sroot * Select from tty and network... 3166000Sroot */ 3176000Sroot telnet(s) 3186000Sroot int s; 3196000Sroot { 3206000Sroot register int c; 3216000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3226000Sroot int on = 1; 3236000Sroot 3246000Sroot mode(1); 325*6024Ssam if (showoptions) 326*6024Ssam printoption("<--", doopt, TELOPT_ECHO); 3276000Sroot sprintf(nfrontp, doopt, TELOPT_ECHO); 3286000Sroot nfrontp += sizeof(doopt) - 2; 329*6024Ssam if (showoptions) 330*6024Ssam printoption("<--", doopt, TELOPT_SGA); 3316000Sroot sprintf(nfrontp, doopt, TELOPT_SGA); 3326000Sroot nfrontp += sizeof(doopt) - 2; 333*6024Ssam if (showoptions) 334*6024Ssam printoption("<--", will, TELOPT_SGA); 3356000Sroot sprintf(nfrontp, will, TELOPT_SGA); 3366000Sroot nfrontp += sizeof(doopt) - 2; 3376000Sroot ioctl(s, FIONBIO, &on); 3386000Sroot for (;;) { 3396000Sroot int ibits = 0, obits = 0; 3406000Sroot 3416000Sroot if (nfrontp - nbackp) 3426000Sroot obits |= (1 << s); 3436000Sroot else 3446000Sroot ibits |= (1 << tin); 3456000Sroot if (tfrontp - tbackp) 3466000Sroot obits |= (1 << tout); 3476000Sroot else 3486000Sroot ibits |= (1 << s); 3496000Sroot if (scc < 0 && tcc < 0) 3506000Sroot break; 3516000Sroot select(32, &ibits, &obits, INFINITY); 3526000Sroot if (ibits == 0 && obits == 0) { 3536000Sroot sleep(5); 3546000Sroot continue; 3556000Sroot } 3566000Sroot 3576000Sroot /* 3586000Sroot * Something to read from the network... 3596000Sroot */ 3606000Sroot if (ibits & (1 << s)) { 3616000Sroot scc = read(s, sibuf, sizeof(sibuf)); 3626000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3636000Sroot scc = 0; 3646000Sroot else { 3656000Sroot if (scc <= 0) 3666000Sroot break; 3676000Sroot sbp = sibuf; 3686000Sroot } 3696000Sroot } 3706000Sroot 3716000Sroot /* 3726000Sroot * Something to read from the tty... 3736000Sroot */ 3746000Sroot if (ibits & (1 << tin)) { 3756000Sroot tcc = read(tin, tibuf, sizeof(tibuf)); 3766000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 3776000Sroot tcc = 0; 3786000Sroot else { 3796000Sroot if (tcc <= 0) 3806000Sroot break; 3816000Sroot tbp = tibuf; 3826000Sroot } 3836000Sroot } 3846000Sroot 3856000Sroot while (tcc > 0) { 3866000Sroot register int c; 3876000Sroot 3886000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 3896000Sroot break; 3906000Sroot c = *tbp++ & 0377, tcc--; 3916000Sroot if (strip(c) == escape) { 3926000Sroot command(0); 3936000Sroot tcc = 0; 3946000Sroot break; 3956000Sroot } 3966000Sroot *nfrontp++ = c; 3976000Sroot } 3986000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 3996000Sroot netflush(s); 4006000Sroot if (scc > 0) 4016000Sroot telrcv(); 4026000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4036000Sroot ttyflush(tout); 4046000Sroot } 4056000Sroot mode(0); 4066000Sroot } 4076000Sroot 4086000Sroot command(top) 4096000Sroot int top; 4106000Sroot { 4116000Sroot register struct cmd *c; 4126000Sroot int oldmode, wasopen; 4136000Sroot 4146000Sroot oldmode = mode(0); 4156000Sroot if (!top) 4166000Sroot putchar('\n'); 4176000Sroot else 4186000Sroot sigset(SIGINT, SIG_DFL); 4196000Sroot for (;;) { 4206000Sroot printf("%s> ", prompt); 4216000Sroot if (gets(line) == 0) 4226000Sroot break; 4236000Sroot if (line[0] == 0) 4246000Sroot break; 4256000Sroot makeargv(); 4266000Sroot c = getcmd(margv[0]); 4276000Sroot if (c == (struct cmd *)-1) { 4286000Sroot printf("?Ambiguous command\n"); 4296000Sroot continue; 4306000Sroot } 4316000Sroot if (c == 0) { 4326000Sroot printf("?Invalid command\n"); 4336000Sroot continue; 4346000Sroot } 4356000Sroot (*c->handler)(margc, margv); 4366000Sroot if (c->handler != help) 4376000Sroot break; 4386000Sroot } 4396000Sroot if (!top) { 4406000Sroot if (!connected) 4416000Sroot longjmp(toplevel, 1); 4426000Sroot mode(oldmode); 4436000Sroot } 4446000Sroot } 4456000Sroot 4466000Sroot /* 4476000Sroot * Telnet receiver states for fsm 4486000Sroot */ 4496000Sroot #define TS_DATA 0 4506000Sroot #define TS_IAC 1 4516000Sroot #define TS_WILL 2 4526000Sroot #define TS_WONT 3 4536000Sroot #define TS_DO 4 4546000Sroot #define TS_DONT 5 4556000Sroot 4566000Sroot telrcv() 4576000Sroot { 4586000Sroot register int c; 4596000Sroot static int state = TS_DATA; 4606000Sroot 4616000Sroot while (scc > 0) { 4626000Sroot c = *sbp++ & 0377, scc--; 4636000Sroot switch (state) { 4646000Sroot 4656000Sroot case TS_DATA: 4666000Sroot if (c == IAC) 4676000Sroot state = TS_IAC; 4686000Sroot else 4696000Sroot *tfrontp++ = c; 4706000Sroot continue; 4716000Sroot 4726000Sroot case TS_IAC: 4736000Sroot switch (c) { 4746000Sroot 4756000Sroot case WILL: 4766000Sroot state = TS_WILL; 4776000Sroot continue; 4786000Sroot 4796000Sroot case WONT: 4806000Sroot state = TS_WONT; 4816000Sroot continue; 4826000Sroot 4836000Sroot case DO: 4846000Sroot state = TS_DO; 4856000Sroot continue; 4866000Sroot 4876000Sroot case DONT: 4886000Sroot state = TS_DONT; 4896000Sroot continue; 4906000Sroot 4916000Sroot case DM: 4926000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 4936000Sroot break; 4946000Sroot 4956000Sroot case NOP: 4966000Sroot case GA: 4976000Sroot break; 4986000Sroot 4996000Sroot default: 5006000Sroot break; 5016000Sroot } 5026000Sroot state = TS_DATA; 5036000Sroot continue; 5046000Sroot 5056000Sroot case TS_WILL: 506*6024Ssam if (showoptions) 507*6024Ssam printoption("-->", will, c); 5086000Sroot if (!hisopts[c]) 5096000Sroot willoption(c); 5106000Sroot state = TS_DATA; 5116000Sroot continue; 5126000Sroot 5136000Sroot case TS_WONT: 514*6024Ssam if (showoptions) 515*6024Ssam printoption("-->", wont, c); 5166000Sroot if (hisopts[c]) 5176000Sroot wontoption(c); 5186000Sroot state = TS_DATA; 5196000Sroot continue; 5206000Sroot 5216000Sroot case TS_DO: 522*6024Ssam if (showoptions) 523*6024Ssam printoption("-->", doopt, c); 5246000Sroot if (!myopts[c]) 5256000Sroot dooption(c); 5266000Sroot state = TS_DATA; 5276000Sroot continue; 5286000Sroot 5296000Sroot case TS_DONT: 530*6024Ssam if (showoptions) 531*6024Ssam printoption("-->", dont, c); 5326000Sroot if (myopts[c]) { 5336000Sroot myopts[c] = 0; 5346000Sroot sprintf(nfrontp, wont, c); 5356000Sroot nfrontp += sizeof(wont) - 2; 536*6024Ssam if (showoptions) 537*6024Ssam printoption("<--", wont, c); 5386000Sroot } 5396000Sroot state = TS_DATA; 5406000Sroot continue; 5416000Sroot } 5426000Sroot } 5436000Sroot } 5446000Sroot 5456000Sroot willoption(option) 5466000Sroot int option; 5476000Sroot { 5486000Sroot char *fmt; 5496000Sroot 5506000Sroot switch (option) { 5516000Sroot 5526000Sroot case TELOPT_ECHO: 5536000Sroot mode(1); 5546000Sroot 5556000Sroot case TELOPT_SGA: 5566000Sroot hisopts[option] = 1; 5576000Sroot fmt = doopt; 5586000Sroot break; 5596000Sroot 5606000Sroot case TELOPT_TM: 5616000Sroot fmt = dont; 5626000Sroot break; 5636000Sroot 5646000Sroot default: 5656000Sroot fmt = dont; 5666000Sroot break; 5676000Sroot } 568*6024Ssam sprintf(nfrontp, fmt, option); 5696000Sroot nfrontp += sizeof(dont) - 2; 570*6024Ssam if (showoptions) 571*6024Ssam printoption("<--", fmt, option); 5726000Sroot } 5736000Sroot 5746000Sroot wontoption(option) 5756000Sroot int option; 5766000Sroot { 5776000Sroot char *fmt; 5786000Sroot 5796000Sroot switch (option) { 5806000Sroot 5816000Sroot case TELOPT_ECHO: 5826000Sroot mode(2); 5836000Sroot 5846000Sroot case TELOPT_SGA: 5856000Sroot hisopts[option] = 0; 5866000Sroot fmt = dont; 5876000Sroot break; 5886000Sroot 5896000Sroot default: 5906000Sroot fmt = dont; 5916000Sroot } 5926000Sroot sprintf(nfrontp, fmt, option); 5936000Sroot nfrontp += sizeof(doopt) - 2; 594*6024Ssam if (showoptions) 595*6024Ssam printoption("<--", fmt, option); 5966000Sroot } 5976000Sroot 5986000Sroot dooption(option) 5996000Sroot int option; 6006000Sroot { 6016000Sroot char *fmt; 6026000Sroot 6036000Sroot switch (option) { 6046000Sroot 6056000Sroot case TELOPT_TM: 6066000Sroot fmt = wont; 6076000Sroot break; 6086000Sroot 6096000Sroot case TELOPT_SGA: 6106000Sroot fmt = will; 6116000Sroot break; 6126000Sroot 6136000Sroot default: 6146000Sroot fmt = wont; 6156000Sroot break; 6166000Sroot } 6176000Sroot sprintf(nfrontp, fmt, option); 6186000Sroot nfrontp += sizeof(doopt) - 2; 619*6024Ssam if (showoptions) 620*6024Ssam printoption("<--", fmt, option); 6216000Sroot } 6226000Sroot 6236000Sroot /* 6246000Sroot * Set the escape character. 6256000Sroot */ 6266000Sroot setescape(argc, argv) 6276000Sroot int argc; 6286000Sroot char *argv[]; 6296000Sroot { 6306000Sroot register char *arg; 6316000Sroot char buf[50]; 6326000Sroot 6336000Sroot if (argc > 2) 6346000Sroot arg = argv[1]; 6356000Sroot else { 6366000Sroot printf("new escape character: "); 6376000Sroot gets(buf); 6386000Sroot arg = buf; 6396000Sroot } 6406000Sroot if (arg[0] != '\0') 6416000Sroot escape = arg[0]; 6426000Sroot printf("Escape character is '%s'.\n", control(escape)); 6436000Sroot } 6446000Sroot 645*6024Ssam /*VARARGS*/ 646*6024Ssam setoptions() 647*6024Ssam { 648*6024Ssam showoptions = !showoptions; 649*6024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 650*6024Ssam } 651*6024Ssam 6526000Sroot /* 6536000Sroot * Construct a control character sequence 6546000Sroot * for a special character. 6556000Sroot */ 6566000Sroot char * 6576000Sroot control(c) 6586000Sroot register int c; 6596000Sroot { 6606000Sroot static char buf[3]; 6616000Sroot 6626000Sroot if (c == 0177) 6636000Sroot return ("^?"); 6646000Sroot if (c >= 040) { 6656000Sroot buf[0] = c; 6666000Sroot buf[1] = 0; 6676000Sroot } else { 6686000Sroot buf[0] = '^'; 6696000Sroot buf[1] = '@'+c; 6706000Sroot buf[2] = 0; 6716000Sroot } 6726000Sroot return (buf); 6736000Sroot } 6746000Sroot 6756000Sroot struct cmd * 6766000Sroot getcmd(name) 6776000Sroot register char *name; 6786000Sroot { 6796000Sroot register char *p, *q; 6806000Sroot register struct cmd *c, *found; 6816000Sroot register int nmatches, longest; 6826000Sroot 6836000Sroot longest = 0; 6846000Sroot nmatches = 0; 6856000Sroot found = 0; 6866000Sroot for (c = cmdtab; p = c->name; c++) { 6876000Sroot for (q = name; *q == *p++; q++) 6886000Sroot if (*q == 0) /* exact match? */ 6896000Sroot return (c); 6906000Sroot if (!*q) { /* the name was a prefix */ 6916000Sroot if (q - name > longest) { 6926000Sroot longest = q - name; 6936000Sroot nmatches = 1; 6946000Sroot found = c; 6956000Sroot } else if (q - name == longest) 6966000Sroot nmatches++; 6976000Sroot } 6986000Sroot } 6996000Sroot if (nmatches > 1) 7006000Sroot return ((struct cmd *)-1); 7016000Sroot return (found); 7026000Sroot } 7036000Sroot 7046000Sroot deadpeer() 7056000Sroot { 7066000Sroot sigset(SIGPIPE, deadpeer); 7076000Sroot mode(0); 7086000Sroot longjmp(peerdied, -1); 7096000Sroot } 7106000Sroot 7116000Sroot intr() 7126000Sroot { 7136000Sroot sigset(SIGINT, intr); 7146000Sroot mode(0); 7156000Sroot longjmp(toplevel, -1); 7166000Sroot } 7176000Sroot 7186000Sroot ttyflush(fd) 7196000Sroot { 7206000Sroot int n; 7216000Sroot 7226000Sroot if ((n = tfrontp - tbackp) > 0) 7236000Sroot n = write(fd, tbackp, n); 7246000Sroot if (n < 0 && errno == EWOULDBLOCK) 7256000Sroot n = 0; 7266000Sroot tbackp += n; 7276000Sroot if (tbackp == tfrontp) 7286000Sroot tbackp = tfrontp = ttyobuf; 7296000Sroot } 7306000Sroot 7316000Sroot netflush(fd) 7326000Sroot { 7336000Sroot int n; 7346000Sroot 7356000Sroot if ((n = nfrontp - nbackp) > 0) 7366000Sroot n = write(fd, nbackp, n); 7376000Sroot if (n < 0 && errno == EWOULDBLOCK) 7386000Sroot n = 0; 7396000Sroot nbackp += n; 7406000Sroot if (nbackp == nfrontp) 7416000Sroot nbackp = nfrontp = netobuf; 7426000Sroot } 743*6024Ssam 744*6024Ssam printoption(direction, fmt, option) 745*6024Ssam char *direction, *fmt; 746*6024Ssam int option; 747*6024Ssam { 748*6024Ssam printf("%s ", direction); 749*6024Ssam if (fmt == doopt) 750*6024Ssam fmt = "do"; 751*6024Ssam else if (fmt == dont) 752*6024Ssam fmt = "dont"; 753*6024Ssam else if (fmt == will) 754*6024Ssam fmt = "will"; 755*6024Ssam else if (fmt == wont) 756*6024Ssam fmt = "wont"; 757*6024Ssam else 758*6024Ssam fmt = "???"; 759*6024Ssam if (option < TELOPT_SUPDUP) 760*6024Ssam printf("%s %s\r\n", fmt, telopts[option]); 761*6024Ssam else 762*6024Ssam printf("%s %d\r\n", fmt, option); 763*6024Ssam } 764