1*6389Ssam static char sccsid[] = "@(#)telnet.c 4.6 (Berkeley) 03/31/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; 328*6389Ssam hisopts[TELOPT_ECHO] = 1; 3296024Ssam if (showoptions) 3306024Ssam printoption("<--", doopt, TELOPT_SGA); 3316000Sroot sprintf(nfrontp, doopt, TELOPT_SGA); 3326000Sroot nfrontp += sizeof(doopt) - 2; 333*6389Ssam hisopts[TELOPT_SGA] = 1; 3346024Ssam if (showoptions) 3356024Ssam printoption("<--", will, TELOPT_SGA); 3366000Sroot sprintf(nfrontp, will, TELOPT_SGA); 3376000Sroot nfrontp += sizeof(doopt) - 2; 338*6389Ssam myopts[TELOPT_SGA] = 1; 3396000Sroot ioctl(s, FIONBIO, &on); 3406000Sroot for (;;) { 3416000Sroot int ibits = 0, obits = 0; 3426000Sroot 3436000Sroot if (nfrontp - nbackp) 3446000Sroot obits |= (1 << s); 3456000Sroot else 3466000Sroot ibits |= (1 << tin); 3476000Sroot if (tfrontp - tbackp) 3486000Sroot obits |= (1 << tout); 3496000Sroot else 3506000Sroot ibits |= (1 << s); 3516000Sroot if (scc < 0 && tcc < 0) 3526000Sroot break; 3536000Sroot select(32, &ibits, &obits, INFINITY); 3546000Sroot if (ibits == 0 && obits == 0) { 3556000Sroot sleep(5); 3566000Sroot continue; 3576000Sroot } 3586000Sroot 3596000Sroot /* 3606000Sroot * Something to read from the network... 3616000Sroot */ 3626000Sroot if (ibits & (1 << s)) { 3636000Sroot scc = read(s, sibuf, sizeof(sibuf)); 3646000Sroot if (scc < 0 && errno == EWOULDBLOCK) 3656000Sroot scc = 0; 3666000Sroot else { 3676000Sroot if (scc <= 0) 3686000Sroot break; 3696000Sroot sbp = sibuf; 3706000Sroot } 3716000Sroot } 3726000Sroot 3736000Sroot /* 3746000Sroot * Something to read from the tty... 3756000Sroot */ 3766000Sroot if (ibits & (1 << tin)) { 3776000Sroot tcc = read(tin, tibuf, sizeof(tibuf)); 3786000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 3796000Sroot tcc = 0; 3806000Sroot else { 3816000Sroot if (tcc <= 0) 3826000Sroot break; 3836000Sroot tbp = tibuf; 3846000Sroot } 3856000Sroot } 3866000Sroot 3876000Sroot while (tcc > 0) { 3886000Sroot register int c; 3896000Sroot 3906000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 3916000Sroot break; 3926000Sroot c = *tbp++ & 0377, tcc--; 3936000Sroot if (strip(c) == escape) { 3946000Sroot command(0); 3956000Sroot tcc = 0; 3966000Sroot break; 3976000Sroot } 3986000Sroot *nfrontp++ = c; 3996000Sroot } 4006000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 4016000Sroot netflush(s); 4026000Sroot if (scc > 0) 4036000Sroot telrcv(); 4046000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 4056000Sroot ttyflush(tout); 4066000Sroot } 4076000Sroot mode(0); 4086000Sroot } 4096000Sroot 4106000Sroot command(top) 4116000Sroot int top; 4126000Sroot { 4136000Sroot register struct cmd *c; 4146000Sroot int oldmode, wasopen; 4156000Sroot 4166000Sroot oldmode = mode(0); 4176000Sroot if (!top) 4186000Sroot putchar('\n'); 4196000Sroot else 4206000Sroot sigset(SIGINT, SIG_DFL); 4216000Sroot for (;;) { 4226000Sroot printf("%s> ", prompt); 4236000Sroot if (gets(line) == 0) 4246000Sroot break; 4256000Sroot if (line[0] == 0) 4266000Sroot break; 4276000Sroot makeargv(); 4286000Sroot c = getcmd(margv[0]); 4296000Sroot if (c == (struct cmd *)-1) { 4306000Sroot printf("?Ambiguous command\n"); 4316000Sroot continue; 4326000Sroot } 4336000Sroot if (c == 0) { 4346000Sroot printf("?Invalid command\n"); 4356000Sroot continue; 4366000Sroot } 4376000Sroot (*c->handler)(margc, margv); 4386000Sroot if (c->handler != help) 4396000Sroot break; 4406000Sroot } 4416000Sroot if (!top) { 4426000Sroot if (!connected) 4436000Sroot longjmp(toplevel, 1); 4446000Sroot mode(oldmode); 4456000Sroot } 4466000Sroot } 4476000Sroot 4486000Sroot /* 4496000Sroot * Telnet receiver states for fsm 4506000Sroot */ 4516000Sroot #define TS_DATA 0 4526000Sroot #define TS_IAC 1 4536000Sroot #define TS_WILL 2 4546000Sroot #define TS_WONT 3 4556000Sroot #define TS_DO 4 4566000Sroot #define TS_DONT 5 4576000Sroot 4586000Sroot telrcv() 4596000Sroot { 4606000Sroot register int c; 4616000Sroot static int state = TS_DATA; 4626000Sroot 4636000Sroot while (scc > 0) { 4646000Sroot c = *sbp++ & 0377, scc--; 4656000Sroot switch (state) { 4666000Sroot 4676000Sroot case TS_DATA: 4686000Sroot if (c == IAC) 4696000Sroot state = TS_IAC; 4706000Sroot else 4716000Sroot *tfrontp++ = c; 4726000Sroot continue; 4736000Sroot 4746000Sroot case TS_IAC: 4756000Sroot switch (c) { 4766000Sroot 4776000Sroot case WILL: 4786000Sroot state = TS_WILL; 4796000Sroot continue; 4806000Sroot 4816000Sroot case WONT: 4826000Sroot state = TS_WONT; 4836000Sroot continue; 4846000Sroot 4856000Sroot case DO: 4866000Sroot state = TS_DO; 4876000Sroot continue; 4886000Sroot 4896000Sroot case DONT: 4906000Sroot state = TS_DONT; 4916000Sroot continue; 4926000Sroot 4936000Sroot case DM: 4946000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 4956000Sroot break; 4966000Sroot 4976000Sroot case NOP: 4986000Sroot case GA: 4996000Sroot break; 5006000Sroot 5016000Sroot default: 5026000Sroot break; 5036000Sroot } 5046000Sroot state = TS_DATA; 5056000Sroot continue; 5066000Sroot 5076000Sroot case TS_WILL: 5086024Ssam if (showoptions) 5096293Sroot printoption("-->", will, c, !hisopts[c]); 5106000Sroot if (!hisopts[c]) 5116000Sroot willoption(c); 5126000Sroot state = TS_DATA; 5136000Sroot continue; 5146000Sroot 5156000Sroot case TS_WONT: 5166024Ssam if (showoptions) 5176293Sroot printoption("-->", wont, c, hisopts[c]); 5186000Sroot if (hisopts[c]) 5196000Sroot wontoption(c); 5206000Sroot state = TS_DATA; 5216000Sroot continue; 5226000Sroot 5236000Sroot case TS_DO: 5246024Ssam if (showoptions) 5256293Sroot printoption("-->", doopt, c, !myopts[c]); 5266000Sroot if (!myopts[c]) 5276000Sroot dooption(c); 5286000Sroot state = TS_DATA; 5296000Sroot continue; 5306000Sroot 5316000Sroot case TS_DONT: 5326024Ssam if (showoptions) 5336293Sroot printoption("-->", dont, c, myopts[c]); 5346000Sroot if (myopts[c]) { 5356000Sroot myopts[c] = 0; 5366000Sroot sprintf(nfrontp, wont, c); 5376000Sroot nfrontp += sizeof(wont) - 2; 5386024Ssam if (showoptions) 5396024Ssam printoption("<--", wont, c); 5406000Sroot } 5416000Sroot state = TS_DATA; 5426000Sroot continue; 5436000Sroot } 5446000Sroot } 5456000Sroot } 5466000Sroot 5476000Sroot willoption(option) 5486000Sroot int option; 5496000Sroot { 5506000Sroot char *fmt; 5516000Sroot 5526000Sroot switch (option) { 5536000Sroot 5546000Sroot case TELOPT_ECHO: 5556000Sroot mode(1); 5566000Sroot 5576000Sroot case TELOPT_SGA: 5586000Sroot hisopts[option] = 1; 5596000Sroot fmt = doopt; 5606000Sroot break; 5616000Sroot 5626000Sroot case TELOPT_TM: 5636000Sroot fmt = dont; 5646000Sroot break; 5656000Sroot 5666000Sroot default: 5676000Sroot fmt = dont; 5686000Sroot break; 5696000Sroot } 5706024Ssam sprintf(nfrontp, fmt, option); 5716000Sroot nfrontp += sizeof(dont) - 2; 5726024Ssam if (showoptions) 5736024Ssam printoption("<--", fmt, option); 5746000Sroot } 5756000Sroot 5766000Sroot wontoption(option) 5776000Sroot int option; 5786000Sroot { 5796000Sroot char *fmt; 5806000Sroot 5816000Sroot switch (option) { 5826000Sroot 5836000Sroot case TELOPT_ECHO: 5846000Sroot mode(2); 5856000Sroot 5866000Sroot case TELOPT_SGA: 5876000Sroot hisopts[option] = 0; 5886000Sroot fmt = dont; 5896000Sroot break; 5906000Sroot 5916000Sroot default: 5926000Sroot fmt = dont; 5936000Sroot } 5946000Sroot sprintf(nfrontp, fmt, option); 5956000Sroot nfrontp += sizeof(doopt) - 2; 5966024Ssam if (showoptions) 5976024Ssam printoption("<--", fmt, option); 5986000Sroot } 5996000Sroot 6006000Sroot dooption(option) 6016000Sroot int option; 6026000Sroot { 6036000Sroot char *fmt; 6046000Sroot 6056000Sroot switch (option) { 6066000Sroot 6076000Sroot case TELOPT_TM: 6086000Sroot fmt = wont; 6096000Sroot break; 6106000Sroot 6116000Sroot case TELOPT_SGA: 6126000Sroot fmt = will; 6136000Sroot break; 6146000Sroot 6156000Sroot default: 6166000Sroot fmt = wont; 6176000Sroot break; 6186000Sroot } 6196000Sroot sprintf(nfrontp, fmt, option); 6206000Sroot nfrontp += sizeof(doopt) - 2; 6216024Ssam if (showoptions) 6226024Ssam printoption("<--", fmt, option); 6236000Sroot } 6246000Sroot 6256000Sroot /* 6266000Sroot * Set the escape character. 6276000Sroot */ 6286000Sroot setescape(argc, argv) 6296000Sroot int argc; 6306000Sroot char *argv[]; 6316000Sroot { 6326000Sroot register char *arg; 6336000Sroot char buf[50]; 6346000Sroot 6356000Sroot if (argc > 2) 6366000Sroot arg = argv[1]; 6376000Sroot else { 6386000Sroot printf("new escape character: "); 6396000Sroot gets(buf); 6406000Sroot arg = buf; 6416000Sroot } 6426000Sroot if (arg[0] != '\0') 6436000Sroot escape = arg[0]; 6446000Sroot printf("Escape character is '%s'.\n", control(escape)); 6456000Sroot } 6466000Sroot 6476024Ssam /*VARARGS*/ 6486024Ssam setoptions() 6496024Ssam { 6506024Ssam showoptions = !showoptions; 6516024Ssam printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); 6526024Ssam } 6536024Ssam 6546000Sroot /* 6556000Sroot * Construct a control character sequence 6566000Sroot * for a special character. 6576000Sroot */ 6586000Sroot char * 6596000Sroot control(c) 6606000Sroot register int c; 6616000Sroot { 6626000Sroot static char buf[3]; 6636000Sroot 6646000Sroot if (c == 0177) 6656000Sroot return ("^?"); 6666000Sroot if (c >= 040) { 6676000Sroot buf[0] = c; 6686000Sroot buf[1] = 0; 6696000Sroot } else { 6706000Sroot buf[0] = '^'; 6716000Sroot buf[1] = '@'+c; 6726000Sroot buf[2] = 0; 6736000Sroot } 6746000Sroot return (buf); 6756000Sroot } 6766000Sroot 6776000Sroot struct cmd * 6786000Sroot getcmd(name) 6796000Sroot register char *name; 6806000Sroot { 6816000Sroot register char *p, *q; 6826000Sroot register struct cmd *c, *found; 6836000Sroot register int nmatches, longest; 6846000Sroot 6856000Sroot longest = 0; 6866000Sroot nmatches = 0; 6876000Sroot found = 0; 6886000Sroot for (c = cmdtab; p = c->name; c++) { 6896000Sroot for (q = name; *q == *p++; q++) 6906000Sroot if (*q == 0) /* exact match? */ 6916000Sroot return (c); 6926000Sroot if (!*q) { /* the name was a prefix */ 6936000Sroot if (q - name > longest) { 6946000Sroot longest = q - name; 6956000Sroot nmatches = 1; 6966000Sroot found = c; 6976000Sroot } else if (q - name == longest) 6986000Sroot nmatches++; 6996000Sroot } 7006000Sroot } 7016000Sroot if (nmatches > 1) 7026000Sroot return ((struct cmd *)-1); 7036000Sroot return (found); 7046000Sroot } 7056000Sroot 7066000Sroot deadpeer() 7076000Sroot { 7086000Sroot sigset(SIGPIPE, deadpeer); 7096000Sroot mode(0); 7106000Sroot longjmp(peerdied, -1); 7116000Sroot } 7126000Sroot 7136000Sroot intr() 7146000Sroot { 7156000Sroot sigset(SIGINT, intr); 7166000Sroot mode(0); 7176000Sroot longjmp(toplevel, -1); 7186000Sroot } 7196000Sroot 7206000Sroot ttyflush(fd) 7216000Sroot { 7226000Sroot int n; 7236000Sroot 7246000Sroot if ((n = tfrontp - tbackp) > 0) 7256000Sroot n = write(fd, tbackp, n); 7266000Sroot if (n < 0 && errno == EWOULDBLOCK) 7276000Sroot n = 0; 7286000Sroot tbackp += n; 7296000Sroot if (tbackp == tfrontp) 7306000Sroot tbackp = tfrontp = ttyobuf; 7316000Sroot } 7326000Sroot 7336000Sroot netflush(fd) 7346000Sroot { 7356000Sroot int n; 7366000Sroot 7376000Sroot if ((n = nfrontp - nbackp) > 0) 7386000Sroot n = write(fd, nbackp, n); 7396000Sroot if (n < 0 && errno == EWOULDBLOCK) 7406000Sroot n = 0; 7416000Sroot nbackp += n; 7426000Sroot if (nbackp == nfrontp) 7436000Sroot nbackp = nfrontp = netobuf; 7446000Sroot } 7456024Ssam 7466293Sroot /*VARARGS*/ 7476293Sroot printoption(direction, fmt, option, what) 7486024Ssam char *direction, *fmt; 7496293Sroot int option, what; 7506024Ssam { 7516024Ssam printf("%s ", direction); 7526024Ssam if (fmt == doopt) 7536024Ssam fmt = "do"; 7546024Ssam else if (fmt == dont) 7556024Ssam fmt = "dont"; 7566024Ssam else if (fmt == will) 7576024Ssam fmt = "will"; 7586024Ssam else if (fmt == wont) 7596024Ssam fmt = "wont"; 7606024Ssam else 7616024Ssam fmt = "???"; 7626024Ssam if (option < TELOPT_SUPDUP) 7636293Sroot printf("%s %s", fmt, telopts[option]); 7646024Ssam else 7656293Sroot printf("%s %d", fmt, option); 7666293Sroot if (*direction == '<') { 7676293Sroot printf("\r\n"); 7686293Sroot return; 7696293Sroot } 7706293Sroot printf(" (%s)\r\n", what ? "reply" : "don't reply"); 7716024Ssam } 772