1*6293Sroot static char sccsid[] = "@(#)telnet.c 4.5 (Berkeley) 03/23/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> 146024Ssam #define TELOPTS 156000Sroot #include "telnet.h" 166000Sroot 176000Sroot #define ctrl(x) ((x) & 037) 186000Sroot #define strip(x) ((x)&0177) 196000Sroot #define INFINITY 10000000 206000Sroot #define swab(x) ((((x) >> 8) | ((x) << 8)) & 0xffff) 216000Sroot 226000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 236000Sroot char netobuf[BUFSIZ] = 246000Sroot { IAC, DO, TELOPT_ECHO, IAC, DO, TELOPT_SGA, 256000Sroot IAC, WONT, TELOPT_SGA }, 266000Sroot *nfrontp = netobuf + 9, *nbackp = netobuf; 276000Sroot 286000Sroot char hisopts[256]; 296000Sroot char myopts[256]; 306000Sroot 316000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 326000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 336000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 346000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 356000Sroot 366000Sroot int connected; 376000Sroot int net; 386024Ssam int showoptions; 396000Sroot char *prompt; 406000Sroot 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 546000Sroot #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 836000Sroot struct sockaddr_in sin = { AF_INET, swab(IPPORT_TELNET) }; 846000Sroot 856000Sroot int intr(), deadpeer(); 866000Sroot char *control(); 876000Sroot struct cmd *getcmd(); 886000Sroot 896000Sroot main(argc, argv) 906000Sroot int argc; 916000Sroot char *argv[]; 926000Sroot { 936000Sroot setbuf(stdin, 0); 946000Sroot setbuf(stdout, 0); 956000Sroot prompt = argv[0]; 966000Sroot if (argc != 1) { 976000Sroot if (setjmp(toplevel) != 0) 986000Sroot exit(0); 996000Sroot tn(argc, argv); 1006000Sroot } 1016000Sroot setjmp(toplevel); 1026000Sroot for (;;) 1036000Sroot command(1); 1046000Sroot } 1056000Sroot 1066000Sroot char host_name[100]; 1076000Sroot 1086000Sroot tn(argc, argv) 1096000Sroot int argc; 1106000Sroot char *argv[]; 1116000Sroot { 1126000Sroot register int c; 1136000Sroot 1146000Sroot if (connected) { 1156000Sroot printf("?Already connected to %s\n", host_name); 1166000Sroot return; 1176000Sroot } 1186000Sroot if (argc < 2) { 1196000Sroot strcpy(line, "Connect "); 1206000Sroot printf("(to) "); 1216000Sroot gets(&line[strlen(line)]); 1226000Sroot makeargv(); 1236000Sroot argc = margc; 1246000Sroot argv = margv; 1256000Sroot } 1266000Sroot if (argc > 3) { 1276000Sroot printf("usage: %s host-name [port]\n", argv[0]); 1286000Sroot return; 1296000Sroot } 1306000Sroot sin.sin_addr.s_addr = rhost(&argv[1]); 1316025Ssam if (sin.sin_addr.s_addr == (u_long)-1) { 1326000Sroot printf("%s: unknown host\n", argv[1]); 1336000Sroot return; 1346000Sroot } 1356024Ssam if (argc == 3) { 1366024Ssam sin.sin_port = atoi(argv[2]); 1376024Ssam if (sin.sin_port < 0) { 1386024Ssam printf("%s: bad port number\n", argv[2]); 1396024Ssam return; 1406024Ssam } 1416024Ssam } 1426000Sroot if ((net = socket(SOCK_STREAM, 0, 0, 0)) < 0) { 1436000Sroot perror("socket"); 1446000Sroot return; 1456000Sroot } 1466000Sroot sigset(SIGINT, intr); 1476000Sroot sigset(SIGPIPE, deadpeer); 1486000Sroot printf("Trying...\n"); 1496000Sroot if (connect(net, &sin)) { 1506000Sroot perror("connect"); 1516000Sroot sigset(SIGINT, SIG_DFL); 1526000Sroot return; 1536000Sroot } 1546000Sroot strcpy(host_name, argv[1]); 1556000Sroot connected++; 1566000Sroot call(status, "status", 0); 1576000Sroot if (setjmp(peerdied) == 0) 1586000Sroot telnet(net); 1596000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 1606000Sroot exit(1); 1616000Sroot } 1626000Sroot 1636000Sroot /* 1646000Sroot * Print status about the connection. 1656000Sroot */ 1666000Sroot /*VARARGS*/ 1676000Sroot status() 1686000Sroot { 1696000Sroot if (connected) 1706000Sroot printf("Connected to %s.\n", host_name); 1716000Sroot else 1726000Sroot printf("No connection.\n"); 1736000Sroot printf("Escape character is '%s'.\n", control(escape)); 1746000Sroot } 1756000Sroot 1766000Sroot makeargv() 1776000Sroot { 1786000Sroot register char *cp; 1796000Sroot register char **argp = margv; 1806000Sroot 1816000Sroot margc = 0; 1826000Sroot for (cp = line; *cp;) { 1836000Sroot while (isspace(*cp)) 1846000Sroot cp++; 1856000Sroot if (*cp == '\0') 1866000Sroot break; 1876000Sroot *argp++ = cp; 1886000Sroot margc += 1; 1896000Sroot while (*cp != '\0' && !isspace(*cp)) 1906000Sroot cp++; 1916000Sroot if (*cp == '\0') 1926000Sroot break; 1936000Sroot *cp++ = '\0'; 1946000Sroot } 1956000Sroot *argp++ = 0; 1966000Sroot } 1976000Sroot 1986000Sroot /*VARARGS*/ 1996000Sroot suspend() 2006000Sroot { 2016000Sroot register int save; 2026000Sroot 2036000Sroot save = mode(0); 2046000Sroot kill(0, SIGTSTP); /* get whole process group */ 2056000Sroot mode(save); 2066000Sroot } 2076000Sroot 2086000Sroot /*VARARGS*/ 2096000Sroot bye() 2106000Sroot { 2116000Sroot int how = 2; 2126000Sroot 2136000Sroot mode(0); 2146000Sroot if (connected) { 2156000Sroot ioctl(net, SIOCDONE, &how); 2166000Sroot printf("Connection closed.\n"); 2176000Sroot close(net); 2186000Sroot connected = 0; 2196000Sroot } 2206000Sroot } 2216000Sroot 2226000Sroot /*VARARGS*/ 2236000Sroot quit() 2246000Sroot { 2256000Sroot call(bye, "bye", 0); 2266000Sroot exit(0); 2276000Sroot } 2286000Sroot 2296000Sroot /* 2306000Sroot * Help command. 2316000Sroot * Call each command handler with argc == 0 and argv[0] == name. 2326000Sroot */ 2336000Sroot help(argc, argv) 2346000Sroot int argc; 2356000Sroot char *argv[]; 2366000Sroot { 2376000Sroot register struct cmd *c; 2386000Sroot 2396000Sroot if (argc == 1) { 2406000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 2416000Sroot for (c = cmdtab; c->name; c++) 2426000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 2436000Sroot return; 2446000Sroot } 2456000Sroot while (--argc > 0) { 2466000Sroot register char *arg; 2476000Sroot arg = *++argv; 2486000Sroot c = getcmd(arg); 2496000Sroot if (c == (struct cmd *)-1) 2506000Sroot printf("?Ambiguous help command %s\n", arg); 2516000Sroot else if (c == (struct cmd *)0) 2526000Sroot printf("?Invalid help command %s\n", arg); 2536000Sroot else 2546000Sroot printf("%s\n", c->help); 2556000Sroot } 2566000Sroot } 2576000Sroot 2586000Sroot /* 2596000Sroot * Call routine with argc, argv set from args (terminated by 0). 2606000Sroot * VARARGS2 2616000Sroot */ 2626000Sroot call(routine, args) 2636000Sroot int (*routine)(); 2646000Sroot int args; 2656000Sroot { 2666000Sroot register int *argp; 2676000Sroot register int argc; 2686000Sroot 2696000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 2706000Sroot ; 2716000Sroot (*routine)(argc, &args); 2726000Sroot } 2736000Sroot 2746000Sroot mode(f) 2756000Sroot register int f; 2766000Sroot { 2776000Sroot register int old; 2786000Sroot struct sgttyb stbuf; 2796000Sroot static int ttymode = 0; 2806000Sroot int onoff; 2816000Sroot 2826000Sroot ioctl(fileno(stdin), TIOCGETP, &stbuf); 2836000Sroot old = ttymode; 2846000Sroot ttymode = f; 2856000Sroot switch (f) { 2866000Sroot case 0: 2876000Sroot stbuf.sg_flags &= ~RAW; 2886000Sroot stbuf.sg_flags |= ECHO|CRMOD; 2896000Sroot onoff = 0; 2906000Sroot break; 2916000Sroot 2926000Sroot case 1: 2936000Sroot stbuf.sg_flags |= RAW; 2946000Sroot stbuf.sg_flags &= ~(ECHO|CRMOD); 2956000Sroot onoff = 1; 2966000Sroot break; 2976000Sroot 2986000Sroot case 2: 2996000Sroot stbuf.sg_flags |= RAW; 3006000Sroot stbuf.sg_flags |= ECHO|CRMOD; 3016000Sroot onoff = 1; 3026000Sroot } 3036000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 3046000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 3056000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 3066000Sroot return (old); 3076000Sroot } 3086000Sroot 3096000Sroot char sibuf[BUFSIZ], *sbp; 3106000Sroot char tibuf[BUFSIZ], *tbp; 3116000Sroot int scc, tcc; 3126000Sroot 3136000Sroot /* 3146000Sroot * Select from tty and network... 3156000Sroot */ 3166000Sroot telnet(s) 3176000Sroot int s; 3186000Sroot { 3196000Sroot register int c; 3206000Sroot int tin = fileno(stdin), tout = fileno(stdout); 3216000Sroot int on = 1; 3226000Sroot 3236000Sroot mode(1); 3246024Ssam if (showoptions) 3256024Ssam printoption("<--", doopt, TELOPT_ECHO); 3266000Sroot sprintf(nfrontp, doopt, TELOPT_ECHO); 3276000Sroot nfrontp += sizeof(doopt) - 2; 3286024Ssam if (showoptions) 3296024Ssam printoption("<--", doopt, TELOPT_SGA); 3306000Sroot sprintf(nfrontp, doopt, TELOPT_SGA); 3316000Sroot nfrontp += sizeof(doopt) - 2; 3326024Ssam if (showoptions) 3336024Ssam printoption("<--", will, TELOPT_SGA); 3346000Sroot sprintf(nfrontp, will, TELOPT_SGA); 3356000Sroot nfrontp += sizeof(doopt) - 2; 3366000Sroot ioctl(s, FIONBIO, &on); 3376000Sroot for (;;) { 3386000Sroot int ibits = 0, obits = 0; 3396000Sroot 3406000Sroot if (nfrontp - nbackp) 3416000Sroot obits |= (1 << s); 3426000Sroot else 3436000Sroot ibits |= (1 << tin); 3446000Sroot if (tfrontp - tbackp) 3456000Sroot obits |= (1 << tout); 3466000Sroot else 3476000Sroot ibits |= (1 << s); 3486000Sroot if (scc < 0 && tcc < 0) 3496000Sroot break; 3506000Sroot select(32, &ibits, &obits, INFINITY); 3516000Sroot if (ibits == 0 && obits == 0) { 3526000Sroot sleep(5); 3536000Sroot continue; 3546000Sroot } 3556000Sroot 3566000Sroot /* 3576000Sroot * Something to read from the network... 3586000Sroot */ 3596000Sroot if (ibits & (1 << s)) { 3606000Sroot scc = read(s, sibuf, sizeof(sibuf)); 3616000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3626000Sroot scc = 0; 3636000Sroot else { 3646000Sroot if (scc <= 0) 3656000Sroot break; 3666000Sroot sbp = sibuf; 3676000Sroot } 3686000Sroot } 3696000Sroot 3706000Sroot /* 3716000Sroot * Something to read from the tty... 3726000Sroot */ 3736000Sroot if (ibits & (1 << tin)) { 3746000Sroot tcc = read(tin, tibuf, sizeof(tibuf)); 3756000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 3766000Sroot tcc = 0; 3776000Sroot else { 3786000Sroot if (tcc <= 0) 3796000Sroot break; 3806000Sroot tbp = tibuf; 3816000Sroot } 3826000Sroot } 3836000Sroot 3846000Sroot while (tcc > 0) { 3856000Sroot register int c; 3866000Sroot 3876000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 3886000Sroot break; 3896000Sroot c = *tbp++ & 0377, tcc--; 3906000Sroot if (strip(c) == escape) { 3916000Sroot command(0); 3926000Sroot tcc = 0; 3936000Sroot break; 3946000Sroot } 3956000Sroot *nfrontp++ = c; 3966000Sroot } 3976000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 3986000Sroot netflush(s); 3996000Sroot if (scc > 0) 4006000Sroot telrcv(); 4016000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4026000Sroot ttyflush(tout); 4036000Sroot } 4046000Sroot mode(0); 4056000Sroot } 4066000Sroot 4076000Sroot command(top) 4086000Sroot int top; 4096000Sroot { 4106000Sroot register struct cmd *c; 4116000Sroot int oldmode, wasopen; 4126000Sroot 4136000Sroot oldmode = mode(0); 4146000Sroot if (!top) 4156000Sroot putchar('\n'); 4166000Sroot else 4176000Sroot sigset(SIGINT, SIG_DFL); 4186000Sroot for (;;) { 4196000Sroot printf("%s> ", prompt); 4206000Sroot if (gets(line) == 0) 4216000Sroot break; 4226000Sroot if (line[0] == 0) 4236000Sroot break; 4246000Sroot makeargv(); 4256000Sroot c = getcmd(margv[0]); 4266000Sroot if (c == (struct cmd *)-1) { 4276000Sroot printf("?Ambiguous command\n"); 4286000Sroot continue; 4296000Sroot } 4306000Sroot if (c == 0) { 4316000Sroot printf("?Invalid command\n"); 4326000Sroot continue; 4336000Sroot } 4346000Sroot (*c->handler)(margc, margv); 4356000Sroot if (c->handler != help) 4366000Sroot break; 4376000Sroot } 4386000Sroot if (!top) { 4396000Sroot if (!connected) 4406000Sroot longjmp(toplevel, 1); 4416000Sroot mode(oldmode); 4426000Sroot } 4436000Sroot } 4446000Sroot 4456000Sroot /* 4466000Sroot * Telnet receiver states for fsm 4476000Sroot */ 4486000Sroot #define TS_DATA 0 4496000Sroot #define TS_IAC 1 4506000Sroot #define TS_WILL 2 4516000Sroot #define TS_WONT 3 4526000Sroot #define TS_DO 4 4536000Sroot #define TS_DONT 5 4546000Sroot 4556000Sroot telrcv() 4566000Sroot { 4576000Sroot register int c; 4586000Sroot static int state = TS_DATA; 4596000Sroot 4606000Sroot while (scc > 0) { 4616000Sroot c = *sbp++ & 0377, scc--; 4626000Sroot switch (state) { 4636000Sroot 4646000Sroot case TS_DATA: 4656000Sroot if (c == IAC) 4666000Sroot state = TS_IAC; 4676000Sroot else 4686000Sroot *tfrontp++ = c; 4696000Sroot continue; 4706000Sroot 4716000Sroot case TS_IAC: 4726000Sroot switch (c) { 4736000Sroot 4746000Sroot case WILL: 4756000Sroot state = TS_WILL; 4766000Sroot continue; 4776000Sroot 4786000Sroot case WONT: 4796000Sroot state = TS_WONT; 4806000Sroot continue; 4816000Sroot 4826000Sroot case DO: 4836000Sroot state = TS_DO; 4846000Sroot continue; 4856000Sroot 4866000Sroot case DONT: 4876000Sroot state = TS_DONT; 4886000Sroot continue; 4896000Sroot 4906000Sroot case DM: 4916000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 4926000Sroot break; 4936000Sroot 4946000Sroot case NOP: 4956000Sroot case GA: 4966000Sroot break; 4976000Sroot 4986000Sroot default: 4996000Sroot break; 5006000Sroot } 5016000Sroot state = TS_DATA; 5026000Sroot continue; 5036000Sroot 5046000Sroot case TS_WILL: 5056024Ssam if (showoptions) 506*6293Sroot printoption("-->", will, c, !hisopts[c]); 5076000Sroot if (!hisopts[c]) 5086000Sroot willoption(c); 5096000Sroot state = TS_DATA; 5106000Sroot continue; 5116000Sroot 5126000Sroot case TS_WONT: 5136024Ssam if (showoptions) 514*6293Sroot printoption("-->", wont, c, hisopts[c]); 5156000Sroot if (hisopts[c]) 5166000Sroot wontoption(c); 5176000Sroot state = TS_DATA; 5186000Sroot continue; 5196000Sroot 5206000Sroot case TS_DO: 5216024Ssam if (showoptions) 522*6293Sroot printoption("-->", doopt, c, !myopts[c]); 5236000Sroot if (!myopts[c]) 5246000Sroot dooption(c); 5256000Sroot state = TS_DATA; 5266000Sroot continue; 5276000Sroot 5286000Sroot case TS_DONT: 5296024Ssam if (showoptions) 530*6293Sroot printoption("-->", dont, c, myopts[c]); 5316000Sroot if (myopts[c]) { 5326000Sroot myopts[c] = 0; 5336000Sroot sprintf(nfrontp, wont, c); 5346000Sroot nfrontp += sizeof(wont) - 2; 5356024Ssam if (showoptions) 5366024Ssam printoption("<--", wont, c); 5376000Sroot } 5386000Sroot state = TS_DATA; 5396000Sroot continue; 5406000Sroot } 5416000Sroot } 5426000Sroot } 5436000Sroot 5446000Sroot willoption(option) 5456000Sroot int option; 5466000Sroot { 5476000Sroot char *fmt; 5486000Sroot 5496000Sroot switch (option) { 5506000Sroot 5516000Sroot case TELOPT_ECHO: 5526000Sroot mode(1); 5536000Sroot 5546000Sroot case TELOPT_SGA: 5556000Sroot hisopts[option] = 1; 5566000Sroot fmt = doopt; 5576000Sroot break; 5586000Sroot 5596000Sroot case TELOPT_TM: 5606000Sroot fmt = dont; 5616000Sroot break; 5626000Sroot 5636000Sroot default: 5646000Sroot fmt = dont; 5656000Sroot break; 5666000Sroot } 5676024Ssam sprintf(nfrontp, fmt, option); 5686000Sroot nfrontp += sizeof(dont) - 2; 5696024Ssam if (showoptions) 5706024Ssam printoption("<--", fmt, option); 5716000Sroot } 5726000Sroot 5736000Sroot wontoption(option) 5746000Sroot int option; 5756000Sroot { 5766000Sroot char *fmt; 5776000Sroot 5786000Sroot switch (option) { 5796000Sroot 5806000Sroot case TELOPT_ECHO: 5816000Sroot mode(2); 5826000Sroot 5836000Sroot case TELOPT_SGA: 5846000Sroot hisopts[option] = 0; 5856000Sroot fmt = dont; 5866000Sroot break; 5876000Sroot 5886000Sroot default: 5896000Sroot fmt = dont; 5906000Sroot } 5916000Sroot sprintf(nfrontp, fmt, option); 5926000Sroot nfrontp += sizeof(doopt) - 2; 5936024Ssam if (showoptions) 5946024Ssam printoption("<--", fmt, option); 5956000Sroot } 5966000Sroot 5976000Sroot dooption(option) 5986000Sroot int option; 5996000Sroot { 6006000Sroot char *fmt; 6016000Sroot 6026000Sroot switch (option) { 6036000Sroot 6046000Sroot case TELOPT_TM: 6056000Sroot fmt = wont; 6066000Sroot break; 6076000Sroot 6086000Sroot case TELOPT_SGA: 6096000Sroot fmt = will; 6106000Sroot break; 6116000Sroot 6126000Sroot default: 6136000Sroot fmt = wont; 6146000Sroot break; 6156000Sroot } 6166000Sroot sprintf(nfrontp, fmt, option); 6176000Sroot nfrontp += sizeof(doopt) - 2; 6186024Ssam if (showoptions) 6196024Ssam printoption("<--", fmt, option); 6206000Sroot } 6216000Sroot 6226000Sroot /* 6236000Sroot * Set the escape character. 6246000Sroot */ 6256000Sroot setescape(argc, argv) 6266000Sroot int argc; 6276000Sroot char *argv[]; 6286000Sroot { 6296000Sroot register char *arg; 6306000Sroot char buf[50]; 6316000Sroot 6326000Sroot if (argc > 2) 6336000Sroot arg = argv[1]; 6346000Sroot else { 6356000Sroot printf("new escape character: "); 6366000Sroot gets(buf); 6376000Sroot arg = buf; 6386000Sroot } 6396000Sroot if (arg[0] != '\0') 6406000Sroot escape = arg[0]; 6416000Sroot printf("Escape character is '%s'.\n", control(escape)); 6426000Sroot } 6436000Sroot 6446024Ssam /*VARARGS*/ 6456024Ssam setoptions() 6466024Ssam { 6476024Ssam showoptions = !showoptions; 6486024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 6496024Ssam } 6506024Ssam 6516000Sroot /* 6526000Sroot * Construct a control character sequence 6536000Sroot * for a special character. 6546000Sroot */ 6556000Sroot char * 6566000Sroot control(c) 6576000Sroot register int c; 6586000Sroot { 6596000Sroot static char buf[3]; 6606000Sroot 6616000Sroot if (c == 0177) 6626000Sroot return ("^?"); 6636000Sroot if (c >= 040) { 6646000Sroot buf[0] = c; 6656000Sroot buf[1] = 0; 6666000Sroot } else { 6676000Sroot buf[0] = '^'; 6686000Sroot buf[1] = '@'+c; 6696000Sroot buf[2] = 0; 6706000Sroot } 6716000Sroot return (buf); 6726000Sroot } 6736000Sroot 6746000Sroot struct cmd * 6756000Sroot getcmd(name) 6766000Sroot register char *name; 6776000Sroot { 6786000Sroot register char *p, *q; 6796000Sroot register struct cmd *c, *found; 6806000Sroot register int nmatches, longest; 6816000Sroot 6826000Sroot longest = 0; 6836000Sroot nmatches = 0; 6846000Sroot found = 0; 6856000Sroot for (c = cmdtab; p = c->name; c++) { 6866000Sroot for (q = name; *q == *p++; q++) 6876000Sroot if (*q == 0) /* exact match? */ 6886000Sroot return (c); 6896000Sroot if (!*q) { /* the name was a prefix */ 6906000Sroot if (q - name > longest) { 6916000Sroot longest = q - name; 6926000Sroot nmatches = 1; 6936000Sroot found = c; 6946000Sroot } else if (q - name == longest) 6956000Sroot nmatches++; 6966000Sroot } 6976000Sroot } 6986000Sroot if (nmatches > 1) 6996000Sroot return ((struct cmd *)-1); 7006000Sroot return (found); 7016000Sroot } 7026000Sroot 7036000Sroot deadpeer() 7046000Sroot { 7056000Sroot sigset(SIGPIPE, deadpeer); 7066000Sroot mode(0); 7076000Sroot longjmp(peerdied, -1); 7086000Sroot } 7096000Sroot 7106000Sroot intr() 7116000Sroot { 7126000Sroot sigset(SIGINT, intr); 7136000Sroot mode(0); 7146000Sroot longjmp(toplevel, -1); 7156000Sroot } 7166000Sroot 7176000Sroot ttyflush(fd) 7186000Sroot { 7196000Sroot int n; 7206000Sroot 7216000Sroot if ((n = tfrontp - tbackp) > 0) 7226000Sroot n = write(fd, tbackp, n); 7236000Sroot if (n < 0 && errno == EWOULDBLOCK) 7246000Sroot n = 0; 7256000Sroot tbackp += n; 7266000Sroot if (tbackp == tfrontp) 7276000Sroot tbackp = tfrontp = ttyobuf; 7286000Sroot } 7296000Sroot 7306000Sroot netflush(fd) 7316000Sroot { 7326000Sroot int n; 7336000Sroot 7346000Sroot if ((n = nfrontp - nbackp) > 0) 7356000Sroot n = write(fd, nbackp, n); 7366000Sroot if (n < 0 && errno == EWOULDBLOCK) 7376000Sroot n = 0; 7386000Sroot nbackp += n; 7396000Sroot if (nbackp == nfrontp) 7406000Sroot nbackp = nfrontp = netobuf; 7416000Sroot } 7426024Ssam 743*6293Sroot /*VARARGS*/ 744*6293Sroot printoption(direction, fmt, option, what) 7456024Ssam char *direction, *fmt; 746*6293Sroot int option, what; 7476024Ssam { 7486024Ssam printf("%s ", direction); 7496024Ssam if (fmt == doopt) 7506024Ssam fmt = "do"; 7516024Ssam else if (fmt == dont) 7526024Ssam fmt = "dont"; 7536024Ssam else if (fmt == will) 7546024Ssam fmt = "will"; 7556024Ssam else if (fmt == wont) 7566024Ssam fmt = "wont"; 7576024Ssam else 7586024Ssam fmt = "???"; 7596024Ssam if (option < TELOPT_SUPDUP) 760*6293Sroot printf("%s %s", fmt, telopts[option]); 7616024Ssam else 762*6293Sroot printf("%s %d", fmt, option); 763*6293Sroot if (*direction == '<') { 764*6293Sroot printf("\r\n"); 765*6293Sroot return; 766*6293Sroot } 767*6293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 7686024Ssam } 769